spring中ResourceBundleMessageSource与ReloadableResourceBundleMessageSource查找资源的区别

本文详细介绍了Spring中ResourceBundleMessageSource与ReloadableResourceBundleMessageSource的区别,包括编码设置、加载资源文件的方式以及如何在项目中应用。通过示例演示了如何配置和使用这些消息源,以及如何自定义消息处理逻辑。
spring中ResourceBundleMessageSource与ReloadableResourceBundleMessageSource查找资源的区别:

1.ResourceBundleMessageSource在xml配置中无法指定编码:

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

<property NAME="basenames">

<LIST>

<VALUE >error</VALUE >

<VALUE >message</VALUE >

</LIST>

</property>

</bean>

而ReloadableResourceBundleMessageSource可以指定编码,譬如:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<property NAME="defaultEncoding" VALUE ="gbk" />

<property NAME="basename" VALUE ="message" />

</bean>

2.加载资源文件的方式不同:

1).下面看下它们的源代码:

ResourceBundleMessageSource的加载,使用ClassUtils.getDefaultClassLoader()加载器,getDefaultClassLoader的方法代码如下:

p lic static ClassLoader getDefaultClassLoader()

{

ClassLoader cl = NULL;

try {

cl = Thread.currentThread().getContextClassLoader();

}

catch (Throwable ex) {

logger.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex);

}

IF (cl == NULL)

{

cl = ClassUtils.class.getClassLoader();

}

RETURN cl;

}

//这种方式也是JVM默认的加载方式,先从当前线程中获取类加载器,如果没有,就获取这个类本身的类加载器

2).ReloadableResourceBundleMessageSource默认也使用ClassUtils.getDefaultClassLoader()加载器,它加载资源的方式如下:

p lic Resource getResource(STRING location)

{

Assert.notNull(location, "Location must not be null");

IF (location.startsWith("classpath:")) {

RETURN NEW ClassPathResource(location.s STRING("classpath:".LENGTH()), getClassLoader());

}

try

{

URL url = NEW URL(location);

RETURN NEW UrlResource(url);

}

catch (MalformedURLException ex)

{

RETURN getResourceByPath(location);

}

}

3). 小结:ResourceBundleMessageSource从classloader中加载资源文件,可以找到,

ReloadableResourceBundleMessageSource加载时,默认使用DefaultResourceLoader,他会先判断资源path是否带有classpath:前缀,如果有,用 ClassPathResource去加载资源文件,如果没有试着用文件协议的url去访问,再没有就在contextPath即WEB-INF下查找。

下面做一个Spring的MessageSource的示例:

1.我们单独新建一个spring消息文件beans-message.xml中加如下配置:

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

<property NAME="basenames">

<LIST>

<VALUE >error</VALUE>

<VALUE >message</VALUE >

</LIST>

</property>

</bean>

2.这段配置假定在你的classpath中有两个资源文件(resource bundle),它们是error, message。通过ResourceBundle,使用JDK中解析消息的标准方式,来处理任何解析消息的请求。出于示例的目的,假定 message_zh_CN.properties的资源文件的内容为…

msg.common.serverBusy = \非\常\抱\歉,\系\统\十\分\繁\忙\!

#非常抱歉,系统十分繁忙!

msg.argument.required={0}\是\个\必\填\项\!

#{0}是个必填项!

3.再写一个测试类:

p lic class MessageTest {

p lic static void main(STRING[] args) {

MessageSource resources = NEW ClassPathXmlApplicationContext("beans-message.xml");

STRING message = resources.getMessage("msg.common.serverBusy", NULL, "Default", NULL);

System.out.println(message);

STRING message1 = resources.getMessage("msg.argument.required", NEW Object[] { "'联系方式'" }, NULL, Locale.CHINA);

System.out.println(message1);

}

}

结果输入为:

非常抱歉,系统十分繁忙!

'联系方式'是个必填项!

3.在我们的项目中,MessageSource不会单独使用,通常我们会把它和自己的业务一起使用,这时候我们可以直接用它本身的方法,我们也可以在其中加入我们自己的逻辑:如,自定义的一个消息类:

p lic class MessageSourceHelper {

private ResourceBundleMessageSource messageSource;

p lic STRING getMessage(STRING CODE, Object[] args, STRING defaultMessage, Locale locale) {

STRING msg = messageSource.getMessage(CODE, args, defaultMessage, locale);

RETURN msg != NULL ? msg.trim() : msg;

}



p lic void setMessageSource(ResourceBundleMessageSource messageSource) {

this.messageSource = messageSource;

}

}

在beans-message.xml中注入:

<bean id="messageSourceHelper" class="com.myspring.message.MessageSourceHelper">

<property NAME="messageSource">

<ref LOCAL="messageSource" />

</property>

</bean>

4.我们可以在MessageSourceHelper中加入自己的业务,注入依赖后,就可以在其他类中调用MessageSourceHelper中的方法。

5.理论简要:ApplicationContext接口扩展了MessageSource 接口,因而提供了消息处理的功能(i18n或者国际化)。与HierarchicalMessageSource一起使用,它还能够处理嵌套的消息,这些是Spring提供的处理消息的基本接口。让我们快速浏览一下它所定义的方法:

