@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
好处是什么? 支持多语言、文案统一管理、改文案不用改代码
相关推荐
fīɡЙtīиɡ ℡1 小时前
内存泄漏产生的原因
java·spring·servlet
码智社2 小时前
Java实现RSA密钥生成、加密解密、加签验签
java
wear工程师2 小时前
ThreadLocal 在线程池里为什么会串数据:别只会答内存泄漏
java·后端
Iruoyaoxh2 小时前
栈和队列~
java·开发语言
审小匠OpenCPAi3 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
码上上班3 小时前
docker课程
java·docker·容器
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
达子6663 小时前
第9章_HarmonyOs图解 用Java开发UI
java·ui·harmonyos
龙虾PRO5 小时前
能源与股票量化核心差异,AI全链路落地实操手册
java·面试·职场和发展