問題
描述
接口的參數(shù)驗證(比如:字段長度搏色、字段需要符合某個格式)
解決思路
- 在控制器類的方法里自己寫校驗邏輯代碼
- 找找是否有可用的第三方庫
解決方案
1. 自己寫邏輯
- 優(yōu)點
- 足夠自由,可以完全按照業(yè)務(wù)邏輯寫
- 不需要額外引入第三方庫
- 缺點
- 不夠優(yōu)雅
- 參數(shù)驗證與業(yè)務(wù)邏輯本身關(guān)系不大崔拥,會占用大量精力
- 后期的維護(hù)成本高
2. 使用Bean Validation
1. PathVariable校驗
直接將參數(shù)驗證的條件加到參數(shù)后面,{group:\d{6}}表示參數(shù)group必須是6位的數(shù)據(jù)
示例
@RequestMapping(value = "pathVariableTest/{group:\\d{6}}/{userid}")
public String pathVariableTest(@PathVariable("group") String group, @PathVariable("userid") Integer userid) {
return "suc";
}
訪問一個錯誤路徑似将,會得到404響應(yīng)
結(jié)果
{
"timestamp": "2020-10-19T09:29:12.950+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/pathVariableTest/aAa/3"
}
注意:PathVariable 只有正則表達(dá)式可達(dá)到校驗的目的,即只有正則表達(dá)式這一種驗證方式。
2. RequestParam校驗
- 在對應(yīng)的參數(shù)上添加校驗條件
@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";
}
嘗試使用非法值訪問
結(jié)果
{
"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(<generated>) ~[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消息體傳參窄潭,同樣可以定義校驗規(guī)則
- 在接口上設(shè)置參數(shù)校驗
注意:必須要將將注解Validated設(shè)置在參數(shù)上,在Ctroller類上的設(shè)置對RequestBody的校驗無效
@RequestMapping(value = "requestBodyTest")
public String requestBodyTest(@Validated @RequestBody User user) {
return "suc";
}
- 在RequestBody對應(yīng)的Bean上設(shè)置校驗條件
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;
}
嘗試使用非法值訪問
結(jié)果
{
"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]] ]