Resource 与 MessageSource 国际化

引言

读取配置文件、模板、证书时,路径写法(classpath? 文件系统? URL?)五花八门;给用户看的提示要随语言切换。Spring 用 Resource 统一“资源位置”,用 MessageSource 统一“按 code 取文案”。本章解决这两个日常刚需。

核心概念

  • Resource(org.springframework.core.io.Resource):资源抽象,getInputStream()exists()getFilename()getDescription() 等;常见实现 ClassPathResourceFileSystemResourceUrlResource
  • 资源前缀classpath:(类路径根)、file:(文件系统)、url:(远程 URL,如 https 前缀按 UrlResource 处理);无前缀按实现默认策略。
  • ResourceLoader / ResourcePatternResolverApplicationContext 本身是 ResourceLoaderctx.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);
    }
}

注意点

  • MessageSource Bean 名称必须叫 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,语言切换交给框架——提示文案从此告别硬编码。

笔记加载中…