SpringMVC数据绑定接收复杂数据处理方案
常用于数据绑定的几个注解@PathVariable
,@RequestBody
、@RequestParam
,本文配合postman,讲解常见的前后台数据交互中的一些数据绑定的问题
@PathVariable
PathVariable是路径变量的意思,这个注解主要作用在请求URL路径上的数据绑定,默认传递数值写在URL上,SpringMVC就可以获取到
- 支持请求方式:GET
- 参数传递:在URL上直接传递
@RequestMapping("/Student")
@RestController
public class DataBindController {
@Autowired
private StudentService studentService;
@GetMapping("/getStudent/{id}")
public Student getStudentById(@PathVariable Integer id){
Student student = studentService.getStudentById(id);
return student;
}
}
@RequestBody
RequestBody是请求体的意思,这个注解作用在请求体的数据绑定,并且数据必须在写在请求体中,还要以JSON的数据格式发送才符合条件
该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded
编码的内容,例如application/json, application/xml等;
- 支持请求方式:GET,POST,PUT,DELETE
- 参数传递:在Body中传递
- 支持的Content-Type:json
@PostMapping("/addStudent")
public Student addStudent(@RequestBody Student student){
System.out.println(student);
return student;
}
@RequestParam
RequestParam是请求参数的意思,这个注解的作用在请求路径和请求体中的数据,因为使用request.getParameter()方式获取参数
所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值
- 支持请求方式:GET,POST,PUT,DELETE
- 参数传递:在Body中传递
- 支持的Content-Type:json
在请求体中的参数必须指定是form-data
或者x-www-form-urlencoded
,这两种方式是以表单的形式提交数据,使用这两种方式
会将表单内的数据转换为键值对,&分隔形式封装在请求体中传送给后台,前者和后者的区别是在于对非ASCII码字符的转码,
前者是直接发送,后者是转码成百分号发送
三个注解小结
注解 | 请求参数位置 | 请求方式 | 支持的Content-Type | 请求示例 |
---|---|---|---|---|
@PathVariable | Url | Get | Get请求没有Content-Type | /students/1 |
@RequestParam | Url和Body | Get/Post/Put/Delete/Patch | form-data,x-www-form-urlencoded | /students?name=zs&age=23 |
@RequestBody | Body | Post/Put/Delete/Patch | application/json | {"id":1,"name":"zs","age":23} |
三个注解的源码和使用场景:
@PathVariable
这个注解我一般在工作中,会用在单个对象的查询上,比如要根据ID值查询学生信息,就会在Postman发送GET
请求,后台使用@PathVariable
接收
- 优点:适合接收简单类型的数据绑定,如int,string这两个常用
- 缺点:id暴露在url上,对于不方便泄露ID的值请求,最好不要使用。只支持Get方式,请求方式有局限性,不支持复杂数据类型,自定义数据类型
源码
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
/**
* 参数名称
*/
String value() default "";
}
源码解析
-
@PathVariable注解源码中只有一个参数,不填的默认是绑定到与路径参数同名的形参变量
-
如果要接收多个路径变量,则需要声明多个@PathVariable变量
@RequestMapping("/Student/{name}/{age}")
public Object getStudentInfo (@PathVariable String name,@PathVariable Integer age){
//...
}
使用解析
- POSTMAN发送的链接:http://localhost:8080/Student/getStudent/1
- 后端接收参数:/Student/getStudent/{id},这里的id是路径上的参数,传什么值接收什么值
- 后端映射值:@PathVariable Integer id 这里的方法参数id要与路径变量参数id同名,因为@PathVariable没有指定别名的注解变量
@RequestParam
这个注解我一般在工作中,会用在组合查询多个对象,比如跟据姓名模糊查询和性别组合查询筛选学生,就会发送POST
请求,后台使用RequestParam
接收
- 优点:支持常用多种请求方式,请求参数可以封装在请求体中较为安全
- 缺点:id暴露在url上,对于不方便泄露ID的值请求,最好不要使用。只支持Get方式,请求方式有局限性
源码
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
/**
* 参数名称(和value同等意思)
*/
@AliasFor("name")
String value() default "";
/**
* 参数名称 (和name同等意思)
*/
@AliasFor("value")
String name() default "";
/**
* 是否必选(默认必选)
*/
boolean required() default true;
/**
* 参数默认值
*/
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
源码解析
@RequestParam总体上来说,该注解类拥有三个参数:
-
value、name 属性都标识请求参数名(必须配置)
-
required:参数是否必传,默认为 true,可以设置为非必传 false;(如果设置了必传或默认,请求未传递参数,将会抛出异常)
-
defaultValue:参数默认值,如果设置了该值,required 将会自动设置为 false
使用解析
-
get请求的 requestHeaders 中 content-type 这个字段,使用 form-data 表单形式携带参数请求
-
Spring中的@RequestParam注解接收的参数大多数场景是来自Request Headers中,
-
即请求头,也就是url中,格式为:
http://localhost:8080?name=zs&age=23
,由于 url 长度有限制,所以参数需要限制数量和值得长度
@RequestBody
源码
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
/**
* 默认参数必传
*/
boolean required() default true;
}
源码解析
- @RequestBody注解只拥有一个参数
- required 默认为 true,即对象中的属性必须有一个要传,否则会抛出异常
使用解析
-
post请求的requestHeaders请求头中有content-type字段,一般用来处理:applicatin/json格式的参数;
-
Spring中的@RequestBody注解是用来接收请求体中的参数数据,即requestBody请求体中,故不受参数数据长度的限制;
补充HTTP知识:Post、Get、Put、Delete
Http协议常用的四种请求方式:Post、Get、Put、Delete等;其中Put、Delete请求方式很少见,都可用Post方式代替!
- 对数据库而言: get 请求不修改数据库,只是查询。Post是增加记录,put是更新,Delete数据库删除;
- Put,Post,Delete 方式的请求参数会直接放在requestBody里;
- 处理 request uri 部分的注解,路径参数变量:@PathVariable;
- 处理request header部分的注解: @RequestHeader, @CookieValue,@RequestParam;
- 处理request body部分的注解:@RequestParam, @RequestBody;
- 综上所述:@RequestParam注解既可以接收Get方式的请求头中的参数,也可以接收Post方式的请求体中的参数;
补充HTTP知识: Content-Type与Accept
--------Response Headers-----------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
If-Modified-Since: 0
expire: 0
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 17 Nov 2020 05:48:54 GMT
--------Request Headers-----------
POST /student/update HTTP/1.1
Host: localhost:9002
Connection: keep-alive
Content-Length: 21
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json
X-Requested-With: XMLHttpRequest
User-Agent: Chrome/86.0.4240.75 Mobile Safari/537.36
Content-Type: application/json
Accept
Accept代表发送希望接受的数据类型
比如:Accept:application/json;
比如我们用浏览器发送请求中,请求头Request Headers带有Accept:application/json;
,
那就是表明浏览器发送这个请求,希望服务器传送回的数据格式是json数据格式
Content-Type
Content-Type代表发送端发送的数据类型
比如:Content-Type:application/json;
Response Headers带有Content-Type: application/json
就代表服务器希发送数据类型是json类型
Request Headers带有Content-Type: application/json
就代表服务器希发送数据类型是json类型
上述报文解释
浏览器发送了POST请求,这次请求发送的数据格式是JSON数据给是,希望服务器能返回JSON的数据格式
服务器发送返回了JSON形式的数据格式数据给浏览器
常见Content-Type媒体类型
Get请求的 headers 中没有 content-type 这个字段,Put、Delete和Post 请求的headers 是有 content-type 这个字段的
常见Content-Type媒体类型如下:
-
application/x-www-form-urlencoded 这种就是一般的文本表单用 post 传地数据,
只要将得到的 data 用 @RequestParam 或 request.getParamter() 获取即可;
-
multipart/form-data ,用于文件上传,此时 form 的 enctype 属性必须指定为 multipart/form-data;
-
application/json,将数据以json对象的格式传递;
-
text/xml;