springboot参数校验详解
⼀、PathVariable 校验
在定义 Restful 风格的接⼝时,通常会采⽤ PathVariable 指定关键业务参数,如下:
@GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}")
@ResponseBody
public String path(@PathVariable("group") String group, @PathVariable("userid") Integer userid) {
return group + ":" + userid;
}
{group:[a-zA-Z0-9_]+} 这样的表达式指定了 group 必须是以⼤⼩写字母、数字或下划线组成的字符串。我们试着访问⼀个错误的路径:
GET //10000
此时会得到 404的响应,因此对于PathVariable 仅由正则表达式可达到校验的⽬的
⼆、⽅法参数校验
类似前⾯的例⼦,⼤多数情况下,我们都会直接将HTTP请求参数映射到⽅法参数上。
@GetMapping("/param")
@ResponseBody
public String param(@RequestParam("group")@Email String group,
@RequestParam("userid") Integer userid) {
return group + ":" + userid;
}
上⾯的代码中,@RequestParam 声明了映射,此外我们还为 group 定义了⼀个规则(复合Email格式)
这段代码是否能直接使⽤呢?答案是否定的,为了启⽤⽅法参数的校验能⼒,还需要完成以下步骤:声明 MethodValidationPostProcessor
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
Controller指定@Validated注解
@Controller
@RequestMapping("/validate")
@Validated
public class ValidateController {
如此之后,⽅法上的@Email规则才能⽣效。
校验异常
如果此时我们尝试通过⾮法参数进⾏访问时,⽐如提供⾮Email格式的 group
会得到以下错误:
GET /validate/param?group=simple&userid=10000
====>
{
"timestamp": 1530955093583,
"status": 500,
"error": "Internal Server Error",
"exception": "javax.validation.ConstraintViolationException",
"message": "No message available",
"path": "/validate/param"
}
⽽如果参数类型错误,⽐如提供⾮整数的 userid,会得到:
GET /validate/param?group=simple&userid=1f
====>
{
"timestamp": 1530954430720,
"status": 400,
"error": "Bad Request",
"exception": "org.hod.annotation.MethodArgumentTypeMismatchException",
"message": "Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For "path": "/validate/param"
}
当存在参数缺失时,由于定义的@RequestParam注解中,属性 required=true,也将会导致失败:
GET /validate/param?userid=10000
====>
{
"timestamp": 1530954345877,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter 'group' is not present",
"path": "/validate/param"
}
三、表单对象校验
页⾯的表单通常⽐较复杂,此时可以将请求参数封装到表单对象中,
并指定⼀系列对应的规则,参考
public static class FormRequest {
@NotEmpty
@Email
private String email;
@Pattern(regexp = "[a-zA-Z0-9_]{6,30}")
private String name;
@Min(5)
@Max(199)
private int age;
上⾯定义的属性中:
email必须⾮空、符合Email格式规则;
name必须为⼤⼩写字母、数字及下划线组成,长度在6-30个;
age必须在5-199范围内
Controller⽅法中的定义:
@PostMapping("/form")
@ResponseBody
public FormRequest form(@Validated FormRequest form) {
return form;
}
@Validated指定了参数对象需要执⾏⼀系列校验。
校验异常
此时我们尝试构造⼀些违反规则的输⼊,会得到以下的结果:
{
"timestamp": 1530955713166,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.validation.BindException",
"errors": [
{
"codes": [
"ail",
"ail",
"Email.java.lang.String",
"Email"
],
"arguments": [
{
"codes": [
"ail",
"email"
],
"arguments": null,
"defaultMessage": "email",
"code": "email"
},
[],
{
"arguments": null,
"codes": [
".*"
],
"defaultMessage": ".*"
}
],
"defaultMessage": "不是⼀个合法的电⼦邮件地址",
"objectName": "formRequest",
"field": "email",
"rejectedValue": "tecom",
"bindingFailure": false,
"code": "Email"
},
{
"codes": [
"Pattern.formRequest.name",
"Pattern.name",
"Pattern.java.lang.String",
"Pattern"
],
"arguments": [
"arguments": [
{
"codes": [
"formRequest.name",
"name"
]
,
"arguments": null,
"defaultMessage": "name",
"code": "name"
},
[],
{
"arguments": null,
"codes": [
"[a-zA-Z0-9_]{6,30}"
],
"defaultMessage": "[a-zA-Z0-9_]{6,30}"
}
],
"defaultMessage": "需要匹配正则表达式\"[a-zA-Z0-9_]{6,30}\"", "objectName": "formRequest",
"field": "name",
"rejectedValue": "fefe",
"bindingFailure": false,
"code": "Pattern"
},
{
"codes": [
"Min.formRequest.age",
"Min.age",
"Min.int",
"Min"
],
"arguments": [
{
"codes": [
"formRequest.age",
"age"
],
"arguments": null,
"defaultMessage": "age",
"code": "age"
},
5
],
"defaultMessage": "最⼩不能⼩于5",
"objectName": "formRequest",
"field": "age",
"rejectedValue": 2,
"bindingFailure": false,
"code": "Min"
}
],
"message": "Validation failed for object='formRequest'. Error count: 3", "path": "/validate/form"
}
如果是参数类型不匹配,会得到:
{
"timestamp": 1530955359265,
"status": 400,springboot框架的作用
"error": "Bad Request",
"exception": "org.springframework.validation.BindException",
"errors": [
{
"codes": [
"typeMismatch.formRequest.age",
"typeMismatch.age",
"typeMismatch.int",
"typeMismatch"
],
"arguments": [
{
"codes": [
"formRequest.age",
"age"
],
"arguments": null,
"defaultMessage": "age",
"code": "age"
}
],
"defaultMessage": "Failed to convert property value of type 'java.lang.String'
to required type 'int' for property 'age'; nested exception is java.lang.NumberFormatException: For input string: \"\"",
"objectName": "formRequest",
"field": "age",
"rejectedValue": "",
"bindingFailure": true,
"code": "typeMismatch"
}
],
"message": "Validation failed for object='formRequest'. Error count: 1",
"path": "/validate/form"
}
Form表单参数上,使⽤@Valid注解可达到同样⽬的,⽽关于两者的区别则是:
@Valid 基于JSR303,即 Bean Validation 1.0,由Hibernate Validator实现;
@Validated 基于JSR349,是Bean Validation 1.1,由Spring框架扩展实现;
后者做了⼀些增强扩展,如⽀持分组校验,有兴趣可。
四、RequestBody 校验
对于直接Json消息体输⼊,同样可以定义校验规则:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论