在开发中,经常会有各种校验的代码,而这些代码与业务逻辑无关,我们可以通过自定义校验注解来简化这些代码。
以下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中能完全告别参数校验相关的代码。
网友评论