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

能否覆盖Spring Validator的默认校验消息以统一自定义提示?

能否覆盖Spring Validator的默认校验消息以统一自定义提示?

当然可以!你完全不用在每个@NotBlank注解里重复写相同的消息,有两种简单优雅的方式实现全局统一配置:

方法一:使用全局校验消息配置文件

Spring Validator(底层默认依赖Hibernate Validator)会自动读取classpath下的ValidationMessages.properties文件,我们可以在这个文件里直接覆盖内置校验注解的默认消息,一步搞定全局统一。

操作步骤:

  1. 在项目的src/main/resources目录下创建ValidationMessages.properties文件(Spring Boot项目建议在application.properties里配置spring.messages.encoding=UTF-8,避免中文或特殊字符乱码)。

  2. 在文件中添加以下内容,覆盖@NotBlank的默认提示:

    javax.validation.constraints.NotBlank.message = {propertyPath} is mandatory
    

    这里的{propertyPath}是Hibernate Validator提供的内置变量,会自动替换为校验失败的字段名(比如projectName、maintainerEmail)。

  3. 简化你的POJO代码,直接使用无参数的@NotBlank注解即可:

    public class Project {
        @NotBlank
        private String projectName;
        @NotBlank
        private String maintainerName;
        @NotBlank
        private String maintainerEmail;
        // 其他字段和方法
    }
    
  4. 优化全局异常处理器:现在消息已经自动包含字段名,无需手动用String.format替换,代码可以更简洁:

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.validation.DefaultMessageSourceResolvable;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import java.util.stream.Collectors;
    
    @ControllerAdvice
    public class GlobalExceptionHandler {
        private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
            log.warn("Validation failed: {}", e.getMessage());
            String errorMessages = e.getBindingResult()
                    .getAllErrors()
                    .stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.joining(", "));
            return new ResponseEntity<>(errorMessages, HttpStatus.BAD_REQUEST);
        }
    }
    

配置完成后,当字段为空时,返回的错误消息会自动是projectName is mandatory这类格式,彻底告别重复写消息的繁琐。

方法二:自定义校验注解(适合更灵活的场景)

如果以后你需要扩展校验规则,或者想给统一的校验逻辑起个更语义化的名字(比如@Mandatory),可以自定义一个继承@NotBlank的注解,内置默认消息:

操作步骤:

  1. 创建自定义注解:

    import javax.validation.Constraint;
    import javax.validation.Payload;
    import javax.validation.constraints.NotBlank;
    import java.lang.annotation.*;
    
    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = {}) // 直接复用@NotBlank的校验逻辑,无需自定义校验器
    @NotBlank(message = "{propertyPath} is mandatory")
    public @interface Mandatory {
        // 继承@NotBlank的必要属性
        String message() default "{propertyPath} is mandatory";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    
  2. 在POJO中使用自定义注解:

    public class Project {
        @Mandatory
        private String projectName;
        @Mandatory
        private String maintainerName;
        @Mandatory
        private String maintainerEmail;
        // 其他字段和方法
    }
    

这种方式的好处是,后续如果要调整校验规则或消息,只需要修改这个自定义注解,所有用到的地方都会自动生效,扩展性更强。

两种方法都能帮你摆脱重复写消息的麻烦,根据你的实际需求选择就行~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:54:32