· STRING getMessage(STRING CODE, Object[] args, STRING DEFAULT, Locale loc):用来从MessageSource获取消息的基本方法。如果在指定的locale中没有找到消息,则使用默认的消息。args中的参数将使用标准类库中的MessageFormat来作消息中替换值。

· STRING getMessage(STRING CODE, Object[] args, Locale loc):本质上和上一个方法相同,其区别在:没有指定默认值,如果没找到消息,会抛出一个NoS hMessageException异常。

· STRING getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的属性都封装到一个MessageSourceResolvable实现中,而本方法可以指定 MessageSourceResolvable实现。

当一个ApplicationContext被加载时,它会自动在context中查找已定义为MessageSource类型的bean。此bean的名称须为messageSource。如果找到,那么所有对上述方法的调用将被委托给该 bean。否则ApplicationContext会在其父类中查找是否含有同名的bean。如果有,就把它作为MessageSource。如果它最终没有找到任何的消息源,一个空的StaticMessageSource将会被实例化,使它能够接受上述方法的调用。

Spring目前提供了两个MessageSource的实现:ResourceBundleMessageSource和StaticMessageSource。它们都继承 NestingMessageSource以便能够处理嵌套的消息。StaticMessageSource很少被使用,但能以编程的方式向消息源添加消息。ResourceBundleMessageSource会用得更多一些,

6. 更多的资料参考spring官方开发手册,很详尽的!

转自:[url]http://meiyx.iteye.com/blog/1028589[/url]
Spring 框架中,**Message(消息)机制**主要用于实现 **国际化(i18n, Internationalization)支持** 和 **统一的消息管理**。它允许应用程序根据用户的语言环境(Locale)显示不同的文本内容,比如提示信息、错误信息、按钮文字等。 --- ### ✅ Spring 中 Message 的核心作用: #### 1. **国际化(I18N)支持** Spring 提供了 `MessageSource` 接口,可以加载不同语言的资源文件(如 `messages_zh_CN.properties`、`messages_en_US.properties`),并根据客户端请求的语言返回对应的文本。 ```properties # messages_en_US.properties welcome.message=Hello, {0}! Welcome to our app. error.login.invalid=Invalid username or password. # messages_zh_CN.properties welcome.message=你好,{0}!欢迎使用本应用。 error.login.invalid=用户名或密码错误。 ``` 通过 `MessageSource` 可以动态获取对应语言的消息: ```java String msg = messageSource.getMessage("welcome.message", new Object[]{"Alice"}, Locale.CHINA); // 输出中文 ``` --- #### 2. **统一管理提示/错误信息** 将所有提示语、错误码集中到 `.properties` 文件中,避免硬编码,便于维护和多语言扩展。 --- #### 3. ** Spring Web 集成良好** - 在 Spring MVC 或 Spring Boot Web 应用中,可自动根据 HTTP 请求头中的 `Accept-Language` 判断用户语言。 - 支持 Thymeleaf、JSP 等模板引擎结合,在页面中直接使用国际化消息。 ```html <!-- Thymeleaf 示例 --> <p th:text="#{welcome.message(${user.name})}"></p> ``` --- #### 4. **支持参数化消息(占位符)** 使用 `{0}`, `{1}` 等占位符插入动态值,并支持类型格式化(日期、数字等)。 ```java messageSource.getMessage("welcome.message", new Object[]{"Bob"}, Locale.US); // → "Hello, Bob! Welcome to our app." ``` --- ### 🔧 核心接口:`MessageSource` Spring 使用 `MessageSource` 接口来提供消息解析功能,常见实现有: - `ResourceBundleMessageSource`:基于 JVM 的 `ResourceBundle` 实现。 - `ReloadableResourceBundleMessageSource`:支持热加载 `.properties` 文件(开发友好)。 #### 配置示例(Java Config): ```java @Configuration public class MessageConfig { @Bean public MessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasename("classpath:messages"); // 加载类路径下的 messages_*.properties messageSource.setDefaultEncoding("UTF-8"); messageSource.setCacheSeconds(5); // 支持热更新 return messageSource; } } ``` > 文件命名规则:`messages.properties`(默认)、`messages_en.properties`、`messages_zh_CN.properties` 等。 --- ### 🌐 实际应用场景 | 场景 | 说明 | |------|------| | 多语言网站 | 用户切换语言时,界面文字自动变化 | | 错误提示信息 | 后端抛出异常后,返回本地化的错误描述 | | 表单验证消息 | 使用 `@NotNull`, `@Size` 等注解时,默认错误信息来自 `ValidationMessages.properties` 或 `messages.properties` | 例如: ```java @NotBlank(message = "{error.username.required}") private String username; ``` 会从 `messages.properties` 查找键为 `error.username.required` 的翻译。 --- ### 总结 | 功能 | 说明 | |------|------| | ✅ 国际化支持 | 根据 Locale 返回不同语言的文本 | | ✅ 解耦硬编码 | 所有提示信息外置到配置文件 | | ✅ 参数替换 | 支持 `{0}`, `{1}` 占位符 | | ✅ Spring 全家桶集成 | Web、Validation、Boot 都能使用 | > 💡 **Message 不是“通信消息”或“队列消息”,而是“文本消息/提示消息”的意思**,属于“信息源”的概念。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值