当前位置: 首页 > 后端技术 > Java

SpringBoot参数校验和组校验的使用

时间:2023-04-01 19:19:42 Java

介绍:在web开发中,基本上每个接口都需要校验参数。参数越少越容易处理。一旦参数多了,代码里面就会有很多if-else语句。这种方式虽然简单直接,但是会大大降低开发效率和代码可读性。所以我们可以使用验证器组件来代替我们不必要的编码操作。本文将以验证者的介绍资料为主,同时结合笔者自身在项目中的实际使用经验进行总结。作者|江颜出处|阿里技术公众号前言做web开发有一件很烦人的事情就是对前端输入参数进行校验。基本上每个接口都需要对参数进行校验,比如一些非空校验,Format校验等,参数少的话好办,但是参数多了就会出现大量的if-else代码中的语句。虽然使用这种方法简单直接,但也有缺点。一来会降低开发效率,因为我们需要验证的参数会存在很多地方,不同的地方会重复验证,二来会降低代码的可读性,因为业务代码中夹杂了太多多余的工作代码。所以我们可以使用验证器组件来代替我们不必要的编码操作。这篇文章是根据验证者的介绍信息,也是结合我在项目中的实际经验总结出来的,希望对大家有所帮助。1什么是validatorBeanValidation是Java定义的一套基于注解的数据验证规范。从JSR303的1.0版本升级到JSR349的1.1版本,再到JSR380的2.0版本(2.0于2017.08完成)。已经出现了三个版本。需要注意的是,JSR只是一个标准,规定了验证注解的一些规范,但并未实现,比如@Null、@NotNull、@Pattern等,位于javax.validation.constraints包下.hibernatevalidator是这个规范的实现,并添加了一些其他的验证注解,比如@NotBlank、@NotEmpty、@Length等,位于org.hibernate.validator.constraints包下。如果我们的项目使用的是SpringBoot,那么在spring-boot-starter-web中已经集成了hibernatevalidator框架,所以不需要再添加其他依赖。如果不是SpringBoot项目,需要添加如下依赖。二、注解介绍1validator内置注解hibernatevalidator扩展了以下注解的定义:3、使用起来比较简单,使用注解。具体分为单参数验证和对象参数验证。单参数校验是指controller接口根据单个参数接收前端值,不带封装对象接收。如果有封装对象,就是对象参数验证。1单参数验证单参数验证只需要在参数前加上注解,如下所示:publicResultdeleteUser(@NotNull(message="idcannotbeempty")Longid){//dosomething}但是有需要注意的一点是,如果使用单参数验证,必须在controller类中添加@Validated注解,如下所示:@RestController@RequestMapping("/user")@Validated//需要添加的注解对于单参数验证publicclassUserController{//dosomething}2对象参数验证使用对象参数验证时,需要先在对象的验证属性上添加注解,然后在对象参数前添加@Validated注解控制器方法,如下所示:@NotNull私有整数年龄;...}注解在对象参数校验场景中是分组的,有一种特殊的场景就是同一个参数对象在不同的??场景下有不同的校验规则。比如创建对象时不需要传入id字段(id字段为主键,系统生成,用户不指定),但是修改对象时必须传入id字段目的。在这种情况下,需要对注释进行分组。1)组件有一个默认组Default.class,那么我们可以再创建一个组UpdateAction.class,如下图:publicinterfaceUpdateAction{}2)在参数类中需要校验的属性上,添加groups属性注释:publicclassUserAO{@NotNull(groups=UpdateAction.class,message="idcannotbeempty")privateLongid;@NotBlank私有字符串名称;@NotNull私有整数年龄;...}如上图,表示只在UpdateAction组下勾选id字段,默认勾选name字段和age字段。然后,在controller的方法中,在@Validated注解中指定使用何种场景即可。如果不指定,则表示使用Default.class,如果使用其他组,则需要显示和指定。以下代码表示在addUser()接口中根据默认情况进行参数校验,在updateUser()接口中根据默认情况和UpdateAction分组联合校验参数。publicResultaddUser(@ValidatedUserAOuserAo){//dosomething}publicResultupdateUser(@Validated({Default.class,UpdateAction.class})UserAOuserAo){//dosomething}如果需要验证参数则对象嵌套有还有一个对象属性嵌套在对象中,嵌套的对象属性也需要校验,所以需要在对象属性上加上@Valid注解。publicclassUserAO{@NotNull(groups=UpdateAction.class,message="idcannotbeempty")privateLongid;@NotBlank私有字符串名称;@NotNull私有整数年龄;@ValidprivatePhone电话;……}publicclassPhone{@NotBlankprivateStringoperatorType;@NotBlankprivateStringphoneNum;}3错误信息的捕获参数验证失败后会抛出异常。我们只需要在全局异常处理类中捕获参数校验失败的异常,然后将错误信息添加到返回值中即可。捕获异常的方法如下,返回值Result是我们系统自定义的返回值类。@RestControllerAdvice(basePackages={"com.alibaba.dc.controller","com.alibaba.dc.service"})publicclassGlobalExceptionHandler{@ExceptionHandler(value={Throwable.class})ResulthandleException(Throwablee,HttpServletRequest请求){//异常处理}}需要注意的是,如果参数缺失抛出的异常是MissingServletRequestParameterException,单参数校验失败后抛出的异常是ConstraintViolationException,get请求的对象参数校验失败后抛出的异常是BindException,post请求的对象参数校验失败后抛出的异常是MethodArgumentNotValidException,不同的异常对象的结构不同,提取异常信息的方法也不同。如下图所示:1)MissingServletRequestParameterExceptionif(einstanceofMissingServletRequestParameterException){Resultresult=Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);Stringmsg=MessageFormat.format("缺失参数{0}",((MissingServletRequestParameterException)e).getParameterName());结果.setMessage(味精);returnresult;}2)ConstraintViolationException异常if(einstanceofConstraintViolationException){//单个参数校试异常Resultresult=Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);Set>sets=((ConstraintViolationException)e).getConstraintViolations();if(CollectionUtils.isNotEmpty(sets)){StringBuildersb=newStringBuilder();sets.forEach(error->{if(errorinstanceofFieldError){sb.append(((FieldError)error).getField()).append(":");}sb.append(error.getMessage()).追加(“;”);});字符串消息=sb.toString();msg=StringUtils.substring(msg,0,msg.length()-1);结果.setMessage(味精);}returnresult;}3)BindException异常if(einstanceofBindException){//获取请求的对象参数校数异常Resultresult=Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);Listerrors=((BindException)e).getBindingResult().getAllErrors();Stringmsg=getValidExceptionMsg(错误);如果(StringUtils.isNotBlank(msg)){result.setMessage(msg);}返回结果;}privateStringgetValidExceptionMsg(Listerrors){if(CollectionUtils.isNotEmpty(errors)){StringBuildersb=newStringBuilder();errors.forEach(error->{if(errorinstanceofFieldError){sb.append(((FieldError)error).getField()).append(":");}sb.append(error.getDefaultMessage()).追加(“;”);});字符串消息=sb.toString();msg=StringUtils.substring(msg,0,msg.length()-1);返回消息;}returnnull;}4)MethodArgumentNotValidException异常if(einstanceofMethodArgumentNotValidException){//post请求对象参数验证异常Resultresult=Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);Listerrors=((MethodArgumentNotValidException)e).getBindingResult().getAllErrors();Stringmsg=getValidExceptionMsg(错误);if(StringUtils.isNotBlank(msg)){result.setMessage(msg);}returnresult;}《一站式大数据开发治理DataWorks使用宝典》官方电子书开放下载DataWorks官方入门电子书发布,零基础入门大数据开发与管理,全面了解DataWorks十大功能模块,快速上手DataWorks核心功能,点此下载~版权声明:本文内容由阿里云实名注册用户投稿,版权归原作者所有。阿里云开发者社区不拥有其版权,不承担相应的法律责任。具体规则请参考《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如发现本社区涉嫌抄袭内容,请填写侵权投诉表进行举报,一经查实,本社区将立即删除涉嫌侵权内容。