SpringMVC前后端参数映射

 更新时间:2023年08月14日 09:45:38   作者:秋官  
在web开发中我们都要进行前端传参后端取参的过程,本文主要介绍了SpringMVC前后端参数映射,针对GET, POST, PUT, DELETE 请求的参数该如何映射,感兴趣的可以了解一下

在web开发中我们都要进行前端传参后端取参的过程,今天就简单记录下针对GET, POST, PUT, DELETE 请求的参数该如何映射。

1. GET 请求的参数映射

1.1 参数名映射

GET请求是最简单的,只需要将参数以键值对的形式拼接到url后面就可以了,比如下面:

http://localhost:8080/helloParam?name=zhangsan&age=33\n
&birthDay=2023-08-01 20:01:11\n
&plays=basketabll&plays=football&plays=swimming

后端可以去获取参数:

@GetMapping(value = "/helloParam")
public String hello(String name,
                    Integer age,
                    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthDay,
                    String[] plays,
                    @RequestParam("plays") List<String> plays2) {
    log.info("请求参数: name = {}, age = {}, birthDay = {}, plays = {}, plays2 = {}", name, age, birthDay, plays, plays2);
    return "success";
}
//日志输出:请求参数: name = zhangsan, age = 33, birthDay = 2023-08-01T20:01:11, plays = [basketabll, football, swimming], plays2 = [basketabll, football, swimming]

日期字符串如何想直接映射成 LocalDateTime 类型,需要使用 @DateTimeFormat 注解进行标注。 plays 是一个数组,后端可以用数组或者集合接收,注意用集合接收时,需要搭配 @RequestParam 注解,否则将无法映射成功。

注意:前端的参数名必须和后端方法的变量名保持一致,如果不一致,将无法映射。如果就不一致,可以使用 @RequestParam 来完成映射。

1.2使用 @RequestParam  注解完成映射

比如:将上面请求参数中的 name 参数改为 cname 发送请求:

http://localhost:8080/helloParam?cname=zhangsan3333&age=33\n
&birthDay=2023-08-01 20:01:11\n
&plays=basketabll&plays=football&plays=swimming

后端映射:

@GetMapping(value = "/helloParam")
public String hello(@RequestParam("cname") String n,
                    Integer age,
                    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthDay,
                    String[] plays,
                    @RequestParam("plays") List<String> plays2) {
    log.info("请求参数: name = {}, age = {}, birthDay = {}, plays = {}, plays2 = {}", n, age, birthDay, plays, plays2);
    return "success";
}
//日志输出:请求参数: name = zhangsan333, age = 33, birthDay = 2023-08-01T20:01:11, plays = [basketabll, football, swimming], plays2 = [basketabll, football, swimming]

使用 @RequestParam 注解时,要求参数必须存在,否则请求将会报错。可以使用它的 required 属性来避免这个问题。

1.3 后端用对象接收参数

还是上面的请求,比如我需要传递分页参数,而后端的分页参数保存在 Page 对象中

http://localhost:8080/helloParam?name=zhangsan3333&age=33\n
&birthDay=2023-08-01 20:01:11\n
&plays=basketabll&plays=football&plays=swimming\n
&page=1&size=10

后端可以这样接收:

@GetMapping(value = "/helloParam")
public String hello(Page page,
                    String name,
                    Integer age,
                    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthDay) {
    log.info("请求参数: name = {}, age = {}, birthDay = {}, 分页参数:page = {}", n, age, birthDay, page);
    return "success";
}
//日志输出:请求参数: name = zhangsan3333, age = 33, birthDay = 2023-08-01T20:01:11, 分页参数:page = Page(page=1, size=10)

Page对象:

@Data
public class Page {
    private Integer page;
    private Integer size;
}

将请求参数也封装到对象中:

@GetMapping(value = "/helloParam")
public String hello(Page page, Student student) {
    log.info("请求对象参数: student = {}, 分页参数 = {}", student, page);
    return "success";
}
//日志输出:请求对象参数: student = Student(name=zhangsan3333, age=33, birthDay=2023-08-01T20:01:11, plays=[basketabll, football, swimming]), 分页参数 = Page(page=1, size=10)
@Data
public class Student {
    private String name;
    private Integer age;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthDay;
    private List<String> plays;
}

1.4 Restful 风格的参数映射

http://localhost:8080/helloParam/liubei/45/1949-10-01 23:23:44

后端可以这样接收:

