SpringBoot 开发案例之参数传递的正确姿势
前言
开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼。
姿势
学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复制粘贴一把撸,问题是你想问不想问为什么!
传递
用户登录
前端代码:
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
类型接收,然后通过FastJson
的 JSON.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 开发案例之参数传递的正确姿势的更多相关文章
- SpringBoot开发案例之多任务并行+线程池处理
前言 前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑.当然了,优化是无止境的,前人栽树后人乘凉.作为我们开发者来说,既然站在了巨人的肩膀上,就要写出更加优化的程序 ...
- SpringBoot开发案例从0到1构建分布式秒杀系统
前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场 ...
- SpringBoot开发案例之打造私有云网盘
前言 最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意.无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还 ...
- SpringBoot开发案例之整合Activiti工作流引擎
前言 JBPM是目前市场上主流开源工作引擎之一,在创建者Tom Baeyens离开JBoss后,JBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过,目前官 ...
- SpringBoot开发案例之整合Dubbo分布式服务
前言 在 SpringBoot 很火热的时候,阿里巴巴的分布式框架 Dubbo 不知是处于什么考虑,在停更N年之后终于进行维护了.在之前的微服务中,使用的是当当维护的版本 Dubbox,整合方式也是使 ...
- SpringBoot开发案例之整合Kafka实现消息队列
前言 最近在做一款秒杀的案例,涉及到了同步锁.数据库锁.分布式锁.进程内队列以及分布式消息队列,这里对SpringBoot集成Kafka实现消息队列做一个简单的记录. Kafka简介 Kafka是由A ...
- SpringBoot开发案例之分布式集群共享Session
前言 在分布式系统中,为了提升系统性能,通常会对单体项目进行拆分,分解成多个基于功能的微服务,如果有条件,可能还会对单个微服务进行水平扩展,保证服务高可用. 那么问题来了,如果使用传统管理 Sessi ...
- 转载-SpringBoot开发案例之整合日志管理
转载:https://cloud.tencent.com/developer/article/1097579 有一种力量无人能抵挡,它永不言败生来倔强.有一种理想照亮了迷茫,在那写满荣耀的地方. 00 ...
- SpringBoot开发案例Nacos配置管理中心
前言 在开发过程中,通常我们会配置一些参数来实现某些功能,比如是否开启某项服务,告警邮件配置等等.一般会通过硬编码.配置文件或者数据库的形式实现. 那么问题来了,如何更加优雅的实现?欢迎来到 Naco ...
随机推荐
- asp.net core + layui.js 搭建仓储系统
先放几张网站图片: 第一步先从layui 网站https://www.layui.com/doc/ 下载相关文件,复制到项目 wwwroot 目录下: 然后在 _Layout.cshtml 中引用 l ...
- Intellij IDEA 2019 + Java Spring MVC + Hibernate学习笔记(2)
书接上文 首先根据各种Spring MVC教程,建立了基础的结构,是否合理不知道,姑且先这样,有问题再解决问题.学习新东西,不能怕掉坑里... 查询网上别人的经历说需要把根目录下的lib目录下的所有包 ...
- Java的EOF标识?
这篇是关于JAVA中EOF标识的讲解,之前在工作上碰到过一个问题,有人问过,不能通过判断EOF来知道文件有没有读取完毕吗?其实,还真不能. 直接从JDK接口文档入手,以FileInputStrea ...
- 两个变量交换数字 不用第三个变量的情况下 int a = 5,b = 6
今天可是涨见识额 记录一下 第一种方法: a=a+bb=a-ba=a-b 第二种: b= a+(a=b)*0 一句话搞定
- linux 指定tomcat的具体路径
1.直接修改catalina.sh中对应的变量 CATALINA_HOME=/xx/xxCATALINA_BASE=/xx/xx (该方法需要找到所有的变量进行修改,不适合,推荐使用方式2) 2.在p ...
- Linux kail安装及查看命令
Linux kail安装及查看命令 apt-get update //更新源 apt-get install package ...
- SpringCache - 请求级别缓存的简易实现
前言 在SpringCache缓存初探中我们研究了如何利用spring cache已有的几种实现快速地满足我们对于缓存的需求.这一次我们有了新的更个性化的需求,想在一个请求的生命周期里实现缓存. 需求 ...
- vue运行报错webpack-dev-server: command not found
翻译过来就是: 'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 解决方法: 然后总结下成功的步骤: 1. 直接在项目目录下: cnpm install npm run ...
- 【Java基础】Java中的语法糖
目录 Java中的语法糖 switch对String和枚举类的支持 对泛型的支持 包装类型的自动装箱和拆箱 变长方法参数 枚举 内部类 条件编译 断言 数值字面量 for-each try-with- ...
- GoLang 获取两个时间相差多少小时
package main import ( "fmt" "time" ) func main() { fmt.Println(getHourDiffer(&qu ...