前言

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

姿势

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

传递

用户登录

前端代码:

var param = {
"username": "admin",
"password": "admin"
}
$.ajax({
url: "/sys/login",
data: param,
type: "post",
dataType: "json",
success: function(data) { }
});

后端代码:

@RestController
@RequestMapping("/sys")
public class LoginController { private static final Logger logger = LoggerFactory.getLogger(LoginController.class); /**
* 登录
*/
@PostMapping("/login")
public Result login(String username, String password){
logger.info("用户登录"+username);
//业务逻辑
return Result.ok("登录成功");
}
}

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

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

用户注册

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

后端代码:

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

/**
* 注册
* https://blog.52itstyle.vip
*/
@PostMapping("/register")
public Result register(SysUser user){
logger.info("{},用户注册",user.getUsername());
//业务逻辑
return Result.ok("注册成功");
}

多参数无实体一

前端代码:

var param = {
"title": "爪哇笔记",
"content": "一个有趣的公众号",
"author": "小柒2012"
}
param = JSON.stringify(param);
$.ajax({
url: "/sys/multiParameter",
data: param,
type: "post",
contentType: "application/json",
dataType: "json",
success: function(data) { }
});

后端实现:

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

多参数无实体二

前端代码:

var param = {
"title": "爪哇笔记",
"content": "一个有趣的公众号",
"author": "小柒2012"
}
$.ajax({
url: "/sys/multiParameter",
data: param,
type: "post",
dataType: "json",
success: function(data) { }
});

后端实现:

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

传递数组

前端代码:

var param = {
"ids": [1, 2, 3]
}
$.ajax({
url: "/sys/array",
data: param,
type: "post",
dataType: "json",
success: function(data) { }
});

后端实现:

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

传递集合

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

后端实现:

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

传递集合实体对象

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

前端代码:

var list = [];
list.push({
"username": "小柒2012",
"mobile": "17762288888"
});
list.push({
"username": "小柒2013",
"mobile": "17762289999"
});
$.ajax({
url: "/sys/listUser",
data: JSON.stringify(list),
type: "post",
contentType: "application/json",
dataType: "json",
success: function(data) { }
});

后端代码:

/**
* 爪哇笔记
* https://blog.52itstyle.vip
*/
@PostMapping("listUser")
public Result listUser(@RequestBody List<SysUser> list) {
logger.info("数据{}", list.size());
list.forEach(user->{
//输出实体对象
System.out.println(user.getUsername());
});
//业务逻辑
return Result.ok();
}

传递集合实体对象一对多

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

前端代码:

var roleList = [];
roleList.push({
"roleSign": "admin",
"roleName": "管理员"
});
roleList.push({
"roleSign": "user",
"roleName": "普通用户"
});
var list = [];
var user = {
"username": "小柒2012",
"mobile": "17762288888"
};
user.roleList = roleList;
list.push(user);
$.ajax({
url: "/sys/listUserRole",
data: JSON.stringify(list),
type: "post",
contentType: "application/json",
dataType: "json",
success: function(data) { }
});

后端实现:

/**
* 爪哇笔记
* https://blog.52itstyle.vip
*/
@PostMapping("listUserRole")
public Result listUserRole(@RequestBody List<SysUser> list) {
logger.info("数据{}", list.size());
list.forEach(user->{
List<SysRole> roleList = user.getRoleList();
roleList.forEach(role->{
System.out.println(role.getRoleName());
});
});
return Result.ok();
}

炒鸡复杂

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

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

RESTful 风格

比如,访问某篇文章:

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

原则

记住一下几点:

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

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

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

扩展

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

multipart/form-data

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

<form action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="description" value="爪哇笔记,一个神奇的公众号">
<input type="file" name="myFile">
<button type="submit">Submit</button>
</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. wepy框架开发小程序遇到的node-sass问题解决方案

    一.报错图 二.解决方案 主要是windows平台缺少编译环境, 1.先运行: npm install -g node-gyp 2.然后运行cmd:(右键点击:以管理员身份运行) 输入:npm ins ...

  2. Java程序语言的后门-反射机制

    在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...

  3. Mac配置环境变量path

    查看当前配置的path有哪些: 1. echo $PATH  当前所有的 2. cat /etc/paths  这个文件是操作系统自带的 mac系统环境变量的加载顺序(优先级): /etc/profi ...

  4. C#连接Mongo报Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1错的解决方案

    ---恢复内容开始--- 最近做一个基于ABP的.net Core的项目,数据库选了MongoDB,但是返现无法给数据库设置认证,只要设置了账号密码连接就报错 连接串如下: mongodb://roo ...

  5. 黑苹果之DELL台式机安装Mac OS X 10.13.6版本操作系统

    由于本人所在的公司一般都是DELL的品牌台式机,所以以DELL台式机做小白鼠.记得在2012年的时候,在当时的那家公司为了学习自学IOS开发的Objective-C开发语言的时候,由于囊中羞涩买不起m ...

  6. Anaconda基本认识

    Anaconda Distribution是执行Python数据科学和机器学习最简单的方法. 它包括250多种流行的数据科学软件包,以及适用于Windows,Linux和MacOS的conda软件包和 ...

  7. elasticsearch应用于产品列表

    package com.linkwee.web.service; import java.util.List; import com.linkwee.api.request.cim.ProductPa ...

  8. Spring 梳理-profile与条件化定义bean

    定义profile <beans> //root <beans profile="dev"> <bean id=.../> </beans ...

  9. Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value:

    问题:ERROR JDBCExceptionReporter:72 - Data truncation: Incorrect datetime value: '' for column 'create ...

  10. ubuntu13启动屏幕亮度0解决方法

    在终端输入: sudo gedit /etc/default/grub 找到 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDL ...