Spring中的国际化消息

发布时间:2024年01月16日

摘要

本文详细介绍了Spring框架中国际消息化相关的内容,在Spring中国际化消息通过 MessageSource接口实现,而Spring为我们提供了ResourceBundleMessageSourceReloadableResourceBundleMessageSource两个实现类来实现具体的功能。通过合理使用这两个组件,我们能够构建出更加灵活、可扩展的多语言应用程序,满足不同地区和文化的用户需求。

正文

Spring项目中提供了地区消息(国际化消息)相关功能,可以根据不同地区获取到对应的消息数据。国际化消息功能通过 org.springframework.contex.MessageSource接口实现,Spring内部提供了以下两个实现类来满足不同需求

  1. ResourceBundleMessageSource会读取类路径下的messages*.properties文件,这个类也是Spring中默认值,不支持热加载(必须重启项目才能读取到新的资源)
  2. ReloadableResourceBundleMessageSource可以加载任何路径下的messages*.properties文件(除了类路径外还包括网络路径、系统文件路径等),支持热加载

除此之外,当没有主动配置MessageSource并且类路径下也没有messages.properties文件时,Spring默认提供一个Empty MessageSource名称的messageSource(类型为DelegatingMessageSource),表示没有国际化消息

ResourceBundleMessageSource

默认配置

ResourceBundleMessageSource底层基于jdk提供的 ResourceBundle实现,可以通过设置baseName的方式,设定消息文件的位置(基于类路径)。

可以在项目resources目录下新增一个 messages.properties文件内容如下

yaos.title=yaos项目标题

在Spring中直接注入 MessageSource接口来获取消息

@Component
public class ContextMessageComponent implements ApplicationRunner {
    private Logger logger= LoggerFactory.getLogger(ContextMessageComponent.class);
    
    @Resource
    private MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String message = messageSource.getMessage("yaos.title", null, Locale.getDefault());
        logger.info(message);
    }
}

这样即可读取到对应的消息

2024-01-16  15:30:37.885 [main] INFO  top.sunyog.spring.notes.message.ContextMessageComponent - yaos项目标题

MessageSource接口是为了应对国际化消息业务而存在的,因此通过它我们可以针对不同地区设置不同的消息内容,来满足国际化的需求。

在resources目录下新增 messages_zh.propertiesmessage_en.properties 两个文件分别对应中国、英国两个地区

messages_zh.properties文件内容如下

yaos.title=项目标题名称

messages_en.properties文件内容如下

yaos.title=project`s title name

重新启动以上代码可以发现输出内容变成了

2024-01-16  15:34:43.702 [main] INFO  top.sunyog.spring.notes.message.ContextMessageComponent - 项目标题名称

当把获取消息的地区修改为 Locale.English(以上java代码中的第 10 行)之后,输出内容变为了

2024-01-16  15:36:50.917 [main] INFO  top.sunyog.spring.notes.message.ContextMessageComponent - project`s title name

自定义消息路径

在实际应用中,由于受到很多限制,消息文件可能不能直接放到resources目录下,而是在一个固定的目录下,如 resources/WEB-INF/messages*.properties这个目录下,这时我们又将如何获取到对应的消息呢?

文件夹路径
|--resources
	|--WEB-INF
		|--messages.properties
		|--messages_zh.properties
		|--messages_en.properties

只需要通过配置,指定 ResourceBundleMessageSource需要读取的路径即可,可以简单使用如下配置

@Bean
public MessageSource messageSourceWeb(){
    ResourceBundleMessageSource res = new ResourceBundleMessageSource();
    res.setDefaultEncoding("UTF-8");
    //指定消息路径
    res.setBasename("WEB-INF/messages");
    return res;
}

这时只需要按名称注入 MessageSource类的Bean即可

@Component
public class ContextMessageComponent implements ApplicationRunner {
    private Logger logger= LoggerFactory.getLogger(ContextMessageComponent.class);

    @Resource(name = "messageSourceWeb")
    private MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String message = messageSource.getMessage("yaos.title", null, Locale.ENGLISH);
        logger.info(message);
    }
}

这样即可正确读取到消息

ReloadableResourceBundleMessageSource

基础用法

ResourceBundleMessageSource不同,ReloadableResourceBundleMessageSource底层基于SpringResource实现,使用它可以获得和 ResourceBundleMessageSource相同的效果。以下代码可以达到和上一节中的内容同样的效果

@Bean
public MessageSource messageSourceWeb(){
    ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
    res.setDefaultEncoding("UTF-8");
    //需要明确指定classpath
    res.setBasename("classpath:/WEB-INF/messages");
    return res;
}

除了支持类路径下的资源外,ReloadableResourceBundleMessageSource还支持读取网络资源或操作系统文件资源,只需要在 setBasename()方法中明确资源路径即可

以下代码可以读取网络资源

@Bean
public MessageSource messageSourceWeb(){
    ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
    res.setDefaultEncoding("UTF-8");
	//需要保证网络上的message*.properties文件能正确访问到
    res.setBasename("http://img.sunyog.top/files/messages");
    return res;
}

下列代码可以读取到系统文件路径内的资源

@Bean
...{
	res.setBasename("file:\\D:\\My\\temp\\files\\messages");
}...

扩展用法

除了以上这些基础用法之外,ReloadableResourceBundleMessageSource还支持热部署,即在项目运行过程中messages文件资源的修改可以热更新。

实现这一功能的秘诀在于 ReloadableResourceBundleMessageSource中提供的 clearCache()方法,这个方法用来更新消息缓存,即读取最新的消息内容。下面我们以一个HTTP请求来获取消息内容为例,来说明这一用法

@RestController
@RequestMapping("/test")
public class TestController {
    @Resource(name = "messageSourceA")
    private MessageSource messageSource;

    @GetMapping("/msg/title")
    public String msgTitle(){
        ((ReloadableResourceBundleMessageSource) this.messageSource).clearCache();
        String msg = this.messageSource.getMessage("yaos.title", null, Locale.getDefault());
        return msg;
    }

    @Bean
    public MessageSource messageSourceA(){
        ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
        res.setDefaultEncoding("UTF-8");
        res.setBasename("http://img.sunyog.top/files/messages");
        return res;
    }
}

每次发起 GET http://localhost:18080/test/msg/title这个请求都会刷新消息缓存,重新读取最新的消息,我们在img.sunyog.top这台服务器上创建messages_zh.properties文件,内容如下

yaos.title=网络内容标题

第一次请求结果

网络内容标题

修改服务器上的文件内容

yaos.title=网络内容标题123333

第二次发起HTTP请求,结果为

网络内容标题123333

总结

今天我们介绍了Spring中提供的国际化消息相关的内容,Spring中的国际化消息通过 MessageSource这个接口实现,其中Spring内置了 ResourceBundleMessageSourceReloadableResourceBundleMessageSource两个实现类来实现具体获取消息的功能,下表对比了这两个类的一些特征

功能特征ResourceBundleMessageSourceReloadableResourceBundleMessageSource
是否默认
读取类路径消息资源支持支持
读取网络消息资源不支持支持
读取系统文件路径资源不支持支持
读取非properties文件资源不支持支持
底层支持jdk提供的ResourceBundle技术Spring提供的Resource技术
是否支持热更新

📩 联系方式
邮箱: qijilaoli@foxmail.com
掘金: https://juejin.cn/user/873463590162108
CSDN: https://blog.csdn.net/qq_43408971

?版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问我的微信公众号

文章来源:https://blog.csdn.net/qq_43408971/article/details/135629209
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。