spring監聽器ContextLoaderListener的疑問
阿新 • • 發佈:2019-01-23
今天新搭了專案,採用Spting和mybatis,MVC用的是Spring MVC ,配置檔案採用的是之前的專案的。
在執行後訪問專案時候報錯了:
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
在研究後發現是web.xml缺少了Spring監聽器:
這裡就有個疑問了,為什麼之前專案不加這一段執行正常。<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param>
經過研究後發現是新專案載入了shiro過濾器:
該過濾器的功能需要依賴ContextLoaderListener所載入的beans.xml檔案生成的applicationContext即Spring的上下文,而之前DispatcherServlet所載入的beans.xml檔案生成的applicationContext為Spring mvc的上下文,shiro過濾器無法載入,所以得依靠監聽器載入public的applicationContext。<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
附三個context的關係:
- 對於一個web應用,web容器載入一個全域性context供其使用,這個context就是servletContext,為其後續的spring
IoC容器提供依賴。
- 在web.xml中提供的ContextLoaderListener監聽器,web容器啟動時會觸發容器初始化事件,ContextLoaderListener會監聽這個事件,初始化一個根上下文即WebApplicationContext,實現類為XmlWebApplicationContext。這個就是Spring的IoC容器,spring將其以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為key儲存在servletContext中
- DispatcherServlet在初始化會建立自己的IoC容器用以持有Spring mvc相關的bean,它在建立的時候會通過WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從servletContext中獲取根上下文作為自己上下文的父上下文,它的實現類也是XmlWebApplicationContext,在建立之後會以和自己servlet-name便籤有關的名稱儲存在servletContext中,這樣每個servlet就擁有自己獨立的bean及根上下文共享的bean
但是這樣會導致重複載入配置檔案,DispatcherServlet、ContextLoaderListener會分別載入一次,解決方法是把配置檔案拆分成2個,一個Spring mvc的配置檔案,一個Spring的配置檔案,DispatcherServlet載入Spring mvc的配置檔案,ContextLoaderListener載入Spring的配置檔案 。
Spring mvc在使用上下文的時候會使用DispatcherServlet載入的applicationContext,也會使用的contextLoaderListener載入的applicationContext。