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 ...
随机推荐
- 基于Docker搭建大数据集群(一)Docker环境部署
本篇文章是基于Docker搭建大数据集群系列的开篇之作 主要内容 docker搭建 docker部署CentOS 容器免密钥通信 容器保存成镜像 docker镜像发布 环境 Linux 7.6 一.D ...
- Spring 梳理-传递模型数据到视图
传递model,返回string,不指定返回key package com.jt; import com.myOrg.DeptUserDomain; @Controller @RequestMappi ...
- Java中Synchronized的优化原理
我们知道,从 JDK1.6 开始,Java 对 Synchronized 同步锁做了充分的优化,甚至在某些场景下,它的性能已经超越了 Lock 同步锁.那么就让我们来看看,它究竟是如何优化的. 原本的 ...
- awk 命令使用
awk命令就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理.例如: awk -F '/' '{print $NF}' tmp/file.txt 该命令用于读取file. ...
- Flask基础(08)-->错误捕获(异常捕获)
错误捕获(异常捕获) from flask import Flask from flask import abort app = Flask(__name__) @app.route('/demo1' ...
- .Net Core自动化部署系列(三):使用GitLab CI/CD 自动部署Api到Docker
之前写过使用Jenkins实现自动化部署,最近正好没事研究了下GitLab的自动化部署,顺便记录一下. 使用GitLab部署我们需要准备两件事,第一个起码你得有个GitLab,自己搭建或者使用官方的都 ...
- SUSE CaaS Platform 4 - 使用 Ceph RBD 作为持久存储 (静态)
1.所有节点安装 # zypper -n in ceph-common 复制 ceph.conf 到 worker 节点上 # scp admin:/etc/ceph/ceph.conf /etc/c ...
- httpd2.2
httpd -t:检查httpd配置文件/etc/httpd/conf/httpd.conf的语法错误 请求报文语法 <method> <request-URL> <ve ...
- element取表格对应id数据
<el-button size="mini" type="danger" @click="editor(scope.row)"> ...
- Java基础学习笔记(三) - 抽象类和接口
一.抽象类 没有方法主体的方法称为抽象方法,包含抽象方法的类就是抽象类. Java中使用 abstract 关键字修饰方法和类,抽象方法只有一个方法名,没有方法体. public abstract c ...