SpringBoot参数校验-解决一些相同字段不同校验逻辑的校验

2019-12-11  本文已影响0人  Java及SpringBoot

个人专题目录


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的国际化,下篇文章再详细介绍。

上一篇下一篇

猜你喜欢

热点阅读