前言

开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼。

姿势

学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复制粘贴一把撸,问题是你想问不想问为什么!

传递

用户登录

前端代码:

  1. var param = {
  2. "username": "admin",
  3. "password": "admin"
  4. }
  5. $.ajax({
  6. url: "/sys/login",
  7. data: param,
  8. type: "post",
  9. dataType: "json",
  10. success: function(data) {
  11. }
  12. });

后端代码:

  1. @RestController
  2. @RequestMapping("/sys")
  3. public class LoginController {
  4. private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
  5. /**
  6. * 登录
  7. */
  8. @PostMapping("/login")
  9. public Result login(String username, String password){
  10. logger.info("用户登录"+username);
  11. //业务逻辑
  12. return Result.ok("登录成功");
  13. }
  14. }

当然,你也可以这么实现,@RequestParam(value="username", required=true)required 默认为 true,如果前台不传递此参数,后台会报错。如果设置为 false,如果不传,默认为 null

  1. /**
  2. * 登录
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("/login")
  6. public Result login(@RequestParam(value="username", required=true) String username,
  7. @RequestParam(value="password", required=true) String password){
  8. logger.info("用户登录"+username);
  9. //业务逻辑
  10. return Result.ok("登录成功");
  11. }

用户注册

前端代码,提交方式与登录基本保持一致。

后端代码:

用一个对象来接收前台参数,一般后端有对应的实体类。

  1. /**
  2. * 注册
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("/register")
  6. public Result register(SysUser user){
  7. logger.info("{},用户注册",user.getUsername());
  8. //业务逻辑
  9. return Result.ok("注册成功");
  10. }

多参数无实体一

前端代码:

  1. var param = {
  2. "title": "爪哇笔记",
  3. "content": "一个有趣的公众号",
  4. "author": "小柒2012"
  5. }
  6. param = JSON.stringify(param);
  7. $.ajax({
  8. url: "/sys/multiParameter",
  9. data: param,
  10. type: "post",
  11. contentType: "application/json",
  12. dataType: "json",
  13. success: function(data) {
  14. }
  15. });

后端实现:

  1. /**
  2. * 多参数
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("/multiParameter")
  6. public Result register(@RequestBody Map<String,Object> map){
  7. logger.info("多参数传递:{},{}",map.get("title"),map.get("content"));
  8. //业务逻辑
  9. return Result.ok("接收多参数成功");
  10. }

多参数无实体二

前端代码:

  1. var param = {
  2. "title": "爪哇笔记",
  3. "content": "一个有趣的公众号",
  4. "author": "小柒2012"
  5. }
  6. $.ajax({
  7. url: "/sys/multiParameter",
  8. data: param,
  9. type: "post",
  10. dataType: "json",
  11. success: function(data) {
  12. }
  13. });

后端实现:

  1. /**
  2. * 多参数
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("/multiParameter")
  6. public Result register(@RequestParam Map<String,Object> map){
  7. logger.info("多参数传递:{},{}",map.get("title"),map.get("content"));
  8. //业务逻辑
  9. return Result.ok("接收多参数成功");
  10. }

传递数组

前端代码:

  1. var param = {
  2. "ids": [1, 2, 3]
  3. }
  4. $.ajax({
  5. url: "/sys/array",
  6. data: param,
  7. type: "post",
  8. dataType: "json",
  9. success: function(data) {
  10. }
  11. });

后端实现:

  1. /**
  2. * 数组
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("array")
  6. public Result array(@RequestParam(value = "ids[]") Integer[] ids) {
  7. logger.info("数据{}", Arrays.asList(ids));
  8. //业务逻辑
  9. return Result.ok();
  10. }

传递集合

前端代码与传递数组保持一致。

后端实现:

  1. /**
  2. * 集合
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("array")
  6. public Result array(@RequestParam(value = "ids[]") List<Integer> ids) {
  7. logger.info("数据{}", ids.toString());
  8. //业务逻辑
  9. return Result.ok();
  10. }

传递集合实体对象

比如,后端想接收一个实体对象集合 List<SysUser>

前端代码:

  1. var list = [];
  2. list.push({
  3. "username": "小柒2012",
  4. "mobile": "17762288888"
  5. });
  6. list.push({
  7. "username": "小柒2013",
  8. "mobile": "17762289999"
  9. });
  10. $.ajax({
  11. url: "/sys/listUser",
  12. data: JSON.stringify(list),
  13. type: "post",
  14. contentType: "application/json",
  15. dataType: "json",
  16. success: function(data) {
  17. }
  18. });

后端代码:

  1. /**
  2. * 爪哇笔记
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("listUser")
  6. public Result listUser(@RequestBody List<SysUser> list) {
  7. logger.info("数据{}", list.size());
  8. list.forEach(user->{
  9. //输出实体对象
  10. System.out.println(user.getUsername());
  11. });
  12. //业务逻辑
  13. return Result.ok();
  14. }

传递集合实体对象一对多

比如,一个用户有多个角色 List<SysRole> roleList

前端代码:

  1. var roleList = [];
  2. roleList.push({
  3. "roleSign": "admin",
  4. "roleName": "管理员"
  5. });
  6. roleList.push({
  7. "roleSign": "user",
  8. "roleName": "普通用户"
  9. });
  10. var list = [];
  11. var user = {
  12. "username": "小柒2012",
  13. "mobile": "17762288888"
  14. };
  15. user.roleList = roleList;
  16. list.push(user);
  17. $.ajax({
  18. url: "/sys/listUserRole",
  19. data: JSON.stringify(list),
  20. type: "post",
  21. contentType: "application/json",
  22. dataType: "json",
  23. success: function(data) {
  24. }
  25. });

后端实现:

  1. /**
  2. * 爪哇笔记
  3. * https://blog.52itstyle.vip
  4. */
  5. @PostMapping("listUserRole")
  6. public Result listUserRole(@RequestBody List<SysUser> list) {
  7. logger.info("数据{}", list.size());
  8. list.forEach(user->{
  9. List<SysRole> roleList = user.getRoleList();
  10. roleList.forEach(role->{
  11. System.out.println(role.getRoleName());
  12. });
  13. });
  14. return Result.ok();
  15. }

