在开发中,经常会有各种校验的代码,而这些代码与业务逻辑无关,我们可以通过自定义校验注解来简化这些代码。
以下StringIn注解起到限制入参的作用,如我们数据库存储一个类型值只有"1"或者"2",对前端或者其余系统调用时传了约定以外的值进行校验。
- 添加 Hibernate-Validator 依赖
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
- 自定义注解
/**
 * Created by Jie on 2021/12/31 上午9:14
 */
@Documented
@Retention(RUNTIME)
@Repeatable(StringIn.List.class)
@Constraint(validatedBy = {StringInValidator.class})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
public @interface StringIn {
    String[] value() default {};
    Class<?>[] groups() default {};
    String message() default "";
    @SuppressWarnings("unused")
    Class<? extends Payload>[] payload() default {};
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        StringIn[] value();
    }
}
- 编写校验类
/**
 * Created by Jie on 2021/12/31 上午9:19
 */
public class StringInValidator implements ConstraintValidator<StringIn, String> {
    private List<String> valueList;
    @Override
    public void initialize(StringIn constraintAnnotation) {
        valueList = Arrays.asList(constraintAnnotation.value());
    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        return valueList.contains(value);
    }
}
由于该框架抛出异常格式令人吐槽,可编写全局异常处理器来解析并返回更合理的格式。
/**
 * Created by Jie on 2021/12/31 上午10:02
 */
@RestControllerAdvice
public class ValidateExceptionHandler {
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult()
                .getAllErrors()
                .stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(""));
        return new Result(200, message);
    }
}
测试:
@Data
public class TestEntity {
    private String id;
    @StringIn(value = {"1", "2"}, message = "name值不在给定范围内!", groups = AddGroup.class)
    private String name;
}
/**
 * Created by Jie on 2021/12/30 下午8:18
 */
@RestController
@RequestMapping("/test")
public class TestController {
    @PostMapping("/testAdd")
    public Result testAdd(@RequestBody @Validated(value = AddGroup.class) TestEntity entity) {
        return new Result(200, "添加成功", null);
    }
}
该方式可自由扩展,甚至可用到Spel表达式进行校验,此种方法在service中能完全告别参数校验相关的代码。










网友评论