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 ...
随机推荐
- Android手机QQ文件夹解析
注:切勿修改手机QQ文件夹,以免造成不必要的使用问题及无法修复的数据丢失] 安卓手机QQ tencent文件夹解析 QQ下载的聊天背景:tencent→MobileQQ→system_backgrou ...
- ReentrantLock API
java可重入锁,简单几个小案例,测试特性. 1.尝试锁 tryLock package com.cn.cfang.ReentrantLock; import java.util.concurren ...
- 程序猿——踩bug之路
从开始这就是一个新的坑,还好今天我们爬上了: 带着Ui界面的编程,最想感谢的是我的搭档乔美萱:此处我觉得需要掌声和尖叫,一路带我从走到飞: 一.结对编程项目:带UI的小初高数学学习软件 1.用户注册功 ...
- 对象实例Vue
var vm = new Vue({ el:'#app', data:{}, //数据 methods:{}, //方法调用 filters:{}, //私有过滤器 directives:{}, // ...
- linux&shell学习系列
1.VMware安装Centos7虚拟机 2.Linux之vim详解 3.linux后台运行的几种方式 4.linux权限管理 5.linux之用户和用户组管理详解 6.grep文本搜索工具详解 7. ...
- springboot + mybatis + mycat整合
1.mycat服务 搭建mycat服务并启动,windows安装参照. 系列文章: [Mycat 简介] [Mycat 配置文件server.xml] [Mycat 配置文件schema.xml] [ ...
- Kubernetes 系列(五):Prometheus监控框架简介
由于容器化和微服务的大力发展,Kubernetes基本已经统一了容器管理方案,当我们使用Kubernetes来进行容器化管理的时候,全面监控Kubernetes也就成了我们第一个需要探索的问题.我们需 ...
- 记录使用echarts的graph类型绘制流程图全过程(一)-x,y位置的计算
先说下本次案例业务需求,输入2个节点,获取数据后绘制出2个节点间的路径,之前使用的是网状图,但是网状图的效果不佳,需要转换成流程图的模式: 那么如何在不修改数据的情况下,实现类似效果尼? 看了下ech ...
- 前端防止url输入地址直接访问页面
首先,解决这个问题要搞明白此url是从程序内部跳转还是直接在地址栏输入的,如果是程序内部跳转,那就好办啦.方法如下: 判断用户是否登录状态,是否携带token 使用router.beforeEach注 ...
- 运算符 字符串 for循环
1. 运算符 1.1赋值运算符 = += -= *= /= //= %= **= 1.2比较运算符 < > = <= == != 1.3成员运算符 in not in 1.4逻辑运算 ...