@GetMapping(value = "/helloParam/{cname}/{age}/{birthDay}")
public String helloObj2(@PathVariable("cname") String name,
                        Integer age,
                        Student student) {
    log.info("Restful请求参数: name = {}, age = {}, 对象student = {}", name, age, student);
    return "success";
}
//日志输出:Restful请求参数: name = liubei, age = null, 对象student = Student(name=null, age=45, birthDay=1949-10-01T23:23:44, plays=null)

@GetMapping("/hello/{name}/{age}/{birthDay}") 这里的{参数名}要和方法中的参数名保持一致。而且当用单个参数去接收时,必须搭配 @PathVariable 注解才可以映射成功,否则将无法映射,比如age就无法映射。当用对象去接收时,无需指定 @PathVariable 注解,但是对象的属性名要和Restful的请求{参数名}保持一致才可以映射成功, Student 类中是 name ,而Rfestul中的请求参数是 cname , 所以无法映射。

2. POST 请求的参数映射

说起 POST 请求,我们先看下几个比较常见的 Content-Type

Content-TypeContent-Type 描述
multipart/form-datamultipart/form-data就是我们常见的表单,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件(可以多个文件)
x-www-form-urlencodedx-www-from-urlencoded,会将表单内的数据转换为键值对,比如,name=zhangsan&age=23,相比multipart/form-data ,它只能上传键值对,不能上传文件
raw可以上传任意格式的文本,比如我们常见的 JOSN( application/json ), 还有其他的 text, xml, html...
binary就是application/octet-stream,只可以上传二进制数据,通常用来上传文件或者音频,没有键值对,一次只能上传一个文件

2.1 Content-Type: application/x-www-form-urlencoded 的参数映射

multipart/form-data 相比 application/x-www-form-urlencoded 多了文件上传的功能,其他基本上都是一样的,所以我就以 application/x-www-form-urlencoded 进行演示说明。

2.1.1 参数名映射

Controller:

@PostMapping(value = "/form")
public String form(String name, Integer age, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthDay) {
    log.info("请求参数: name = {}, age = {}, time = {}", name, age, birthDay);
    return "success";
}
//日志输出:请求参数: name = zhangsan, age = 23, time = 2023-07-31T23:51:23

注意:这里如果要映射成功,确保请求参数名与方法参数名称保持一致。如果不一致,可以使用 @RequestParam 注解来指定.

Controller:

@PostMapping(value = "/form")
public String form(@RequestParam("cname") String name, Integer age) {
    log.info("请求参数: name = {}, age = {}", name, age);
    return "success";
}
//日志输出:请求参数: name = zhangsan, age = 23

有没有发现,其实和GET请求映射一模一样。

2.1.2 对象映射

@Data
public class Student {
    private String name;
    private Integer age;
    private String fromCity;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthDay;
}

前端没有变化,还是之前的请求:

curl --location --request POST 'http://localhost:8080/form' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=zhangsan' \
--data-urlencode 'age=23' \
--data-urlencode 'birthDay=2023-07-31 23:51:23'

后端用对象接收:

@PostMapping(value = "/form")
public String form(Student student) {
    log.info("obj请求参数: name = {}, age = {}", student.getName(), student.getAge());
    return "success";
}
//日志输出:obj请求参数: name = zhangsan, age = 23, time = 2023-07-31T23:51:23

2.2.3 Restful 风格的参数映射

调整一下请求格式:

curl --location --request POST 'http://localhost:8080/form/zhangxinyu/33'

后端接收:

@PostMapping(value = "/form/{cname}/{age}")
public String form(@PathVariable("cname") String name,
                   @PathVariable Integer age,
                   Student student) {
    log.info("restful请求参数: name = {}, age = {}, student对象 = {}", name, age, student);
    return "success";
}
//日志输出:obj请求参数: name = zhangxinyu, age = 33, student对象 = Student(name=null, age=33, birthDay=null, plays=null)

@PostMapping(value = "/form/{cname}/{age}") 这里的{参数名}要和方法中的参数名保持一致。而且当用单个参数去接收时,必须搭配 @PathVariable 注解才可以映射成功,否则将无法映射。当用对象去接收时,无需指定 @PathVariable 注解,但是对象的属性名要和Restful的请求{参数名}保持一致才可以映射成功, Student 类中是 name ,而Rfestul中的请求参数是 cname , 所以无法映射。和 GET 请求是一样的。

2.2 Content-Type: application/json 的参数映射

想要接收 application/json 的数据,后端的方法参数上必须标注 @RequestBody 注解

2.2.1 @RequestBody 注解完成参数映射

我们看下后端的接收:

@PostMapping("/application")
public String hello(Integer age, @RequestBody String name, LocalDateTime birthDay){
    log.info("请求参数: name = {}, age = {}, birthDay = {}", name, age, birthDay);
    return "success";
}

