SpringMVC前后端参数映射

在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-Type Content-Type 描述
multipart/form-data multipart/form-data便是咱们常见的表单,它会将表单的数据处理为一条音讯,以标签为单元,用分隔符分开。既能够上传键值对,也能够上传文件(能够多个文件)
x-www-form-urlencoded x-www-from-urlencoded,会将表单内的数据转换为键值对,比方,name=zhangsan&age=23,比较multipart/form-data ,它只能上传键值对,不能上传文件
raw 能够上传恣意格局的文本,比方咱们常见的 JOSN(application/json), 还有其他的 text, xml, html…
binary 便是application/octet-stream,只能够上传二进制数据,一般用来上传文件或许音频,没有键值对,一次只能上传一个文件

SpringMVC前后端参数映射

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 参数名映射

SpringMVC前后端参数映射

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注解来指定.

SpringMVC前后端参数映射

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;
}

前端没有变化,仍是之前的恳求:

SpringMVC前后端参数映射

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 风格的参数映射

调整一下恳求格局:

SpringMVC前后端参数映射

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注解完结参数映射

SpringMVC前后端参数映射

咱们看下后端的接纳:

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

SpringMVC前后端参数映射

只有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注解映射参数名不共同的状况

SpringMVC前后端参数映射

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注解忽略不需要映射的字段

假如前端不需要展现某个字段,也能够用这个注解标示

SpringMVC前后端参数映射

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数据:

SpringMVC前后端参数映射

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


好了,关于SpringMVC常见的参数映射就介绍到这儿吧,欢迎我们批评指正。