Spring中ApplicationContext的拓展功能詳解
國(guó)際化支持
簡(jiǎn)介
國(guó)際化的英文為Internationalization,這個(gè)也太長(zhǎng)了,所以它又稱為I18n(英文單詞 internationalization的首末字符i和n,18為中間的字符數(shù))。 國(guó)際化的操作就是指一個(gè)程序可以同時(shí)適應(yīng)多門語(yǔ)言,即:如果現(xiàn)在程序的使用者是中國(guó)人,則會(huì)以中文為顯示文字,如果現(xiàn)在程序的使用者是美國(guó)人,則會(huì)以英語(yǔ)為顯示的文字,也就是說可以通過國(guó)際化操作,讓一個(gè)程序適應(yīng)各個(gè)國(guó)家的語(yǔ)言要求。
原理
程序根據(jù)不同的語(yǔ)言環(huán)境找到不同的資源文件,之后從資源文件中取出內(nèi)容,資源文件中的內(nèi)容是以key-àvalue的形式保存的,所以在讀取的時(shí)候通過其key找到對(duì)應(yīng)的value
Demo
1、i18n.xml
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>message</value> </list> </property> </bean> </beans>
2、message_en_US.properties
k1=welcome\uFF1A {0}
3、message_zh_CN.properties
k1=\u6b22\u8fce\u4f60\uff0c{0}
k1就是“你好”,上面使用的是unicode??梢允褂?a rel="external nofollow" target="_blank">Unicode的轉(zhuǎn)換器來進(jìn)行轉(zhuǎn)換,也可以使用命令
4、測(cè)試
package com.yj.spring; import java.util.Locale; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class I18NTest { @Test public void Test() { Locale defaultLocale = Locale.getDefault(); //Locale defaultLocale = Locale.US; System.out.println("country="+ defaultLocale.getCountry()); System.out.println("language="+ defaultLocale.getLanguage()); Object[] arg = new Object[] { "悟空"}; ApplicationContext ctx = new ClassPathXmlApplicationContext("i18n.xml"); String msg = ctx.getMessage("k1", arg, defaultLocale); System.out.println(msg); } }
5、默認(rèn)時(shí),顯示為
country=CN language=zh 歡迎你,悟空
當(dāng)為美國(guó)US時(shí),顯示為
country=US language=en welcome: 悟空
資源訪問
很多時(shí)候應(yīng)用程序都需要存取資源。Spring提供了對(duì)資源文件的存取。ApplicationContext繼承了ReourceLoader接口,開發(fā)人員可以使用getResource()方法并指定資源文件的URL來存取。
ApplicationContext對(duì)資源文件的讀取有如下3種方式:
1.虛擬路徑來存取
如果資源文件位于CLASSPATH下:可以通過這種方式來獲取,代碼如下
Resource resource=ctx.getResource("classpath:message.properties");
這里要說明的是"claspath:"是 spring約定的URL虛擬路徑。
2.絕對(duì)路徑來存取
指定標(biāo)準(zhǔn)的URL,例如“file:”或“”,代碼如下
Resource source=ctx.getResource("file:D:/eclipse/workspace/Spring/src/main/resources/message.properties");
3.相對(duì)路徑來存取
Resource source = actx.getResource("WEB-INF/message.properties");
當(dāng)通過ApplicationContext取得一個(gè)Resource后,開發(fā)人員可以使用:
- getFile() 來存取資源文件內(nèi)容
- exists()來檢查資源文件是否存在
- isOpen()檢查資源文件是否被打開
- getURL()返回資源文件的URL
完整test文件:
package com.yj.spring; import java.io.File; import java.io.FileInputStream; import java.util.Properties; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.core.io.Resource; public class PropTest { @Test public void ClassPathTest() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("Beans.xml"); Resource resource=ctx.getResource("classpath:message.properties"); File file=resource.getFile(); Properties prop=fileToProp(file); System.out.println("通過classptah路徑獲取:"+prop.getProperty("name")); } @Test public void RealPathTest() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("Beans.xml"); Resource resource=ctx.getResource("file:D:/eclipse/workspace/Spring/src/main/resources/message.properties"); File file=resource.getFile(); Properties prop=fileToProp(file); System.out.println("通過實(shí)際路徑獲取:"+prop.getProperty("name")); } @Test public void virtualPathTest() throws Exception { ApplicationContext ctx = new FileSystemXmlApplicationContext("D:/eclipse/workspace/Spring/src/main/resources/Beans.xml"); Resource resource=ctx.getResource("WEB-INF/message.properties"); File file=resource.getFile(); Properties prop=fileToProp(file); System.out.println("通過虛擬路徑獲取:"+prop.getProperty("name")); } private Properties fileToProp(File file) throws Exception{ Properties prop = new Properties(); prop.load(new FileInputStream(file)); return prop; } }
3.事件傳遞
ApplicationContext事件機(jī)制是觀察者設(shè)計(jì)模式(訂閱/發(fā)布模式)的實(shí)現(xiàn),通過ApplicationEvent類和ApplicationListener接口,可以實(shí)現(xiàn)ApplicationContext事件處理。如果容器中有一個(gè)ApplicationListener Bean,每當(dāng)ApplicationContext發(fā)布ApplicationEvent時(shí),ApplicationListener Bean將自動(dòng)被觸發(fā)。
Spring的事件框架有如下兩個(gè)重要的成員:
- ApplicationEvent:容器事件,必須由ApplicationContext發(fā)布
- ApplicationListener:監(jiān)聽器,可由容器中的任何監(jiān)聽器Bean擔(dān)任
實(shí)際上,Spring的事件機(jī)制與所有時(shí)間機(jī)制都基本相似,它們都需要事件源、事件和事件監(jiān)聽器組成。只是此處的事件源是ApplicationContext,且事件必須由Java程序顯式觸發(fā)。
下面的程序?qū)⒀菔維pring容器的事件機(jī)制。
Demo
1.項(xiàng)目整體結(jié)構(gòu)
2.EmailController
package com.yj.event.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.yj.event.email.EmailEvent; import com.yj.event.email.EmailService; @RestController public class EmailController { @Autowired private EmailService emailService; @RequestMapping("/sendEmail") public void sendEmail() { EmailEvent emailEvent = new EmailEvent("source"); emailEvent.setAddress("my address"); emailEvent.setText("hello world"); emailService.sendEmail(emailEvent); } }
3.EmailEvent
程序先定義了一個(gè)EmailEvent類,其對(duì)象就是一個(gè)Spring容器事件。該類繼承了ApplicationEvent類,除此之外,它就是一個(gè)普通的Java類。代碼如下:
package com.yj.event.email; import org.springframework.context.ApplicationEvent; public class EmailEvent extends ApplicationEvent { private static final long serialVersionUID = 8890656093518139995L; private String address; private String text; public EmailEvent(Object source) { super(source); } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getText() { return text; } public void setText(String text) { this.text = text; } }
4.EmailListener
兩種實(shí)現(xiàn)方式,
- @EventListener注解
- 一種實(shí)現(xiàn)ApplicationListener接口,重寫onApplicationEvent方法
基于注解的方式
package com.yj.event.email; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component public class EmailAnnoListener { @EventListener //@Async public void EmailEventListener(EmailEvent event) { try { System.out.println("開始休眠..."); Thread.sleep(5000L); System.out.println("休眠結(jié)束..."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("EmailEventListener:"+event.getClass()); System.out.println("注解監(jiān)聽到發(fā)送郵件的事件"); System.out.println("注解需要發(fā)送的郵件地址: " + event.getAddress()); System.out.println("注解郵件正文: " + event.getText()); } }
實(shí)現(xiàn)接口的方式
package com.yj.event.email; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; //@Component //@Async public class EmailListener implements ApplicationListener<ApplicationEvent> { @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("EmailListener:" + event.getClass()); if (event instanceof EmailEvent) { EmailEvent emailEvent = (EmailEvent) event; System.out.println("監(jiān)聽到發(fā)送郵件的事件"); System.out.println("需要發(fā)送的郵件地址: " + emailEvent.getAddress()); System.out.println("郵件正文: " + emailEvent.getText()); try { Thread.sleep(5000L); System.out.println("休眠..."); } catch (InterruptedException e) { e.printStackTrace(); } } } }
EmailEventListener方法或者onApplicationEvent方法,可以傳入ApplicationEvent參數(shù),監(jiān)聽所有的事件,本例只傳入EmailEvent參數(shù),只監(jiān)聽EmailEvent事件。然后將監(jiān)聽器配置在Spring的容器中。需注意的是,此時(shí)事件的發(fā)布,與事件的監(jiān)聽處理,默認(rèn)是同步阻塞的,下文會(huì)開啟異步的方式
5.EmailService
當(dāng)系統(tǒng)創(chuàng)建Spring容器、加載Spring容器時(shí)會(huì)自動(dòng)觸發(fā)容器事件,容器事件監(jiān)聽器可以監(jiān)聽到這些事件。除此之外,程序也可以調(diào)用ApplicationContext的publishEvent()方法來主動(dòng)觸發(fā)一個(gè)容器事件
package com.yj.event.email; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import com.yj.event.util.ApplicationContextUtil; @Component public class EmailService { public void sendEmail(EmailEvent event){ ApplicationContext ctx=ApplicationContextUtil.getApplicationContext(); ctx.publishEvent(event); } }
6.ApplicationContextUtil
如果Bean想發(fā)布事件,則Bean必須獲得其容器的引用。如果程序中沒有直接獲取容器的引用,則應(yīng)該讓Bean實(shí)現(xiàn)ApplicationContextAware或者BeanFactoryAware接口,從而可以獲得容器的引用
package com.yj.event.util; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class ApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; public static ApplicationContext getApplicationContext() { return applicationContext; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (ApplicationContextUtil.applicationContext == null) { ApplicationContextUtil.applicationContext = applicationContext; } } }
7.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yj</groupId> <artifactId>Event</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>Event</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
8.app
package com.yj.event; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication //@EnableAsync public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
驗(yàn)證
訪問路徑
//127.0.0.1:8080/sendEmail
默認(rèn)同步的情況下,顯示結(jié)果
開始休眠...
休眠結(jié)束...
EmailEventListener:class com.yj.event.email.EmailEvent
注解監(jiān)聽到發(fā)送郵件的事件
注解需要發(fā)送的郵件地址: my address
注解郵件正文: hello world
結(jié)束
開啟異步的情況(app.java類添加@EnableAsync注解,EmailAnnoListener類的EmailEventListener方法上添加@Async注解),有點(diǎn)MQ的效果,只是只能在一個(gè)ApplicationContext范圍內(nèi)才能捕獲到事件的發(fā)布,才能起作用。
顯示結(jié)果
結(jié)束
開始休眠...
休眠結(jié)束...
EmailEventListener:class com.yj.event.email.EmailEvent
注解監(jiān)聽到發(fā)送郵件的事件
注解需要發(fā)送的郵件地址: my address
注解郵件正文: hello world
Spring提供如下幾個(gè)內(nèi)置事件:
- ContextRefreshedEvent:ApplicationContext容器初始化或刷新時(shí)觸發(fā)該事件。此處的初始化是指:所有的Bean被成功裝載,后處理Bean被檢測(cè)并激活,所有Singleton Bean 被預(yù)實(shí)例化,ApplicationContext容器已就緒可用
- ContextStartedEvent:當(dāng)使用ConfigurableApplicationContext(ApplicationContext的子接口)接口的start()方法啟動(dòng)ApplicationContext容器時(shí)觸發(fā)該事件。容器管理聲明周期的Bean實(shí)例將獲得一個(gè)指定的啟動(dòng)信號(hào),這在經(jīng)常需要停止后重新啟動(dòng)的場(chǎng)合比較常見
- ContextClosedEvent:當(dāng)使用ConfigurableApplicationContext接口的close()方法關(guān)閉ApplicationContext時(shí)觸發(fā)該事件
- ContextStoppedEvent:當(dāng)使用ConfigurableApplicationContext接口的stop()方法使ApplicationContext容器停止時(shí)觸發(fā)該事件。此處的停止,意味著容器管理生命周期的Bean實(shí)例將獲得一個(gè)指定的停止信號(hào),被停止的Spring容器可再次調(diào)用start()方法重新啟動(dòng)
- RequestHandledEvent:Web相關(guān)事件,只能應(yīng)用于使用DispatcherServlet的Web應(yīng)用。在使用Spring作為前端的MVC控制器時(shí),當(dāng)Spring處理用戶請(qǐng)求結(jié)束后,系統(tǒng)會(huì)自動(dòng)觸發(fā)該事件。
到此這篇關(guān)于Spring中ApplicationContext的拓展功能詳解的文章就介紹到這了,更多相關(guān)ApplicationContext的拓展功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis中TypeAliasRegistry的作用及使用方法
Mybatis中的TypeAliasRegistry是一個(gè)類型別名注冊(cè)表,它的作用是為Java類型建立別名,使得在Mybatis配置文件中可以使用別名來代替完整的Java類型名。使用TypeAliasRegistry可以簡(jiǎn)化Mybatis配置文件的編寫,提高配置文件的可讀性和可維護(hù)性2023-05-05springboot+vue+elementsUI實(shí)現(xiàn)分角色注冊(cè)登錄界面功能
這篇文章主要給大家介紹了關(guān)于springboot+vue+elementsUI實(shí)現(xiàn)分角色注冊(cè)登錄界面功能的相關(guān)資料,Spring?Boot和Vue.js是兩個(gè)非常流行的開源框架,可以用來構(gòu)建Web應(yīng)用程序,需要的朋友可以參考下2023-07-07struts2中實(shí)現(xiàn)多個(gè)文件同時(shí)上傳代碼
struts2中實(shí)現(xiàn)多個(gè)文件同時(shí)上傳代碼,需要的朋友可以參考一下2013-04-04SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過程
日常開發(fā)過程中,我們經(jīng)常需要使用到郵件發(fā)送任務(wù),比方說驗(yàn)證碼的發(fā)送、日常信息的通知等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過程,需要的朋友可以參考下2022-10-10Java List Object[]轉(zhuǎn)換成List T的實(shí)例
這篇文章主要介紹了Java List Object[]轉(zhuǎn)換成List T的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09Spring?AI?+?ollama?本地搭建聊天?AI?功能
這篇文章主要介紹了Spring?AI?+?ollama?本地搭建聊天?AI?,本文通過實(shí)例圖文相結(jié)合給大家講解的非常詳細(xì),需要的朋友可以參考下2024-11-11