个人专题目录
SpringBoot参数校验-解决一些相同字段不同校验逻辑的校验顺序问题
项目中遇到的问题
springBoot中对一些参数需要不同维度的校验逻辑,但是需要控制校验顺序,校验之间有先后顺序的依赖。
解决方案:使用JSR提供的@GroupSequence
注解控制校验顺序
分组验证
分组接口
public interface GroupRunCount {
}
/**
* JSR提供的@GroupSequence注解控制校验顺序
* 第二个组的约束验证依赖于第一个约束执行完成的结果
* 某个Group组的校验非常耗时,并且会消耗比较大的CPU/内存
* 一个组可以定义为其他组的序列,使用它进行验证的时候必须符合该序列规定的顺序。
* 在使用组序列验证的时候,如果序列前边的组验证失败,则后面的组将不再给予验证
*
* 本例中目的是想先验证属性上面的验证规则,然后再验证自定义验证规则
*/
@GroupSequence({Default.class, GroupRunCount.class})
public interface Group {
}
实体类
@Data
@TestParamCheck(groups = GroupRunCount.class)
public class TestParam {
@NotNull(message = "{MaxCountInvalidParameterValue}")
@Range(min = 1, max = 500, message = "{MaxCountInvalidParameterValue}")
private Integer maxCount;
@NotNull(message = "{MinCountInvalidParameterValue}")
@Range(min = 1, max = 500, message = "{MinCountInvalidParameterValue}")
private Integer minCount;
}
自定义验证注解
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = TestParamValidator.class)
@Documented
public @interface TestParamCheck {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
自定义注解处理类
public class TestParamValidator implements ConstraintValidator<TestParamCheck, TestParam> {
@Autowired
private QuotaService quotaService;
@Override
public void initialize(TestParamCheck constraintAnnotation) {
}
@Override
public boolean isValid(TestParam param, ConstraintValidatorContext context) {
Integer maxCount = param.getMaxCount();
Integer minCount = param.getMinCount();
if (maxCount != null && minCount != null) {
int quotaMax = quotaService.getMax();
String messageTemplate;
context.disableDefaultConstraintViolation();
if (maxCount > quotaMax) {
messageTemplate = "{MaxCountInvalidParameterValue}";
context.buildConstraintViolationWithTemplate(messageTemplate).addConstraintViolation();
return false;
} else if (minCount > quotaMax) {
messageTemplate = "{MinCountInvalidParameterValue}";
context.buildConstraintViolationWithTemplate(messageTemplate).addConstraintViolation();
return false;
}
}
return true;
}
}
功能测试
测试核心代码如下:
Controller
@RestController
@RequestMapping(value = "/", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
@Slf4j
public class TestController {
@RequestMapping
public void testAction(HttpServletRequest request, @Validated(TestParam.Group.class)) {
log.info("param={}", param);
}
}
通过测试我们发现代码先验证属性上面的验证规则,然后再验证自定义验证规则,解决了顺序验证问题。
本文示例代码的验证错误消息都整合了Spring的国际化,怎么整合hibernate-validator验证和Spring验证并使用Spring的国际化,下篇文章再详细介绍。
网友评论