Question 1 How to get a Web container to load your Web MVC framework
For servlet-based web containers, the servlet specification is followed, and the Portal configuration file is XML. This type of Web container will be launched and will only load the following three types of objects:
- Servlet
- Context Listener
- Filter
And there is a certain order of loading and destroying!
Loading Servlets, Context Listeners, and Filters
Servlets, Context Listeners, and Filters is loaded and destroyed in the following order:
Order of loading:
- Context Listeners
- Filters
- Servlets
Order of Destruction:
- Servlets
- Filters
- Context Listeners
Servlets and filters is loaded in the same order they is defined in the Web. xml file and unloaded in reverse order. Context listeners is loaded in the following order:
- All context listeners in the Web. xml file in the order as specified in the file
- Packaged JAR files containing tag library descriptors
- Tag library descriptors in the Web-inf directory
In general, the servlet is used to receive user requests, filter as the servlet interceptor, and context listener as the event listener. So it's common to use Servlets to load the Web MVC framework.
For spring MVC, the official documentation is described in great detail: 15. Web MVC Framework
Spring MVC is DispatcherServlet initiated through this Front Controller . And DispatcherServlet itself is a servlet, configured in Web. XML:
<servlet> <servlet-name>foobar</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping> <servlet-name>foobar</servlet-name> <url-pattern>*.htm</url-pattern></servlet-mapping>
Question 2: How does your Web MVC framework load your web-aware Spring applicationcontext?
The previous simple configuration we have let the Web container load our web MVC Framework startup class DispatcherServlet , then DispatcherServlet how to load our application context?
In spring MVC Official document 15. In the Web MVC framework, there is this sentence:
As detailed in sections 3.13, "Additional capabilities of the ApplicationContext", ApplicationContext instances in Spring C An IS scoped. In the Web MVC framework, each dispatcherservlet have its own webapplicationcontext, which inherits all the beans already D Efined in the root webapplicationcontext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local T o a given servlet instance.
Just as the Portal configuration file for the Web container is XML, each Web MVC framework has its own configuration file, and for SPRINGMVC, its configuration file defaults to WEB-INF/${dispatcherServletName}-servlet.xml . For the example above, when Dispatchservlet is loaded, it loads the foobar-servlet.xml application context from the.
Decompose the application context
Based on the previous configuration, Dispatcherservlet has been loaded into foobar-servlet.xml. You can configure all the beans in the system in Foobar-servlet.xml, but eventually the file is very bloated, and the best practice is to configure each layer (Web, biz, DAL) Separately, at least to differentiate between the configuration of the Web tier and the biz layer.
To ensure that all the configuration files can be loaded, we need to configure a context loader in the Web. xml file.
Configuring a Context Loader
To ensure the all of these configuration files is loaded, you'll need to configure a context loader in your web. xml file . A Context Loader loads context configura-tion files in addition to the one that dispatcherservlet loads. The most Com-monly used context loader are a servlet listener called Contextloaderlistener that's configured in Web. S follows:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
NOTE Some Web containers do not initialize servlet listeners before Servlets-which was important when loading Spring context de Finitions. If your application is going to being deployed to a older web container that adheres to Servlet 2.2 or if the Web container is a Servlet 2.3 container This does not initialize listeners before Servlets, you'll want to use Contextloaderservlet ins Tead of Contextloaderlistener.
Once configured ContextLoaderListener , we need to tell it which files need it to load and whether it will load by default /WEB-INF/applicationContext.xml , which is done by setting the parameter in the contextConfigLocation servlet context:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/foobar-service.xml /WEB-INF/foobar-data.xml /WEB-INF/foobar-security.xml </param-value></context-param>
Why not introduce multiple files using spring's import tags how to Load multiple Spring Bean Configuration file
File:spring-all-module.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <import resource="common/Spring-Common.xml"/> <import resource="connection/Spring-Connection.xml"/> <import resource="moduleA/Spring-ModuleA.xml"/>
This is because the application context loaded with Contextloaderlistener is shared by DispatcherServlet the WebApplicationContext for this servlet root application context all loading contexts as the root application context () of the loaded Application context () DispatherServlet .
A Web application can define any number of dispatcherservlets. each servlet would operate in Its own namespace, loading it own application context with mappings, handlers, etc. Only the root application context as loaded by Org.springframework.web.context.ContextLoaderListener , if Any, would be shared.
public class Dispatcherservlet extends Frameworkservlet {...} Public abstract class Frameworkservlet extends Httpservletbean {@Override protected final void Initservletbean () th Rows Servletexception {... try {this.webapplicationcontext = Initwebapplicationcontext (); Initframeworkservlet (); } ... } Protected Webapplicationcontext Initwebapplicationcontext () {Webapplicationcontext WAC = Findwebapplicationcontext (); if (WAC = = null) {//No fixed context defined for this servlet-create a local one. Webapplicationcontext parent = Webapplicationcontextutils.getwebapplicationcontext (Getservletcontext ()); WAC = Createwebapplicationcontext (parent); } if (!this.refresheventreceived) {//apparently not a configurableapplicationcontext with refresh Supp ORT://Triggering initial onrefresh manually here. Onrefresh (WAC); } if (this.publishcontext) {//Publish the context as a servlet context attribute. String attrname = Getservletcontextattributename (); Getservletcontext (). SetAttribute (Attrname, WAC); if (this.logger.isDebugEnabled ()) {This.logger.debug ("Published Webapplicationcontext of servlet '" + GetS Ervletname () + "' as ServletContext attribute with name [" + Attrname + "]"); }} return WAC; }}
Where WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); Contextloaderlistener loads the root application context:
Webapplicationcontext Org.springframework.web.context.support.WebApplicationContextUtils.getWebApplicationContext (ServletContext SC)
Find the root webapplicationcontext for this Web application, which is typically loaded via Org.springframework.web.contex T.contextloaderlistener.
In fact it is just looking for a value in ServletContext that has no key WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE :
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);}public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { Assert.notNull(sc, "ServletContext must not be null"); Object attr = sc.getAttribute(attrName); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (attr instanceof Exception) { throw new IllegalStateException((Exception) attr); } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr;}
Because ContextLoaderListener this key is placed in the ServletContext after loading.
public class Contextloaderlistener extends Contextloader implements Servletcontextlistener {/** * Initialize the root web Application context. */public void contextinitialized (Servletcontextevent event) {This.contextloader = Createcontextloader (); if (This.contextloader = = null) {This.contextloader = this; } this.contextLoader.initWebApplicationContext (Event.getservletcontext ()); }}public class Contextloader {public Webapplicationcontext initwebapplicationcontext (ServletContext ServletContext) { if (Servletcontext.getattribute (webapplicationcontext.root_web_application_context_attribute) = null) { throw new IllegalStateException ("Cannot initialize context because there is already a root application C Ontext present-"+" check whether you had multiple contextloader* definitions in your web.xml! "); } ... try {//Determine parent for root Web applicationContext, if any. ApplicationContext parent = Loadparentcontext (ServletContext); Store context in the local instance variable, to guarantee that//It's available on ServletContext shutdown. This.context = Createwebapplicationcontext (ServletContext, parent); Servletcontext.setattribute (Webapplicationcontext.root_web_application_context_attribute, This.context); ClassLoader CCL = Thread.CurrentThread (). Getcontextclassloader (); if (CCL = = ContextLoader.class.getClassLoader ()) {currentcontext = This.context; } else if (CCL! = null) {Currentcontextperthread.put (CCL, this.context); } ... return this.context; } ... }}
The spring official document gives such a diagram:
However this figure is not correct! In this diagram, Dispatcherservlet loads the webapplicationcontext with the Webapplicationcontext (s) of the biz layer (root applicationcontext, This appellation itself is a bit strange, there is misleading suspicion! ), is a one-to-many relationship! In fact it should be reversed. From the code above, it WebApplicationContextUtils.getWebApplicationContext(servletContext) is the application context of all Dispatcherservlet shared biz tiers that are obtained by the Rootapplicationcontext, which can be seen from the pass-through ServletContext parameter. Because ServletContext itself is the application level, it is shared as the parent context of each dispatcherservlet loaded Web ApplicationContext container.
This can be easily verified by using the Web layer to WebApplicationContextUtils.getWebApplicationContext see if you can get the Web ApplicationContext that Dispatcherservlet loaded. I tried it out, and did not get it, because root applicationcontext (parent) is not aware of and not care, each dispatcherservlet loaded WebApplication (children).
--eof--
From:http://blog.arganzheng.me/posts/spring-and-web-mvc-integration-web-application-context.html
Application context management for the integration of Spring and web MVC--spring