炒鸡复杂

传输对象有实体,有集合,有各种类型的数据,这时候最简单的方式就是传递 Key-Value 结构的 JSON 字符串,后台 Map 类型接收,然后通过FastJsonJSON.parseObject()JSON.parseArray() 方法转化为对应的实体或者集合。

  1. String user = parseMap.get("user").toString();
  2. SysUser sysUser = JSON.parseObject(user,SysUser.class);
  3. String contractClause = parseMap.get("rules").toString();
  4. List<Rule> ruleList = JSON.parseArray(contractClause,Rule.class);

RESTful 风格

比如,访问某篇文章:

  1. /**
  2. * 爪哇笔记
  3. * https://blog.52itstyle.vip
  4. */
  5. @GetMapping("article/{id}")
  6. public void article(@PathVariable("id") String id) {
  7. logger.info("文章{}",id);
  8. //业务逻辑
  9. }

原则

记住一下几点:

  • @RequestBody 注解,必须与 contentType 类型application/json配合使用。

  • @RequestParam 注解,必须与 contentType 类型application/x-www-form-urlencoded配合使用,其为默认类型。

  • JSON.stringify() 把对象类型转换为字符串类型,一般配合 @RequestBody 注解和contentType 类型application/json使用。

扩展

在以上只涉及了两种 contentType 类型,其实还有两种常见的类型:

multipart/form-data

一般用于表单文件上传,必须让 form 的 enctype 等于这个值。

  1. <form action="/upload" method="post" enctype="multipart/form-data">
  2. <input type="text" name="description" value="爪哇笔记,一个神奇的公众号">
  3. <input type="file" name="myFile">
  4. <button type="submit">Submit</button>
  5. </form>

text/xml

做过微信支付的小伙伴一定会知道,微信就喜欢用这种方式,去年还发生过 XXE 漏洞,在解析XML文档时,解析器通过 ENTITY 扩展的功能,读取本地受保护的文件,并且使用扩展功能将受保护的文件发送到远程地址。

小结

不敢说是最完整的传参方案,但绝对敢保证是最正确的,因为所有的传参方式都经过 360° 官方检验。

