人世繁华|请不要在Java开发中再使用判断进行参数校验了( 二 )


publicenumColors{RED,YELLOW,BLUE}【人世繁华|请不要在Java开发中再使用判断进行参数校验了】我们希望入参不能超出Colors的范围["RED","YELLOW","BLUE"] , 这就需要实现ConstraintValidator接口来定义一个颜色约束了 , 其中泛型A为自定义的约束注解 , 泛型T为入参的类型 , 这里使用字符串,然后我们的实现如下:
/***@authorfelord.cn*@since17:57**/publicclassColorConstraintValidatorimplementsConstraintValidator{privatestaticfinalSetCOLOR_CONSTRAINTS=newHashSet<>();@Overridepublicvoidinitialize(ColorconstraintAnnotation){Colors[]value=https://pcff.toutiao.jxnews.com.cn/p/20200809/constraintAnnotation.value();Listlist=Arrays.stream(value).map(Enum::name).collect(Collectors.toList());COLOR_CONSTRAINTS.addAll(list);}@OverridepublicbooleanisValid(Stringvalue,ConstraintValidatorContextcontext){returnCOLOR_CONSTRAINTS.contains(value);}}然后声明对应的约束注解@Color , 需要在元注解@Constraint中指明使用上面定义好的处理类ColorConstraintValidator进行校验 。
/***@authorfelord.cn*@since17:55**/@Constraint(validatedBy=ColorConstraintValidator.class)@Documented@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE})@Retention(RetentionPolicy.RUNTIME)public@interfaceColor{//错误提示信息Stringmessage()default"颜色不符合规格";Class>[]groups()default{};ClassextendsPayload>[]payload()default{};//约束的类型Colors[]value();}然后我们来试一下 , 先对参数进行约束:
@DatapublicclassParam{@Color({Colors.BLUE,Colors.YELLOW})privateStringcolor;}接口跟上面几个一样 , 调用下面的接口将抛出BindException异常:
GET/student/color?color=CAYHTTP/1.1Host:localhost:8888当我们把参数color赋值为BLUE或者YELLOW后 , 能够成功得到响应 。
4.2常见问题在实际使用起来我们会遇到一些问题 , 这里总结了一些常见的问题和处理方式 。
检验基础类型不生效的问题上面为了校验颜色我们声明了一个Param对象来包装唯一的字符串参数color , 为什么不直接使用下面的方式定义呢?
@GetMapping("/color")publicRest>color(@Valid@Color({Colors.BLUE,Colors.YELLOW})Stringcolor){returnRestBody.okData(color);}或者使用路径变量:
@GetMapping("/rest/{color}")publicRest>rest(@Valid@Color({Colors.BLUE,Colors.YELLOW})@PathVariableStringcolor){returnRestBody.okData(color);}上面两种方式是不会生效的 。 不信你可以试一试 , 起码在SpringBoot2.3.1.RELEASE是不会直接生效的 。
使以上两种生效的方法是在类上添加@Validated注解 。 注意一定要添加到方法所在的类上才行 。 这时候校验失败会抛出ConstraintViolationException异常 。
集合类型参数中的元素不生效的问题就像下面的写法 , 方法的参数为集合时 , 如何检验元素的约束呢?
/***集合类型参数元素.**@paramstudentthestudent*@returntherest*/@PostMapping("/batchadd")publicRest>batchAddStudent(@Valid@RequestBodyListstudent){returnRestBody.okData(student);}同样是在类上添加@Validated注解 。 注意一定要添加到方法所在的类上才行 。 这时候校验失败会抛出ConstraintViolationException异常 。
嵌套校验不生效嵌套的结构如何校验呢?打个比方 , 如果我们在学生类Student中添加了其所属的学校信息School并希望对School的属性进行校验 。
@DatapublicclassStudent{@NotBlank(message="姓名必须填")privateStringname;@AgeprivateIntegerage;@NotEmpty(message="成绩必填")privateListscores;@NotNull(message="学校不能为空")privateSchoolschool;}@DatapublicclassSchool{@NotBlank(message="学校名称不能为空")privateStringname;@Min(value=https://pcff.toutiao.jxnews.com.cn/p/20200809/0,message="校龄大于0")privateIntegerage;}当GET请求时正常校验了School的属性 , 但是POST请求却无法对School的属性进行校验 。 这时我们只需要在该属性上加上@Valid注解即可 。