【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 |
| 好处是什么? | 支持多语言、文案统一管理、改文案不用改代码 |