Spring MVC集成Freemarker本地化消息异常:空用户名提示缺失短名正常
看起来你遇到的是个典型的校验消息配置不匹配问题——空值校验的俄文消息找不到,但长度校验能正常显示。咱们一步步拆解原因,再给出解决办法:
核心原因分析
1. 校验注解的消息码规则不匹配
Spring的校验注解(比如@NotBlank/@NotNull/@Size)会生成一套默认的消息码优先级:
- 优先找
{注解名}.{表单对象名}.{字段名}(比如NotBlank.userForm.username) - 找不到就 fallback 到
{注解名}.{字段名}(比如NotBlank.username) - 再找不到就用
{注解名}(比如NotBlank) - 如果你的注解手动指定了
message="{Required}",那会直接找Required这个键,不会走上面的优先级
你的情况是:
- 长度校验(
@Size)正常,说明Size.userForm.username或者Size键在俄文消息文件里存在 - 空值校验提示找不到
Required,要么是你注解里写了message="{Required}"但俄文文件里没这个键,要么是默认的NotBlank/NotNull系列键没配置
2. 消息源配置或文件问题
- 消息文件命名/位置不对:比如俄文消息文件应该叫
messages_ru.properties,放在src/main/resources下(classpath根目录),如果文件名错了或者路径不对,Spring读不到 - 编码问题:俄文消息文件必须用UTF-8编码,否则会出现读取失败或乱码
- 消息源配置缺失:比如没设置
defaultEncoding="UTF-8",或者basename没指向正确的消息文件前缀
3. Freemarker页面的错误渲染方式
如果页面里没有用Spring提供的spring.message()宏来解析错误消息,而是手动拼接,可能会跳过Spring的消息解析逻辑,导致找不到对应locale的消息。
具体解决步骤
第一步:检查实体类的校验注解
先看你的UserForm类里username字段的校验代码,比如:
// 错误示例:手动指定了message="{Required}",但消息文件里没这个键 @NotBlank(message = "{Required}") @Size(min = 6, message = "{Size.userForm.username}") private String username; // 推荐写法:用默认的注解消息码,让Spring自动匹配 @NotBlank @Size(min = 6) private String username;
如果是第一种手动指定{Required}的情况,直接在俄文消息文件里加Required=Введите обязательное поле;如果是默认写法,就加NotBlank.userForm.username=Имя пользователя не может быть пустым(或者通用的NotBlank=Поле не может быть пустым)。
第二步:修复消息配置文件
打开messages_ru.properties,添加对应俄文消息:
# 针对username字段的非空校验 NotBlank.userForm.username=Имя пользователя не может быть пустым # 通用非空校验(可选,作为fallback) NotBlank=Поле не может быть пустым # 你已经配置好的长度校验 Size.userForm.username=Имя пользователя должно содержать не менее 6 символов
注意:文件编码必须设为UTF-8,否则俄文会乱码。
第三步:确认消息源配置正确
检查WebConfig里的ReloadableResourceBundleMessageSource配置,确保:
@Bean public MessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); // 指向classpath下的messages前缀文件(messages.properties、messages_ru.properties等) messageSource.setBasenames("classpath:messages"); // 必须设置UTF-8编码,支持俄文 messageSource.setDefaultEncoding("UTF-8"); // 可选:关闭系统locale fallback,强制使用指定的locale messageSource.setFallbackToSystemLocale(false); return messageSource; }
第四步:检查Freemarker页面的错误渲染
确保页面里导入了Spring的FTL宏,并使用spring.message()来解析错误:
<#import "/spring.ftl" as spring> <#if bindingResult.hasErrors()> <div class="error-container"> <#list bindingResult.fieldErrors as error> <p class="error-text">${spring.message(error)}</p> </#list> </div> </#if>
不要手动拼接错误消息,让Spring的消息源自动根据当前locale解析对应的消息码。
第五步:验证消息文件是否被正确打包
检查项目编译后的target/classes目录下,是否存在messages_ru.properties,如果没有,说明文件位置不对,需要调整到src/main/resources下。
内容的提问来源于stack exchange,提问作者Roman

