一、知识点
Spring的应用程序上下文能够根据关键字为目标语言环境解析文本消息。通常,一个语言环境的消息应该存储在一个独立的属性文件中,这个属性文件称作资源包(Resource bundle)。
MessageSource是一个定义了多种消息解析方法的接口。ApplicationContext接口扩展了这个接口,使得所有应用程序上下文都能解析文本消息。应用程序上下文将消息解析委托给名为messageSource的Bean。ResourceBundleMessageSource是最常见的MessageSource实现,它从资源包中解析不同语言环境的消息。
二、代码示例
创建美国英语资源包message_en_US.properties。
alert.checkout=A shopping cart has been checked out.
Bean配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/beans/spring-context-3.2.xsd"> <!-- 用ResourceBundleMessageSource作为MessageSource的实现。Bean名称必须设置为messageSource,应用程序上下文才能发现它。必须为ResourceBundleMessageSource指定资源包的基本名称 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"> <value>messages</value> </property> </bean> </beans>
对于这个MessageSource定义,如果寻找一个用于美国地区、首选语言为英语的文本消息,将首先考虑语言和国家都匹配的资源包messages_en_US.properties。如果没有找到这样的资源包或者消息,就会考虑仅匹配语言的messages_en.properties。如果还找不到,最终将选择用于所有地区的默认资源包messages.properties。
测试类
package com.jackie.codeproject.springrecipesnote.springadvancedioc; import java.util.Locale; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author jackie * */ public class MessageResolveTest { @Test public void testMessageResolve() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // getMessage方法要求应用程序上下文解析消息。第一个参数是关键字,第三个参数是目标语言环境。 String alert = applicationContext.getMessage("alert.checkout", null, Locale.US); System.out.println(alert); } }
getMessage()方法的第二个参数是消息参数数组。可用索引值定义多个参数。
alert.checkout=A shopping cart costing {0} dollars has been checked out at {1}.
传入一个对象数组,数组元素在填写参数之前转换成字符串
String alert = applicationContext.getMessage("alert.checkout", new Object[]{4, new Date()}, Locale.US); System.out.println(alert);
对于解析文本消息的Bean来说,必须实现ApplicationContextAware接口或者MessageSourceAware
package com.codeproject.jackie.springrecipesnote.springadvancedioc; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.Locale; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; /** * Cashier类实现BeanNameAware感知接口和,StorageConfig标记接口和MessageSourceAware接口 * @author jackie * */ public class Cashier implements BeanNameAware, StorageConfig, MessageSourceAware { private String name; private BufferedWriter writer; private String path; private MessageSource messageSource; public void setPath(String path) { this.path = path; } public void openFile() throws IOException { File file = new File(path, name + ".txt"); FileWriter fw = new FileWriter(file, true); writer = new BufferedWriter(fw); } public void checkout(ShoppingCart cart) throws IOException { double total = 0; for (Product product : cart.getItems()) { total += product.getPrice(); } writer.write(new Date() + "\t" + total + "\r\n"); writer.flush(); String alert = messageSource.getMessage("alert.checkout", new Object[] { total, new Date()}, Locale.US); System.out.println(alert); } public void closeFile() throws IOException { writer.close(); } @Override public String getPath() { return path; } @Override public void setBeanName(String beanName) { this.name = beanName; } @Override public void setMessageSource(MessageSource messageSource) { this.messageSource = messageSource; } }