Spring Boot 2.0.1实现国际化时遇NoSuchMessageException求助
NoSuchMessageException问题 我来帮你一步步排查这个找不到消息的异常,这在Spring国际化配置里是很常见的问题,咱们从几个关键方向入手:
1. 先确认资源文件的命名与位置
Spring对国际化资源文件的命名有严格规范:[基础名]_[语言代码].properties,比如messages_en.properties。你需要检查:
- 资源文件是否确实放在
src/main/resources/translations目录下,文件名是否符合规范(比如如果你的基础名是translations,那英文文件应该是translations_en.properties;如果基础名是messages,那就是messages_en.properties放在translations目录下) - 文件名有没有拼写错误,比如
en必须是小写,后缀必须是.properties,不能写成.prop或者其他格式
2. 检查Spring配置类中的资源包路径
你的配置类必须正确指定资源包的位置,举个标准的配置示例供你参考:
@Configuration public class InternationalizationConfig implements WebMvcConfigurer { @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); // 这里的路径是resources下的相对路径,不需要加.properties后缀 // 比如你的文件是translations/messages_en.properties,就写"translations/messages" messageSource.setBasenames("translations/messages"); messageSource.setDefaultEncoding("UTF-8"); // 关闭系统Locale fallback,避免找不到时自动用系统语言 messageSource.setFallbackToSystemLocale(false); return messageSource; } @Bean public LocaleResolver localeResolver() { SessionLocaleResolver localeResolver = new SessionLocaleResolver(); localeResolver.setDefaultLocale(Locale.ENGLISH); return localeResolver; } }
重点:setBasenames里的路径是classpath下的相对路径,不能写错层级,也不需要加文件后缀。
3. 确认资源文件中存在对应的key
打开你的英文资源文件,检查是否有nav_home=xxx这样的键值对,注意key的拼写必须完全一致——包括大小写、下划线,比如nav_home不能写成navHome或者nav-home,多一个空格都不行。
4. 检查资源文件是否被正确打包
有时候IDE或Maven可能没把resources目录下的文件打包到编译后的classpath里:
- 在IntelliJ IDEA中,确认
src/main/resources被标记为「Resources Root」(右键目录→Mark Directory as→Resources Root) - 如果用Maven,确保pom.xml里的资源配置正确:
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> </includes> </resource> </resources> </build>
之后可以去target/classes/translations目录下看看,是否存在你的.properties文件。
5. 测试MessageSource是否能直接获取消息
先排除视图层的问题,在配置类或测试类中注入MessageSource直接测试:
@Autowired private MessageSource messageSource; public void testMessageLookup() { try { String homeText = messageSource.getMessage("nav_home", null, Locale.ENGLISH); System.out.println("获取到的消息:" + homeText); } catch (NoSuchMessageException e) { e.printStackTrace(); } }
如果这里能拿到消息,说明问题出在视图层的调用方式;如果还是报错,那就是资源包配置或文件本身的问题。
6. 确认Locale解析是否正确
有时候配置的LocaleResolver可能没生效,导致实际使用的Locale不是en。你可以在请求方法中打印当前Locale:
Locale currentLocale = LocaleContextHolder.getLocale(); System.out.println("当前使用的Locale:" + currentLocale);
如果打印的不是en,就要检查LocaleResolver的配置是否正确,或者请求中是否有正确传递Locale参数(比如通过lang=en的请求参数)。
内容的提问来源于stack exchange,提问作者xvercruysse

