1. Spring MVC的核心就是DispatcherServlet類,Spring MVC處理請求的流程如下圖所示:
2. Spring MVC中典型的上下文層次
當我們初始化一個DispatcherServlet類時,Spring MVC會在web應用的WEB-INF目錄下查詢一個名字叫:[servlet-name]-servlet.xml的配置檔案,查詢這個檔案中定義的bean並初始化。[servlet-name]-servlet.xml的定義的bean初始化時將會覆蓋在全域性範圍內(global scope)定義的相同名稱的bean。我們一般會在web.xml中定義DispatcherServlet。由上圖我們可以看出Controller、HandlerMapping、ViewResovler類(和web有關的)在Servlet WebApplicationContext中定義,而Services類,Repositories類(中間服務、資料來源等)在Root WebApplicationContext中定義。
3. Spring MVC中單個的根上下文(Single Root Contexct)
如果只有一個單一個根上下文,這樣我們就可以定義一個空的contextConfigLocation,因此所有的beans就要在這這個單一的Root Context中定義了。
4. 如何不再要web.xm和[servlet-name].servlet.xml而採用純粹的java類來實現?
從上圖中我們可以看出只要繼承了AbstractAnnotationConfigDispatcherServletInitializer類並實現了相關方法即可實現註冊一個DispatcherServlet類。
4.1.將 DispatcherServlet 配置在 Servlet 容器中而不再使用 web.xml 。
public class RtpFrontWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { /** * 指定 Root WebApplicationContext 類,這個類必須@Configuration來註解,從而代替XML配置檔案 */ @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[]{RootConfig.class}; } /** * 指定 Servlet WebApplicationContext 類,這個類必須@Configuration來註解,從而代替XML配置檔案 */ @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[]{WebConfig.class}; } /** * 指定 Servlet mappings */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
4.2 定義RootConfig類
@Configuration @ComponentScan(basePackageClasses = Configs.class, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)}) public class RootConfig { }
RootConfig類使用了@Configuration作為註解,而@Configuration本身是使用了@Component進行了註解。所以這個RootConfig類是可以被元件掃描到並注入到容器中的。@Configuration用來說明這個是配置類用來替換原來的xml。了實現元件自動掃描和例項化並注入到容器中,我們要在配置類中加上@ComponnetScan註解,並設定掃描的包的範圍。本示例掃描的是Configs.class類所在的包。
4.3 定義WebConfig類
@Configuration @EnableWebMvc @ComponentScan(basePackageClasses = HomeController.class) public class WebConfig { }
通過@EnableMvc來匯入Spring MVC的相關配置,通過@ComponentScan來自動掃描控制器類HomeController所在的包。同樣,@Configuration用來說明這個是配置類用來替換原來的xml。
5. 從Servlet容器中(Bean工廠)獲取bean.
下面是一個工具類,程式碼如下:
public class SpringContextUtil { /** * 私有建構函式,不允許例項化 */ private SpringContextUtil(){ } /** * Spring應用上下文環境 */ private static AnnotationConfigWebApplicationContext ctx; static { ctx = new AnnotationConfigWebApplicationContext(); ctx.register(RootConfig.class); ctx.refresh(); } /** * 獲取指定Bean的例項 * * @param name 要獲取Bean的名稱 * @return Bean object */ public static Object getBean(String name) { return ctx.getBean(name); } }
定義了一個工具類來從servlet容器中獲取bean。這些bean都是被自動掃描並注入到servlet容器中去的。預設情況下,這個bean的例項都是單例的。獲取bean的方法如下:
AtomTransaction atomTransaction = (AtomTransaction) SpringContextUtil.getBean(getBeanName(transType));
至此,我們已經完成了Spring MVC的零配置實現,主要是用相關的Java類來代替之前的XML檔案。
總結:
1、Spring MVC的核心是DispatcherServlet類,它主要實現請求的路由和相關流程的控制;
2、傳統DispatcherServlet類的初始化由讀取web.xml和[servlet-name]-servlet.xml的相關配置來實現;
3、為什麼我們要採用annotation而非xml?基於java的配置,它比基於XML的配置更加強大、型別安全並且易於重構;
4、零配置,其實很簡單:繼承AbstractAnnotationConfigDispatcherServletInitializer這個抽象類並實現3個相關的抽象方法,3個抽象方法中分別指定:Servlet WebApplicationContext(WebConfig)、Root WebApplicationContext(RootConfig)、Mappings。WebConfig和RootConfig必須要有@Configuration註解和@ComponentScan註解。@Configuration註解用來表明這些是配置類,用來替換XML;@ComponentScan註解用來實現元件或Bean的自動化掃描及在容器中註冊(預設為初始化單例)。
5、使用AnnotationConfigWebApplicationContext來從容器中獲取Bean,這些Bean預設都是單例的。
幫助到您了嗎?
打賞作者(支付寶):