只有 name 参数映射上了,这是因为它会把整个body里面的内容映射给标注了 @RequestBody 参数,而 age , birthDay 因为没有标注 @RequestBody 注解所以无法映射,而且也不能再标注 @RequestBody 注解,因为只能给一个参数标注,如果多个参数标注 @RequestBody 注解会报错。

那如果想给多个参数都映射成功,怎么处理?可以用 自定义对象 去接收或者 Map .

自定义 Student 对象去接收:

@Data
public class Student {
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")   //要用这个注解
    //@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //GET/form 用这个去映射
    private LocalDateTime birthDay;
    private List<String> plays;
    private Course course;
}
@Data
public class Course {
    private String id;
    private String courseName;
}

Controller:

@PostMapping("/application")
public String hello(@RequestBody Student student){
    log.info("请求参数: student对象:{}", student);
    return "success" + student.getBirthDay();
}
//日志输出:请求参数: student对象:Student(name=周星驰, age=50, birthDay=2023-08-02T20:36:04, plays=null, course=null)

2.2.2 使用 @JsonProperty 注解映射参数名不一致的情况

javaBean对象:

@Data
public class Student {
    //使用JsonProperty("username")注解完成映射
    @JsonProperty("username")
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthDay;
    private List<String> plays;
    private Course course;
}

2.2.3 使用 @JsonIgnore 注解忽略不需要映射的字段

如果前端不需要展示某个字段,也可以用这个注解标注

JavaBean对象:

@Data
public class Student {
    @JsonProperty("username")
    private String name;
    @JsonIgnore
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthDay;
    private List<String> plays;
    @JsonIgnore
    private Course course;
}

Controller:

@Slf4j
@RestController
public class HelloController {
    @PostMapping("/application")
    public Student hello(@RequestBody Student student){
        log.info("请求参数: student对象:{}", student);
        return student;
    }
}
//日志输出:请求参数: student对象:Student(name=周星驰, age=null, birthDay=2023-08-02T20:36:04, plays=[swimming, singing], course=null)

看下返回给前端的JSON数据:

age , course 这种标注了 @JsonIgnore 注解的属性就不会显示在JSON中了。

到此这篇关于SpringMVC前后端参数映射的文章就介绍到这了,更多相关SpringMVC参数映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • 详解如何自定义parallelStream线程池

    详解如何自定义parallelStream线程池

    这篇文章主要为大家介绍了如何自定义parallelStream的线程池实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Java Volatile应用单例模式实现过程解析

    Java Volatile应用单例模式实现过程解析

    这篇文章主要介绍了Java Volatile应用单例模式实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • IntelliJ IDEA maven 构建简单springmvc项目(图文教程)

    IntelliJ IDEA maven 构建简单springmvc项目(图文教程)

    在工作当中,我们有时需要创建一个全新的工程,而基于spring-mvc web的工程较为常见,这篇文章主要介绍了IntelliJ IDEA maven 构建简单springmvc项目(图文教程),感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Java集合基础知识 List/Set/Map详解

    Java集合基础知识 List/Set/Map详解

    这篇文章主要介绍了Java集合基础知识 List/Set/Map,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java实现心跳机制的方法

    Java实现心跳机制的方法

    这篇文章主要介绍了Java实现心跳机制的方法,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • MyBatis配置文件的写法和简单使用

    MyBatis配置文件的写法和简单使用

    MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。这篇文章主要介绍了MyBatis配置文件的写法和简单使用,需要的朋友参考下
    2017-01-01
  • 解析Java和IDEA中的文件打包问题

    解析Java和IDEA中的文件打包问题

    这篇文章主要介绍了Java和IDEA中的文件打包问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • SSH原理及两种登录方法图文详解

    SSH原理及两种登录方法图文详解

    SSH(Secure Shell)是一套协议标准,可以用来实现两台机器之间的安全登录以及安全的数据传送,其保证数据安全的原理是非对称加密。本文通过图文并茂的形式给大家介绍了SSH原理及两种登录方法,一起看看吧
    2018-08-08
  • Java限流实现的几种方法详解

    Java限流实现的几种方法详解

    这篇文章主要介绍了Java限流实现的几种方法,通俗的说,限流就是 限制一段时间内,用户访问资源的次数,减轻服务器压力,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-12-12
  • Java中字符串转int数据类型的三种方式

    Java中字符串转int数据类型的三种方式

    这篇文章主要介绍了Java中字符串转int数据类型的三种方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03

最新评论