摘要
本文详细介绍了Spring框架中国际消息化相关的内容,在Spring中国际化消息通过 MessageSource
接口实现,而Spring为我们提供了ResourceBundleMessageSource
和ReloadableResourceBundleMessageSource
两个实现类来实现具体的功能。通过合理使用这两个组件,我们能够构建出更加灵活、可扩展的多语言应用程序,满足不同地区和文化的用户需求。
正文
Spring项目中提供了地区消息(国际化消息)相关功能,可以根据不同地区获取到对应的消息数据。国际化消息功能通过 org.springframework.contex.MessageSource
接口实现,Spring内部提供了以下两个实现类来满足不同需求
ResourceBundleMessageSource
会读取类路径下的messages*.properties文件,这个类也是Spring中默认值,不支持热加载(必须重启项目才能读取到新的资源)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.properties
、message_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内置了 ResourceBundleMessageSource
和 ReloadableResourceBundleMessageSource
两个实现类来实现具体获取消息的功能,下表对比了这两个类的一些特征
功能特征 | ResourceBundleMessageSource | ReloadableResourceBundleMessageSource |
---|---|---|
是否默认 | 是 | 否 |
读取类路径消息资源 | 支持 | 支持 |
读取网络消息资源 | 不支持 | 支持 |
读取系统文件路径资源 | 不支持 | 支持 |
读取非properties文件资源 | 不支持 | 支持 |
底层支持 | jdk提供的ResourceBundle技术 | Spring提供的Resource技术 |
是否支持热更新 | 否 | 是 |
📩 联系方式
邮箱: qijilaoli@foxmail.com
掘金: https://juejin.cn/user/873463590162108
CSDN: https://blog.csdn.net/qq_43408971❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问我的微信公众号
![](https://i-blog.csdnimg.cn/blog_migrate/c677d60ef9f0a7a202e36c2e4b1a73d6.jpeg#pic_center)