导读
我们开发项目的时候,如何判断请求过来的参数非空,长度大小等情况,是不是在代码里面写非空判断,校验长度,如下代码。
非空判断代码
如果这个UserVO这个对象有10个字段都要做非空判断,那么这个代码就会变成很多且非常不优雅,那么我们就要想办法解决这个,因此spring为我们提供了validation框架,在springboot框架使用更加简单,validation框架都是已经整合到springboot中了。
新建一个springboot-validation项目
依赖包如下:
org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASEorg.springframework.boot spring-boot-starter-web org.projectlombok lombok
新建一个ResponseVO类
该类是统一返回Json格式封装类,例如要统一返回格式:
{ "code":"200", //状态码 "msg":"操作成功", //消息 "data":null //数据}
类如下:
/** * 统一响应VO */@Data@AllArgsConstructor@NoArgsConstructorpublic class ResponseVO { /** * 状态码 */ String code; /** * 状态信息 */ String msg; /** * 返回数据对象 */ T data; /** * 定义一个静态方法,返回成功状态码 * @return 响应对象 */ public static ResponseVO success(){ return new ResponseVO("200","操作成功",null); } /** * 定义一个静态方法,返回失败状态码,以及指定失败信息 * @param msg 失败信息 * @return 响应对象 */ public static ResponseVO fail(String msg){ return new ResponseVO("999",msg,null); }}
新建一个UserVO类
该类就用到了validation框架注解
import lombok.Data;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;@Datapublic class UserVO { @NotBlank(message = "用户名不能为空") String userName; @NotBlank(message = "密码不能为空") @Size(min = 6,message = "密码长度最小六位") String password; @NotNull(message = "年龄不能为空") Integer age;}
相关注解说明:
@AssertFalse
新建UserController类
@Controller@Slf4jpublic class UserController { /** * 新增用户对象 */ @GetMapping("addUser") @ResponseBody public ResponseVO addUser(@Validated UserVO userVO){ log.info("新增用户对象={}",userVO); //返回成功状态码 return ResponseVO.success(); }}
@Validated 是必须注解,就是把UserVO对象用validation框架校验参数,当提交数据的时候,会自动校验UserVO里面属性非空注解。
新建SpringBootValidApp启动类
@SpringBootApplicationpublic class SpringBootValidApp { public static void main(String[] args) { SpringApplication.run(SpringBootValidApp.class,args); }}
启动服务成功后,浏览器访问地址,设置请求参数空值测试
http://127.0.0.1:8080/addUser?userName=&password=&age=
发现控制台出现以下异常,说明校验生效了
2020-10-23 14:38:49.123 WARN 39904 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 4 errorsField error in object 'userVO' on field 'password': rejected value []; codes [NotBlank.userVO.password,NotBlank.password,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.password,password]; arguments []; default message [password]]; default message [密码不能为空]Field error in object 'userVO' on field 'password': rejected value []; codes [Size.userVO.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.password,password]; arguments []; default message [password],2147483647,6]; default message [密码长度最小六位]Field error in object 'userVO' on field 'userName': rejected value []; codes [NotBlank.userVO.userName,NotBlank.userName,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.userName,userName]; arguments []; default message [userName]]; default message [用户名不能为空]Field error in object 'userVO' on field 'age': rejected value [null]; codes [NotNull.userVO.age,NotNull.age,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.age,age]; arguments []; default message [age]]; default message [年龄不能为空]]
浏览器页面显示错误信息
Whitelabel Error PageThis application has no explicit mapping for /error, so you are seeing this as a fallback.Fri Oct 23 14:38:49 CST 2020There was an unexpected error (type=Bad Request, status=400).Validation failed for object='userVO'. Error count: 4
现在只是看到了校验失败信息,那么如何把错误信息返回到页面当中呢?这个是我们下面要解决的问题
新建一个全局异常类
该异常类核心用到了一个注解:@RestControllerAdvice,该数据就是监听Controller类如果有异常的时候,通知一下,然后使用:@ExceptionHandler,来处理特定异常,从而根据异常对象,解析异常信息,封装成:ResponseVO,返回到客户端。
/** * 全局公共异常帮助类 */@RestControllerAdvice@Slf4jpublic class GlobalExceptionHandler {/** * Get 非body请求 ,用BindException * @RequestBody @Valid 用MethodArgumentNotValidException * 校验参数异常,显示输出具体字段错误列表 */@ExceptionHandler(value= {BindException.class,MethodArgumentNotValidException.class})public Object validatorbindException(Throwable e,HttpServletRequest req){String uri=req.getRequestURI();log.error("请求URI={},校验参数不通过",uri);BindingResult bindingResult=null;if(e instanceof BindException) {bindingResult=((BindException)e).getBindingResult();}else if(e instanceof MethodArgumentNotValidException) {bindingResult=((MethodArgumentNotValidException)e).getBindingResult();}StringBuilder msg=new StringBuilder("");try {if(bindingResult.hasErrors()) {List fieldErrors=bindingResult.getFieldErrors();for (FieldError fieldError:fieldErrors) {msg.append(", ").append(fieldError.getDefaultMessage());log.error("请求URI={},字段={},校验信息={}",uri,fieldError.getField(),fieldError.getDefaultMessage());}msg.deleteCharAt(0);}} catch (Throwable tx) {log.error("转换校验参数异常",tx);}return ResponseVO.fail(msg.toString());}}
重新启动服务,重新做以上非空访问测试,页面显示如下信息,证明异常返回页面处理成功
{ "code":"999", "msg":" 密码长度最小六位, 用户名不能为空, 年龄不能为空, 密码不能为空", "data":null}
测试正常数据请求
访问地址:http://127.0.0.1:8080/addUser?userName=xiaoming&password=123456&age=12
测试结果:{ "code":"200", "msg":"操作成功", "data":null}
总结
Sringboot validation校验请求参数,大大简化了在代码里面做非空判断,大大的提高了工作效率,即优雅又漂亮的代码,从此再也不用加班了,你Get到了吗?如果有疑问,欢迎大家讨论或者与我沟通。