@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.blankAuth clientid cannot be blankmessages_ja_JP.properties日文auth.clientid.not.blank認証クライアントIDは空にできません**校验框架会根据当前请求的语言请求头Accept-Language自动选择对应的文件请求头 Accept-Language返回的错误信息zh-CN,zh;q0.9认证客户端id不能为空en-US,en;q0.9Auth clientid cannot be blankja-JP,ja;q0.9認証クライアントIDは空にできません四、两种写法的对比写法示例优缺点硬编码NotBlank(message 客户端id不能为空)✅ 写起来简单❌ 不支持多语言❌ 改文案要改 Java 代码消息键推荐NotBlank(message {auth.clientid.not.blank})✅ 支持多语言切换✅ 改文案只改 properties 文件✅ 文案统一管理不会漏改❌ 多写一层配置五、花括号语法从哪来的这不是 Spring 独创的而是 **JSR-303 / JSR-380Bean 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.properties2. 在application.yml配置spring: messages: basename: i18n/messages # 如果在 i18n 目录下 encoding: UTF-83. 配置 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好处是什么支持多语言、文案统一管理、改文案不用改代码