本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~ Github地址:https://github.c ...
1.使用MessageSource
(1) 有時,我們的項目可能會面臨國際化需求,例如:對不同國家的人,我們需返回不同語言的消息,而java本身已經給我們提供了ResourceBundle類實現國際化的需求,如下
//在resources目錄下,新建兩個配置文件,分別為message_en_us.properties和message_zh_cn.properties,內容如下
//message_en_us.properties文件中配置如下
country=us
//message_zh_cn.properties文件中配置如下,註意對中文使用unicode編碼
country=\u4e2d\u56fd
//現在,我們希望我們的項目在不同的國家返回不同的country信息,那麼就可以使用ResourceBundle類了,如下
public static void main(String[] args) {
//使用ResourceBundle載入的文件都必須放置在resources根目錄下,因此我們的message_en_us.properties和message_zh_cn.properties文件都位於resources根目錄,而且這些文件都必須按照${name}_${language}_${region}的方式來命名,因為這種命名方式正好能對應ResourceBundle.getBundle()方法中的參數,例如ResourceBundle.getBundle("message", new Locale("zh", "cn")),其中,message對應${name},zh對應${language},cn對應${region},即ResourceBundle.getBundle("message", new Locale("zh", "cn"))這個方法會讀取我們的message_zh_cn.properties配置文件,這樣我們就可以根據不同的參數來讀取不同的文件,達到國際化的目的
//未指定它的Locale,因此java獲取它當前所在的地區,為cn
ResourceBundle DefaultBundle = ResourceBundle.getBundle("message");
System.out.println(DefaultBundle.getString("country"));
//指定地區為cn
ResourceBundle cnBundle = ResourceBundle.getBundle("message", new Locale("zh","cn"));
System.out.println(cnBundle.getString("country"));
//指定地區為us
ResourceBundle uSbundle = ResourceBundle.getBundle("message", new Locale("en","us"));
System.out.println(uSbundle.getString("country"));
}
//列印結果如下,通過ResourceBundle實現了國際化
中國
中國
us
(2) Spring提供了MessageSource來幫助我們實現國際化功能,具體的使用方法同jdk中的ResourceBundle,如下
//在resources目錄下,新建兩個配置文件,分別為message_en.properties和message_zh.properties,內容如下
//message_en.properties文件中配置如下
country=us
//message_zh.properties文件中配置如下
country=中國
<!-- 配置xml -->
<beans ....>
<!-- 使用ReloadableResourceBundleMessageSource類,向容器中註入MessageSource用於國際化功能,註意:這個bean的名稱必須為messageSource -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<!-- 指定消息源為message,那麼spring會去尋找名稱中包含message的配置文件 -->
<value>message</value>
</list>
</property>
<!-- 避免中文亂碼 -->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>
</beans>
//ApplicationContext繼承了MessageSource介面
MessageSource messageSource = new ClassPathXmlApplicationContext("beans.xml");
//指定不同的語言,來獲取不同消息
String zh = messageSource.getMessage("country", null, Locale.CHINESE);
System.out.println(zh);
String en = messageSource.getMessage("country", null, Locale.ENGLISH);
System.out.println(en);
//啟動容器,輸出如下
中國
us
(3) Spring的MessageSource還提供了占位符功能,來進行消息內容的填充,如下例所示
//向message_zh.properties中添加配置項如下,{0}表示第一個占位符,還有{1},{2}等等,以此類推
argument=we need {0}
//main函數
MessageSource messageSource = new ClassPathXmlApplicationContext("beans.xml");
//Object[]指定向占位符填充的內容
String argument = messageSource.getMessage("argument", new Object[]{"蛋糕"}, Locale.CHINESE);
System.out.println(argument);
//啟動後,列印如下
we need 蛋糕
2.標準和自定義事件
(1) Spring中的事件是通過ApplicationEvent類和ApplicationListener介面提供的,如果一個bean實現了ApplicationListener介面,那麼每當一個ApplicationEvent發佈到Spring中時,都會通知該bean
(2) Spring中內置事件
事件 | 說明 |
---|---|
ContextRefreshedEvent | 容器初始化或刷新時(refresh)時發佈該事件 |
ContextStartedEvent | 通過調用ConfigurationApplicationContext介面中的start()方法啟動容器時發佈該事件 |
ContextStoppedEvent | 通過調用ConfigurationApplicationContext介面中的stop()方法停止容器時發佈該事件 |
ContextClosedEvent | 通過調用ConfigurationApplicationContext介面中的close()方法或jvm關閉鉤子關閉容器時發佈該事件 |
RequestHandledEvent | 適用於使用了DispatcherServlet的web環境中,在請求完成後發佈該事件,用於告知所有的bean已經為http請求提供了服務 |
ServletRequestHandledEvent | RequestHandledEvent的子類,其中添加了Servlet特定信息 |
(3) 示例如下
//現在假設有一個用戶註冊事件,每當一個用戶註冊後,進行相應的其他操作(如發送郵件等等)
//自定義事件,需繼承ApplicationEvent
public class RegisterEvent extends ApplicationEvent {
private String username;
public RegisterEvent(Object source,String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
//使用ApplicationEventPublisher中的publishEvent()方法來向容器中發佈一個事件
@Service
public class RegisterService implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
//publishEvent()方法會阻塞,直到所有的監聽器都完成了對事件的處理
public void finishRegister(String username) {
this.publisher.publishEvent(new RegisterEvent(this, username));
}
}
//實現ApplicationListener介面,實現某種類型事件的監聽者
@Component
public class RegisterLister implements ApplicationListener<RegisterEvent> {
//每當有一個RegisterEvent事件發佈後,都會觸發該回調
@Override
public void onApplicationEvent(RegisterEvent registerEvent) {
System.out.println("用戶:" + registerEvent.getUsername() + "完成註冊...");
//do other things,such as send emails
}
}
//main
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext("cn.example.spring");
String username ="zpc";
ctx.getBean(RegisterService.class).finishRegister(username);
//啟動後,容器列印如下,可見Spring使用了觀察者模式,來實現了一個事件發佈與訂閱的功能
用戶:zpc完成註冊...