Resource 与 MessageSource 国际化
引言
读取配置文件、模板、证书时,路径写法(classpath? 文件系统? URL?)五花八门;给用户看的提示要随语言切换。Spring 用 Resource 统一“资源位置”,用 MessageSource 统一“按 code 取文案”。本章解决这两个日常刚需。
核心概念
- Resource(org.springframework.core.io.Resource):资源抽象,
getInputStream()、exists()、getFilename()、getDescription()等;常见实现ClassPathResource、FileSystemResource、UrlResource。 - 资源前缀:
classpath:(类路径根)、file:(文件系统)、url:(远程 URL,如 https 前缀按 UrlResource 处理);无前缀按实现默认策略。 - ResourceLoader / ResourcePatternResolver:
ApplicationContext本身是ResourceLoader,ctx.getResource("classpath:app.properties");ResourcePatternResolver.getResources("classpath*:META-INF/*.factories")支持通配与classpath*:多位置扫描。 - MessageSource(org.springframework.context):国际化文案源,
getMessage(String code, Object[] args, Locale locale);ApplicationContext 自身实现该接口并委托给名为messageSource的 Bean。 - 实现类:
ResourceBundleMessageSource(基于 JDK ResourceBundle)、ReloadableResourceBundleMessageSource(支持热加载、可设编码);文案文件如messages.properties(默认)+messages_zh_CN.properties,按 locale 切换。 - 占位参数用 MessageFormat 风格
{0};也可调getMessage(code, args, defaultMessage, locale)给兜底文案。
代码示例
// 文案文件:messages.properties: order.created=订单 {0} 已创建,金额 {1}
// messages_zh_CN.properties: order.created=订单 {0} 已创建,金额 {1}
// messages_en_US.properties: order.created=Order {0} created, amount {1}
@Configuration
public class I18nConfig {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource ms =
new ReloadableResourceBundleMessageSource();
ms.setBasename("classpath:messages"); // 多个用逗号分隔
ms.setDefaultEncoding("UTF-8"); // 中文必须显式 UTF-8
ms.setCacheSeconds(60); // 生产可设为 -1 不刷新
return ms;
}
}
@Service
public class OrderNotice {
private final MessageSource messages; // 注入接口,容器注入 messageSource Bean
public OrderNotice(MessageSource messages) { this.messages = messages; }
public String createdText(String no, String amount) {
return messages.getMessage("order.created",
new Object[]{no, amount}, java.util.Locale.CHINA);
}
}
注意点
MessageSourceBean 名称必须叫messageSource,ApplicationContext 的委托才找得到(以官方文档为准)。- properties 文件默认按 ISO-8859-1 解读,中文务必
setDefaultEncoding("UTF-8")或写成\uXXXX转义。 Resource只抽象“位置”,真正读内容用getInputStream()+ try-with-resources,别忘关闭。- 通配
classpath*:与classpath:不同:前者扫描所有 classpath 根(多 jar 场景),后者只取第一个命中。 - Web 场景的 Locale 来自请求(LocaleResolver/LocaleContextHolder),Spring MVC 教程再展开。
小结
Resource 用“前缀 + 位置”统一了资源来源(classpath:/file:/url:),MessageSource 用“code + 参数 + locale”统一了国际化文案。配置一个 messageSource Bean + 多语言 properties,代码里只写 code,语言切换交给框架——提示文案从此告别硬编码。