为枚举类型编写自定义校验器的实际优势是什么?
枚举类自定义校验器的意义疑问
我实在搞不懂,给枚举类实现自定义校验器,比起直接在RestControllerAdvice里统一处理org.springframework.http.converter.HttpMessageNotReadableException异常,到底有啥实际好处?
按照网上示例的套路,每个枚举类都得写两个校验相关的类,代码量直接上去了,但我没看到错误处理方面的实际收益——比如注解里定义的默认提示"must be any of {anyOf};"根本没生效。那为啥不直接写个统一异常处理方法完事?
我照着枚举校验的示例在Spring Boot里写了测试代码:
枚举类定义
public enum GenderTypeEnum { MALE("male"), FEMALE("female"); private final String value; private GenderTypeEnum(String value) { this.value = value; } public String getGender(){ return this.value; } }
校验器实现类
import com.example.springbootenumvalidator.enums.GenderTypeEnum; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.Arrays; public class GenderTypeEnumValidator implements ConstraintValidator<ValidGenderTypeEnum, GenderTypeEnum> { private GenderTypeEnum[] subset; @Override public void initialize(ValidGenderTypeEnum constraint) { this.subset = constraint.anyOf(); } @Override public boolean isValid(GenderTypeEnum value, ConstraintValidatorContext context) { return value == null || Arrays.asList(subset).contains(value); } }
自定义校验注解
import com.example.springbootenumvalidator.enums.GenderTypeEnum; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = GenderTypeEnumValidator.class) public @interface ValidGenderTypeEnum { GenderTypeEnum[] anyOf(); String message() default "must be any of {anyOf}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
DTO类
import com.example.springbootenumvalidator.enums.GenderTypeEnum; import com.example.springbootenumvalidator.validator.ValidGenderTypeEnum; import lombok.*; @AllArgsConstructor @NoArgsConstructor @Getter @Setter @Builder public class UserDTO { @ValidGenderTypeEnum(anyOf = {GenderTypeEnum.MALE, GenderTypeEnum.FEMALE}) private GenderTypeEnum gender; }
控制层代码
import com.example.springbootenumvalidator.dto.UserDTO; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("api/v1") public class UserController { @GetMapping(path = "/user") @ResponseBody public ResponseEntity<?> getUser( @Valid @RequestBody UserDTO user ) { return ResponseEntity.ok().body(user); } }
配置文件
spring.jackson.mapper.accept-case-insensitive-enums=true
测试报错信息
2023-06-11T09:17:23.702+02:00 WARN 16912 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : 已解决异常 [org.springframework.http.converter.HttpMessageNotReadableException: JSON解析错误:无法将字符串"MALEXX"反序列化为类型`com.example.springbootenumvalidator.enums.GenderTypeEnum`,该枚举类的可接受值为:[FEMALE, MALE]]
内容的提问来源于stack exchange,提问作者Gianni Spear
相关产品推荐
相关产品推荐

