问题
描述
接口的参数验证(比如:字段长度、字段需要符合某个格式)
解决思路
- 在控制器类的方法里自己写校验逻辑代码
- 找找是否有可用的第三方库
解决方案
1. 自己写逻辑
- 优点
- 足够自由,可以完全按照业务逻辑写
- 不需要额外引入第三方库
- 缺点
- 不够优雅
- 参数验证与业务逻辑本身关系不大,会占用大量精力
- 后期的维护成本高
2. 使用Bean Validation
1. PathVariable校验
直接将参数验证的条件加到参数后面,{group:\d{6}}表示参数group必须是6位的数据
示例
@RequestMapping(value = "pathVariableTest/{group:\\d{6}}/{userid}")
public String pathVariableTest(@PathVariable("group") String group, @PathVariable("userid") Integer userid) {
return "suc";
}
访问一个错误路径,会得到404响应
结果
{
"timestamp": "2020-10-19T09:29:12.950+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/pathVariableTest/aAa/3"
}
注意:PathVariable 只有正则表达式可达到校验的目的,即只有正则表达式这一种验证方式。
2. RequestParam校验
- 在对应的参数上添加校验条件
@RequestMapping(value = "requestParamTest")
public String requestParamTest(
@RequestParam @Size(min = 1, max = 10, message = "姓名长度必须为1到10") String name,
@Min(value = 10, message = "年龄最小为10") @Max(value = 100, message = "年龄最大为100") @RequestParam("age") Integer age) {
return "suc";
}
- 声明MethodValidationPostProcessor
注意:这一步是为了要启用RequestParam校验
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
- Controller指定@Validated注解
注意:一定要在Ctroller类上,不然校验条件也是无法生效的。
@RequestMapping(value = "requestParamTest")
public String requestParamTest(
@RequestParam @Size(min = 1, max = 10, message = "姓名长度必须为1到10") String name,
@Min(value = 10, message = "年龄最小为10") @Max(value = 100, message = "年龄最大为100") @RequestParam("age") Integer age) {
return "suc";
}
尝试使用非法值访问
结果
{
"timestamp": "2020-10-19T10:07:44.509+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/requestParamTest"
}
2020-10-19 17:42:13.424 ERROR 21660 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.validation.ConstraintViolationException: requestParamTest.age: 年龄最大为100] with root cause
javax.validation.ConstraintViolationException: requestParamTest.age: 年龄最大为100
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:116) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at com.hyq.demo.springbootdemo.ParamValidController$$EnhancerBySpringCGLIB$$293abf03.requestParamTest() ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_161]
...
3.RequestBody验证
对于直接JSON消息体传参,同样可以定义校验规则
- 在接口上设置参数校验
注意:必须要将将注解Validated设置在参数上,在Ctroller类上的设置对RequestBody的校验无效
@RequestMapping(value = "requestBodyTest")
public String requestBodyTest(@Validated @RequestBody User user) {
return "suc";
}
- 在RequestBody对应的Bean上设置校验条件
public class User {
@Size(min = 1, max = 10, message = "姓名长度必须为1到10")
private String name;
@Min(value = 10, message = "年龄最小为10")
@Max(value = 100, message = "年龄最大为100")
private int age;
}
尝试使用非法值访问
结果
{
"timestamp": "2020-10-19T10:00:29.682+00:00",
"status": 400,
"error": "Bad Request",
"message": "",
"path": "/requestBodyTest"
}
2020-10-19 18:00:29.673 WARN 22448 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.hyq.demo.springbootdemo.ParamValidController.requestBodyTest(com.hyq.demo.springbootdemo.User): [Field error in object 'user' on field 'age': rejected value [192]; codes [Max.user.age,Max.age,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],100]; default message [年龄最大为100]] ]
4.表单对象校验
参考链接
参考文章
springboot 参数校验详解
SpringBoot里参数校验/参数验证