You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为枚举类型编写自定义校验器的实际优势是什么?

枚举类自定义校验器的意义疑问

我实在搞不懂,给枚举类实现自定义校验器,比起直接在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:18:09