说明:
(1)本篇博客的逻辑:
● 为什么写本篇博客?:在【Spring Boot电商项目23:商品分类模块二:【增加目录分类】接口;(接收请求中的、放在body中的参数时候,使用了@RequestBody;)】中,Controller处接收参数的时候,当我们通过AddCategoryReq这个bean接收到参数后,我们需要校验下参数是否为空;在这篇博客中,我们采用笨笨的方式去校验;
显然,在多时候我们都需要进行参数校验;比如上面的非空检验等;而,为了能够更加优雅的实现参数校验,于是就引出了本篇博客介绍的@Valid注解;
● 但是,在使用@Valid注解时候,引入的一个新问题:但是,在使用@Valid参数校验时候,如果校验失败,其引发的异常是【MethodArgumentNotValidException异常】;但是,我们在GlobalExceptionHandler中并没有特别处理这种异常(而是用Exception这种粗粒度的方式,去处理了),所以就出现了返回信息太宽泛,没有反映出具体错误信息的情况;
● 解决策略(这也是本篇博客重难点):在GlobalExceptionHandler编写对应的方法去处理【MethodArgumentNotValidException异常】,以能根据【MethodArgumentNotValidException异常的具体错误信息】去构建对应的APIRestResponse统一返回对象 ;(这其中涉及到了如【getBindingResult()】、【BindingResult.hasErrors()】、【BindingResult.getAllErrors()】、【objectError.getDefaultMessage()】等与Validation校验异常相关的方法)
目录
一:参数校验的注解:【@Valid】,【@NotNull,@Max(value),@Size(max,min)】:简述;
二:参数校验的注解:【@Valid】,【@NotNULL,@Max(value),@Size(max,min)】:案例演示;
1.【@Valid】,【@NotNULL,@Max(value),@Size(max,min)】:使用案例;
2.启动项目,实测;以及引出新的问题(参数校验引发的【MethodArgumentNotValidException异常】没有去单独处理);
(2)仍存问题:系统异常处理粒度太大:没有去单独处理参数校验引发的【MethodArgumentNotValidException异常】;
(1)方法说明:拦截【MethodArgumentNotValidException异常】,打印日志,去构建ApiRestResponse统一返回对象;
(2)【getBindingResult()】说明(不准确,可能存在错误);
(4)【BindingResult.hasErrors()】:bindingResult.hasErrors()是为了验证@Validated后面bean 里是否有不符合校验条件的错误信息;
(5)【BindingResult.getAllErrors()】(方法返回值类型是【List】):获取参数校验时的,所有错误;
(6)【ObjectError】:可以理解为是一个【封装了Validation校验错误】的对象;(理解,可能不准确……)
(7)【getDefaultMessage()】:获取错误的具体信息;
(8)方法说明:提取错误信息,将其添加到一个List集合中;
(9)方法说明:根据从【MethodArgumentNotValidException异常】中,提取的具体错误信息,构建ApiRestResponse统一返回对象;
(2)完善:设置为空时,具体的信息:@NotNull(message="***不能为空");
一:参数校验的注解:【@Valid】,【@NotNull,@Max(value),@Size(max,min)】:简述;
说明:
(1)如果我们在Controller处,给某个入参添加上@Valid注解,就表示这个入参需要校验;@Valid注解就像一个开关一样,用了这个注解就表示开启校验,不用这个注解就表示不用校验;
(2)@NotNULL,@Max(value),@Size(max,min)表示了校验规则;可以根据校验需求,在对应的属性上,使用这些注解;
(3)单纯看这些描述,可能云里雾里;具体,看下下面的案例;
二:参数校验的注解:【@Valid】,【@NotNULL,@Max(value),@Size(max,min)】:案例演示;
1.【@Valid】,【@NotNULL,@Max(value),@Size(max,min)】:使用案例;
说明:
(1)Spring Boot2.3版本将不再内部依赖validator;所以对于2.3以后的版本,如果还想使用@Valid参数校验,需要自己先手动引入validator依赖。
2.启动项目,实测;以及引出新的问题(参数校验引发的【MethodArgumentNotValidException异常】没有去单独处理);
(1)测试结果:参数校验生效了;
看下控制台的异常日志信息:
org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [1] in public com.imooc.mall.common.ApiRestResponse com.imooc.mall.controller.CategoryController.addCategory(javax.servlet.http.HttpSession,com.imooc.mall.model.request.AddCategoryReq): [Field error in object 'addCategoryReq' on field 'name': rejected value [测试类别1额方法地方]; codes [Size.addCategoryReq.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [addCategoryReq.name,name]; arguments []; default message [name],5,2]; default message [个数必须在2和5之间]] at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:139) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) [spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) [spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
日志信息,很明确:
至此,说明参数校验已经生效了;
……………………………………………………
(2)仍存问题:系统异常处理粒度太大:没有去单独处理参数校验引发的【MethodArgumentNotValidException异常】;
但是,还有个问题:上面出现了错误后,详细的提示信息只出现在了日志中,我们程序员是可以看到的;但是,我们这个商城的用户却不能知道具体的错误原因,商城的用户只能得到“系统异常”这个笼统的错误信息;