本文转载请联系JAVA日之鹿公众号。对于web服务,为了防止非法参数影响业务,必须在Controller层对参数进行校验!本章我们以SpringBoot项目为例,介绍参数校验的基本用法和一些高级技巧,希望对大家有所帮助。简单使用1.要在Springboot项目中添加参数验证功能,首先要添加spring-boot-starter-validation依赖于org.springframework.bootspring-boot-启动器验证2。然后在需要校验的字段上加上约束注解,比如我们校验实体类参数@DatapublicclassValidEntity{privateintid;@NotBlankprivateStringappId;@NotBlankprivateStringname;@EmailprivateStringemail;}常用的约束注解如下:注解函数@AssertFalse可以为null,如果不为null,必须为false@AssertTrue可以为null,不为null,必须为true@DecimalMax设置不能超过最大值@DecimalMin设置不能超过最小值@Digits设置必须是一个数字并且整数的位数和小数位数必须在指定范围内@Futuredate必须在当前日期的未来日期@Pastdate必须在当前日期的过去@Max不得超过此最大值价值@Min最大值不能小于这个最小值@NotNull不能为null,可以为空@Null必须为null@Pattern必须满足指定的正则表达式@Size集合、数组、映射等的size()值。mustbeinthespecifiedrange@Emailmustbeemailformat@Lengthlengthmustbeinthespecifiedrange@NotBlankstringcannotbenull,andstringtrim()cannotbeequalto""@NotEmptycannotbenull,size()ofcollections,arrays,maps等不能为0;stringtrim()可以等于""@Range值必须在指定范围内@URL必须是URL注意:本表只是简单描述注解函数,不解释每个注解的属性;您可以查看源代码3了解详细信息。在Controller层需要参数校验的方法上添加@Validated注解一般分为两类:当Controller使用模型接收数据时,@Validated注解可以直接放在模型参数的前面。当我们直接在Controller层中的参数前,使用约束注解时,@Validated应该直接放在类上@PostMapping(value="test2")publicStringtest2(@EmailStringemail){return"test2validsuccess";}这时候,@Validated需要在主类中添加注解@Validated@RestController@RequestMapping("/demo/valid")publicclassValidController{...}我们在验证参数时可以同时使用@Validated和@Valid注解。两者大部分功能相似;主要区别是:@Valid属于javax,而@Validated属于spring;@Valid支持嵌套验证,@Validated不支持,@Validated支持分组,@Valid不支持。统一的异常处理如果参数校验失败,Spring会抛出三种异常1、校验@RequestBody需要的参数时,直接校验具体参数时会出现org.springframework.web.bind.MethodArgumentNotValidExceptionJavax.validation.ConstraintViolationException,这也属于ValidationException。直接验证对象时,直接验证对象时会出现org.springframework.validation.BindException。在SpringBoot中统一拦截处理只需要在配置类上添加@RestControllerAdvice注解,然后在具体方法中通过@ExceptionHandler指定需要处理的异常。具体代码如下:@RestControllerAdvice@Slf4jpublicclassGlobalExceptionHandler{publicstaticfinalStringERROR_MSG="系统异常,请联系管理员。";@ExceptionHandler(value={BindException.class,ValidationException.class,MethodArgumentNotValidException.class})publicResponseEntity>handleValidatedException(Exceptione){Resultresp=null;if(einstanceofMethodArgumentNotValidException){//BeanValidationexceptionMethodArgumentNotValidExceptionex=(MethodArgumentNotValidException)e;resp=newResult<>(Integer.toString(HttpStatus.BAD_REQUEST.value()),ex.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(",")),getStackTrace(ex));}elseif(einstanceofConstraintViolationException){//BeanValidationGETsimpleparamConstraintViolationExceptionex=(ConstraintViolationException)e;resp=newResult<>(Integer.toString(HttpStatus.BAD_REQUEST.value()),例如。getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(",")),getStackTrace(ex));}elseif(einstanceofBindException){//BeanValidationGETobjectparamBindExceptionex=(BindException)e;resp=newResult<>(Integer.toString(HttpStatus.BAD_REQUEST.value()),ex.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(",")),getStackTrace(ex));}returnnewResponseEntity<>(resp,HttpStatus.BAD_REQUEST);}privateStringgetStackTrace(Exceptione){//打印日志开关,可以通过配置booleanprintSrackTrace=false读取;if(printSrackTrace){StringWritersw=newStringWriter();e.printStackTrace(newPrintWriter(sw));returnssw.toString();}else{returnERROR_MSG;}}}最终实现效果如下:参数组有如下实体class,我们需要进行参数校验@DatapublicclassValidEntity{privateintid;@NotBlankprivateStringappId;@NotBlankprivateStringname;@EmailprivateStringemail;}但是实际业务是编辑的时候需要appId,新增的时候需要name。这时候可以使用groups来分组功能来实现:同一个模型在不同场景下可以动态区分验证模型中的不同字段。如何使用首先我们定义一个分组接口ValidGroup,然后在分组接口中定义多个不同的操作类型,Create,Update,Query,DeletepublicinterfaceValidGroupextendsDefault{interfaceCrudextendsValidGroup{interfaceCreateextendsCrud{}interfaceUpdateextendsCrud{}interfaceQueryextendsCrud{}interfaceDeleteextendsCrud{}}}这里ValidGroup继承自Default,当然不需要继承。具体的区别我们后面再说。将组分配给模型中的验证参数@Data@ApiModel(value="ValidEntity")publicclassValidEntity{privateintid;@NotBlank(groups=ValidGroup.Crud.Update.class)privateStringappId;@NotBlank(groups=ValidGroup.Crud.Create.class)privateStringname;@EmailprivateStringemail;}tips:这里@Email注解没有指定组,默认属于Default组。如果appId和name指定了一个组,它将不再属于Default组。验证参数时,组由value属性指定。这里,具体的组由@Validated(value=ValidGroup.Crud.Update.class)指定。上面说的是否继承Default的区别在于:如果继承了Default,@Validated注解也会对未指定组或Default组的参数进行校验。比如email不继承Default,就不会校验未指定组的参数。需要添加@Validated(value={ValidGroup.Crud.Update.class,Default.class}会验证快速失败(FaliFast)。默认情况下,在验证参数时,SpringValidation会验证所有字段,然后抛出异常。可以通过配置开启FaliFast模式,一旦验证失败,立即返回。@ConfigurationpublicclassValidatedConfig{@BeanpublicValidatorvalidator(){ValidatorFactoryvalidatorFactory=Validation.byProvider(HibernateValidator.class).configure()//failfastmode.failFast(true).buildValidatorFactory();returnvalidatorFactory.getValidator();}}以上,希望对你有帮助!