Spring MVC 国际化机制详解(MessageSource 接口体系)
1. 核心接口与实现类详解
接口/类名 | 描述 | 功能特性 | 适用场景 |
---|---|---|---|
MessageSource | 核心接口,定义消息解析能力 | 支持参数化消息(如{0} 占位符) | 所有国际化场景的基础接口 |
ResourceBundleMessageSource | Spring 官方实现,基于 ResourceBundle | 支持缓存、自动加载属性文件(如messages_en.properties ) | 通用场景(推荐) |
StaticMessageSource | 内存中存储消息(非文件) | 动态注册消息(如运行时配置) | 单元测试或动态消息场景 |
ReloadableResourceBundleMessageSource | 增强版 ResourceBundleMessageSource | 支持热加载(无需重启)、编码指定(如encoding=UTF-8 ) | 需要动态更新消息的生产环境 |
CacheAwareContextControlMessageSource | 支持国际化上下文控制(如日期格式) | 结合 LocaleContextHolder 管理线程级本地化 | 需要复杂本地化控制的场景 |
2. 完整示例代码
2.1 配置类(Spring Boot)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
@Configuration
public class I18nConfig {
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
source.setBasename("classpath:i18n/messages"); // 属性文件前缀
source.setDefaultEncoding("UTF-8"); // 编码设置
source.setCacheSeconds(60); // 60秒后重新加载(热更新)
return source;
}
}
2.2 国际化属性文件
-
messages_en.properties
greeting=Hello, {0}! error=An error occurred: {0}
-
messages_zh.properties
greeting=你好,{0}! error=发生错误:{0}
2.3 控制器示例
import org.springframework.context.MessageSource;
import org.springframework.web.bind.annotation.*;
import java.util.Locale;
@RestController
public class I18nController {
private final MessageSource messageSource;
public I18nController(MessageSource messageSource) {
this.messageSource = messageSource;
}
@GetMapping("/greeting")
public String greeting(@RequestHeader(value = "Accept-Language", required = false) Locale locale,
@RequestParam String name) {
// 根据 locale 解析消息
String message = messageSource.getMessage("greeting", new Object[]{name}, locale);
return message;
}
@ExceptionHandler(Exception.class)
public String handleException(Exception ex, Locale locale) {
return messageSource.getMessage("error", new Object[]{ex.getMessage()}, locale);
}
}
2.4 测试请求
# 中文请求
curl -H "Accept-Language: zh-CN" "http://localhost:8080/greeting?name=张三"
# 输出:你好,张三!
# 英文请求
curl -H "Accept-Language: en-US" "http://localhost:8080/greeting?name=John"
# 输出:Hello, John!
3. Spring Boot 国际化配置项整理
配置项 | 作用 | 默认值 | 示例 |
---|---|---|---|
spring.messages.basename | 消息属性文件前缀(路径) | messages | classpath:i18n/messages |
spring.messages.encoding | 文件编码 | UTF-8 | GBK |
spring.messages.cache-duration | 热加载间隔(仅 Reloadable 实现生效) | 7200s (2小时) | 60s |
spring.http.accept-language.header | 自定义语言头名称 | Accept-Language | X-Language |
spring.mvc.locale | 默认语言 | 由系统 Locale 决定 | en |
spring.mvc.fallback-locale | 备用语言 | en | zh |
4. 关键代码注释说明
-
ReloadableResourceBundleMessageSource
配置source.setCacheSeconds(60); // 60秒后自动重新加载属性文件(无需重启)
-
控制器中解析消息
// 参数顺序:消息键、参数数组、当前Locale messageSource.getMessage("greeting", new Object[]{name}, locale);
-
属性文件占位符语法
greeting=Hello, {0}! // {0} 表示第一个参数(name)
5. 总结表格:MessageSource 实现对比
实现类 | 特性 | 适用场景 | 配置复杂度 |
---|---|---|---|
ResourceBundleMessageSource | 基础实现,无缓存 | 简单项目 | 低 |
ReloadableResourceBundleMessageSource | 支持热加载、编码指定 | 需要动态更新的生产环境 | 中 |
StaticMessageSource | 内存存储,动态注册消息 | 单元测试或动态消息 | 高 |
CacheAwareContextControlMessageSource | 支持线程级本地化上下文 | 需要复杂本地化控制(如日期格式) | 高 |
6. 常见问题
-
Q:如何自定义语言切换参数?
A:通过@Configuration
注册LocaleResolver
,例如从请求参数lang
获取语言:@Bean public LocaleResolver localeResolver() { AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver(); resolver.setDefaultLocale(Locale.US); resolver.setLanguageAttribute("lang"); // 从请求参数 lang 获取 return resolver; }
-
Q:属性文件路径错误如何排查?
A:确保文件位于src/main/resources/i18n/
目录,名称格式为messages_{language}.properties
。
提示:国际化配置建议与前端框架(如 Thymeleaf)结合,通过 <spring:message>
标签直接渲染消息。