SpringBoot 开发案例之参数传递的正确姿势的更多相关文章

  1. SpringBoot开发案例之多任务并行+线程池处理

    前言 前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑.当然了,优化是无止境的,前人栽树后人乘凉.作为我们开发者来说,既然站在了巨人的肩膀上,就要写出更加优化的程序 ...

  2. SpringBoot开发案例从0到1构建分布式秒杀系统

    前言 ​最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场 ...

  3. SpringBoot开发案例之打造私有云网盘

    前言 最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意.无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还 ...

  4. SpringBoot开发案例之整合Activiti工作流引擎

    前言 JBPM是目前市场上主流开源工作引擎之一,在创建者Tom Baeyens离开JBoss后,JBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过,目前官 ...

  5. SpringBoot开发案例之整合Dubbo分布式服务

    前言 在 SpringBoot 很火热的时候,阿里巴巴的分布式框架 Dubbo 不知是处于什么考虑,在停更N年之后终于进行维护了.在之前的微服务中,使用的是当当维护的版本 Dubbox,整合方式也是使 ...

  6. SpringBoot开发案例之整合Kafka实现消息队列

    前言 最近在做一款秒杀的案例,涉及到了同步锁.数据库锁.分布式锁.进程内队列以及分布式消息队列,这里对SpringBoot集成Kafka实现消息队列做一个简单的记录. Kafka简介 Kafka是由A ...

  7. SpringBoot开发案例之分布式集群共享Session

    前言 在分布式系统中,为了提升系统性能,通常会对单体项目进行拆分,分解成多个基于功能的微服务,如果有条件,可能还会对单个微服务进行水平扩展,保证服务高可用. 那么问题来了,如果使用传统管理 Sessi ...

  8. 转载-SpringBoot开发案例之整合日志管理

    转载:https://cloud.tencent.com/developer/article/1097579 有一种力量无人能抵挡,它永不言败生来倔强.有一种理想照亮了迷茫,在那写满荣耀的地方. 00 ...

  9. SpringBoot开发案例Nacos配置管理中心

    前言 在开发过程中,通常我们会配置一些参数来实现某些功能,比如是否开启某项服务,告警邮件配置等等.一般会通过硬编码.配置文件或者数据库的形式实现. 那么问题来了,如何更加优雅的实现?欢迎来到 Naco ...

随机推荐

  1. Android手机QQ文件夹解析

    注:切勿修改手机QQ文件夹,以免造成不必要的使用问题及无法修复的数据丢失] 安卓手机QQ tencent文件夹解析 QQ下载的聊天背景:tencent→MobileQQ→system_backgrou ...

  2. ReentrantLock API

    java可重入锁,简单几个小案例,测试特性. 1.尝试锁  tryLock package com.cn.cfang.ReentrantLock; import java.util.concurren ...

  3. 程序猿——踩bug之路

    从开始这就是一个新的坑,还好今天我们爬上了: 带着Ui界面的编程,最想感谢的是我的搭档乔美萱:此处我觉得需要掌声和尖叫,一路带我从走到飞: 一.结对编程项目:带UI的小初高数学学习软件 1.用户注册功 ...

  4. 对象实例Vue

    var vm = new Vue({ el:'#app', data:{}, //数据 methods:{}, //方法调用 filters:{}, //私有过滤器 directives:{}, // ...

  5. linux&shell学习系列

    1.VMware安装Centos7虚拟机 2.Linux之vim详解 3.linux后台运行的几种方式 4.linux权限管理 5.linux之用户和用户组管理详解 6.grep文本搜索工具详解 7. ...

  6. springboot + mybatis + mycat整合

    1.mycat服务 搭建mycat服务并启动,windows安装参照. 系列文章: [Mycat 简介] [Mycat 配置文件server.xml] [Mycat 配置文件schema.xml] [ ...

  7. Kubernetes 系列(五):Prometheus监控框架简介

    由于容器化和微服务的大力发展,Kubernetes基本已经统一了容器管理方案,当我们使用Kubernetes来进行容器化管理的时候,全面监控Kubernetes也就成了我们第一个需要探索的问题.我们需 ...

  8. 记录使用echarts的graph类型绘制流程图全过程(一)-x,y位置的计算

    先说下本次案例业务需求,输入2个节点,获取数据后绘制出2个节点间的路径,之前使用的是网状图,但是网状图的效果不佳,需要转换成流程图的模式: 那么如何在不修改数据的情况下,实现类似效果尼? 看了下ech ...

  9. 前端防止url输入地址直接访问页面

    首先,解决这个问题要搞明白此url是从程序内部跳转还是直接在地址栏输入的,如果是程序内部跳转,那就好办啦.方法如下: 判断用户是否登录状态,是否携带token 使用router.beforeEach注 ...

  10. 运算符 字符串 for循环

    1. 运算符 1.1赋值运算符 = += -= *= /= //= %= **= 1.2比较运算符 < > = <= == != 1.3成员运算符 in not in 1.4逻辑运算 ...