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 类型接收,然后通过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° 官方检验。

原文地址:https://www.cnblogs.com/qq575654643/p/11759791.html

时间: 2024-10-08 00:30:14

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

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

前言 前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑.当然了,优化是无止境的,前人栽树后人乘凉.作为我们开发者来说,既然站在了巨人的肩膀上,就要写出更加优化的程序. SpringBoot开发案例之JdbcTemplate批量操作 SpringBoot开发案例之CountDownLatch多任务并行处理 改造 理论上讲,线程越多程序可能更快,但是在实际使用中我们需要考虑到线程本身的创建以及销毁的资源消耗,以及保护操作系统本身的目的.我们通常需要将线程限制在一定

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

前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场景,同时跟大家分享交流一下. 秒杀场景 秒杀场景无非就是多个用户在同时抢购一件或者多件商品,专用词汇就是所谓的高并发.现实中经常被大家喜闻乐见的场景,一群大妈抢购打折鸡蛋的画面一定不会陌生,如此场面让服务员大姐很无奈,赶上不要钱了. 业务特点 瞬间高并发.电脑旁边的小哥哥.小姐姐们如超市哄抢的大妈一般

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

前言 在 SpringBoot 很火热的时候,阿里巴巴的分布式框架 Dubbo 不知是处于什么考虑,在停更N年之后终于进行维护了.在之前的微服务中,使用的是当当维护的版本 Dubbox,整合方式也是使用的 xml 配置方式. 改造前 之前在 SpringBoot 中使用 Dubbox是这样的.先简单记录下版本,Dubbox-2.8.4.zkclient-0.6.zookeeper-3.4.6. 项目中引入 spring-context-dubbo.xml 配置文件如下: <?xml versio

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

前言 在开发过程中,通常我们会配置一些参数来实现某些功能,比如是否开启某项服务,告警邮件配置等等.一般会通过硬编码.配置文件或者数据库的形式实现. 那么问题来了,如何更加优雅的实现?欢迎来到 Nacos 的世界! Nacos 配置管理 Nacos 是阿里巴巴的开源的项目,全称 Naming Configuration Service ,专注于服务发现和配置管理领域. Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务

SpringBoot开发案例之打造十万博文Web篇

前言 通过 Python 爬取十万博文之后,最重要的是要让互联网用户访问到,那么如何做呢? 选型 从后台框架.前端模板.数据库连接池.缓存.代理服务.限流等组件多个维度选型. 后台框架 SpringBoot2+.JPA 前端框架 Vue 模块框架 Thymeleaf 数据库连接池 HikariCP 缓存 Redis 限流 Guava 代理服务 Nginx 文章编辑 Markdown 架构 博文 我们可以通过以下方式访问: https://blog.52itstyle.top/49.html 亦或

开发函数计算的正确姿势——轻松解决大依赖部署

<a name="1"></a> 前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费.函数计算更多信息 参考.Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算.API 网关.

开发函数计算的正确姿势 —— 使用 Fun Local 本地运行与调试

前言首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费.函数计算更多信息 参考. Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算.API 网关.日志服务等资源.它通过一个资源配置文件(template.yml),

开发函数计算的正确姿势 —— 爬虫

在 <函数计算本地运行与调试 - Fun Local 基本用法> 中,我们介绍了利用 Fun Local 本地运行.调试函数的方法.但如果仅仅这样简单的介绍,并不能展现 Fun Local 对函数计算开发的巨大效率的提升. 这一次,我们拿一个简单的场景来举例子--开发一个简单的爬虫函数(代码参考函数计算控制台模板),介绍如何以正确姿势,从零开始,开发一个自动伸缩.按调用次数收费的 serverless 爬虫应用. 开发步骤我们将这个完整的应用拆分成多步,并且在每一步完成后,我们都会进行相应的运

从方法到思维:什么是应用逻辑架构的正确姿势?

Blog: https://blog.yilon.top 作者: 阿里技术 地址: https://zhuanlan.51cto.com/art/202004/613905.htm 本文分享阿里资深技术专家六铢的架构方法论,这套方法论中包含了详细的架构推导逻辑,希望能够帮助大家在工作中从各个粒度.各个层次来做好架构工作.较长,同学们可先收藏再看. 一.背景 1.1 架构中的问题识别 需求分析,架构实现,(新需求,架构改动)* n = 推倒重来. 这个过程是一个循环往复的过程,有的产品每年都会推倒