@NotBlank(message = “{xxx}“) 注解中花括号的含义

【SpringBoot 实战】@NotBlank(message = "{auth.clientid.not.blank}") 花括号里的是什么?

一、问题场景

最近在看项目的登录代码 LoginBody.java,发现一个很有意思的写法:

复制代码
@NotBlank(message = "{auth.clientid.not.blank}")
private String clientId;

以前我写的校验注解都是这样的:

复制代码
@NotBlank(message = "客户端ID不能为空")
private String clientId;

为什么要用花括号 {} 包起来?直接写文案不好吗? "auth.clientid.not.blank" 这一串是啥意思?


二、答案:这是国际化(i18n)的消息配置写法

花括号 {} 包裹的内容是一个 消息键(Message Key),它的作用是:

告诉校验框架:别直接把 {auth.clientid.not.blank} 当错误文案返回,而是去国际化资源文件中查找对应 key 的实际文案。

用一张图理解:

复制代码
前端传参 clientId 为空
        │
        ▼
@NotBlank 校验失败
        │
        ▼
看到 message = "{auth.clientid.not.blank}"
        │
        ▼
去 messages_zh_CN.properties 找 key
        │
        ├── key: auth.clientid.not.blank = 认证客户端id不能为空
        │
        ▼
返回给前端:认证客户端id不能为空

三、项目中的实际配置

在 SpringBoot 项目的 resources 目录下,通常会有几个 properties 文件:

文件名 语言环境 内容示例
messages.properties 默认(中文) auth.clientid.not.blank=认证客户端id不能为空
messages_zh_CN.properties 简体中文 auth.clientid.not.blank=认证客户端id不能为空
messages_en_US.properties 英文 auth.clientid.not.blank=Auth clientid cannot be blank
messages_ja_JP.properties 日文 auth.clientid.not.blank=認証クライアントIDは空にできません

**校验框架会根据当前请求的语言(请求头 Accept-Language)自动选择对应的文件:

请求头 Accept-Language 返回的错误信息
zh-CN,zh;q=0.9 认证客户端id不能为空
en-US,en;q=0.9 Auth clientid cannot be blank
ja-JP,ja;q=0.9 認証クライアントIDは空にできません

四、两种写法的对比

写法 示例 优缺点
硬编码 @NotBlank(message = "客户端id不能为空") ✅ 写起来简单 ❌ 不支持多语言 ❌ 改文案要改 Java 代码
消息键(推荐) @NotBlank(message = "{auth.clientid.not.blank}") ✅ 支持多语言切换 ✅ 改文案只改 properties 文件 ✅ 文案统一管理,不会漏改 ❌ 多写一层配置

五、花括号语法从哪来的?

这不是 Spring 独创的,而是 **JSR-303 / JSR-380(Bean Validation)规范定义的标准语法:

语法 含义
message = "xxx" 直接返回字符串
message = "{xxx}" 去资源文件查找 key 对应的值
message = "{xxx} {yyy}" 支持拼接,两个 key 都会解析
message = "长度必须在 {min} 到 {max} 之间" 甚至可以引用注解参数

比如 @Size 注解可以这样用:

复制代码
@Size(min = 2, max = 10, message = "用户名长度必须在 {min} 到 {max} 之间")
private String username;

校验失败时会自动替换:

复制代码
用户名长度必须在 2 到 10 之间

六、SpringBoot 中怎么配置?

1. 新建国际化资源文件

在 resources/i18n/ 目录下(或者直接 resources/):

复制代码
resources/
├── messages.properties         # 默认
├── messages_zh_CN.properties
└── messages_en_US.properties
2. 在 application.yml 配置:
复制代码
spring:
  messages:
    basename: i18n/messages   # 如果在 i18n 目录下
    encoding: UTF-8
3. 配置 LocaleResolver(可选,基于请求头切换语言)
复制代码
@Configuration
public class I18nConfig {

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
        resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return resolver;
    }
}

这样前端在 DTO 上直接用:

复制代码
@NotBlank(message = "{user.username.not.blank}")
private String username;

七、总结

问题 答案
{auth.clientid.not.blank} 是什么? 国际化资源文件中的 **消息 key
为什么用花括号? JSR-303 规范的语法,告诉框架去解析 key
好处是什么? 支持多语言、文案统一管理、改文案不用改代码
相关推荐
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi3 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号3 天前
java函数式编程--入门基础
java·编程·函数式编程