通过前面的教程( IDEA用Maven创建Spring MVC项目 示例 )得知,Spring MVC 默认情况下,会有2个 xml 配置文件,分别为:
- /WEB-INF/applicationContext.xml
- /WEB-INF/<servlet-name>-servlet.xml
web.xml 内容如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
1、/WEB-INF/applicationContext.xml
在系统启动时,通过监听器,加载配置文件 applicationContext.xml
,web.xml 相关设置如下:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
2、/WEB-INF/<servlet-name>-servlet.xml
注意:上面的 <servlet-name> 为 DispatcherServlet
类实例的名称,如下名称为:dispatcher
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
在系统启动时,该 DispatcherServlet 会 加载名为 dispatcher-servlet.xml
的配置文件。
当然,我们也可以手动指定其他不同名的(如:first-servlet.xml) 配置文件,如:
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/first-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
web.xml 配置中 ContextLoaderListener 和 DispatcherServlet 的区别
- ContextLoaderListener:是在我们的web容器启动的时候启动的,默认会加载/WEB-INF/下面的applicationContext.xml文件。并创建一个WebApplicationContext容器。
- DispatcherServlet:是在我们第一次访问我们的应用的时候创建的(注意:通常情况下是,配置为系统启动时创建)。这时候它默认加载在/WEB-INF下面的<servlet-name>-servlet.xml配置文件,然后也创建一个WebApplicationContext。这个WebApplicationContext将之前ContextLoaderListener创建的容器作为父容器,因此在父容器中配置的所有Bean都能够被注入到子容器中。
摘自:https://blog.csdn.net/sinat_36710456/article/details/78741209
applicationContext.xml 与 dispatch-servlet.xml 的作用及区别
dispatcher-servlet.xml(在你的项目中也可能写作springmvc-serlvet.xml、spring-serlvet.xml等等)和 applicationContext.xml 中的根元素都是<beans>,两者也同样都可以托管Java Bean,那么两者的区别何在呢?
1.两者的区别:
Spring允许你使用树形的结构定义多个上下文,而applicationContext.xml定义的是“root webapp context”,直译过来就是根应用上下文。而dispatcher-servlet.xml定义一个servlet的应用上下文,是applicationContext.xml上下文的子类。在初始化时,applicationContext.xml首先初始化,而dispatcher-servlet.xml在对应的servlet实例化时启动,因此applicationContext.xml初始化在前,而dispatcher-servlet.xml初始化在后。即使将spring servlet设置为<load-on-startup>1</load-on-startup>,即servlet在应用启动时初始化,dispatcher-servlet.xml的初始化也会在根上下文之后。在一个应用中,可以有多个像dispatcher-servlet.xml一样的上下文,每一个各自服务于一个spring的servlet,比如spring1-servlet.xml用于名字为spring1的servlet,spring2-servlet.xml用于名字为spring2的servlet,并通过在web.xml中的配置进行绑定,如下:
web.xml:
<!--++++++++++++++++++++++++++++++++++++++++++++++++++++--> <!-- spring1 servlet --> <!--++++++++++++++++++++++++++++++++++++++++++++++++++++--> <servlet> <servlet-name>spring1</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!-- 指定spring1-servlet.xml为spring1这个servlet的配置文件 --> <param-value>/WEB-INF/spring1-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>spring1</servlet-name> <url-pattern>/spring1/</url-pattern> </servlet-mapping> <!--++++++++++++++++++++++++++++++++++++++++++++++++++++--> <!-- spring2 servlet --> <!--++++++++++++++++++++++++++++++++++++++++++++++++++++--> <servlet> <servlet-name>spring2</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!-- 指定spring2-servlet.xml为spring2这个servlet的配置文件 --> <param-value>/WEB-INF/spring2-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>spring2</servlet-name> <url-pattern>/spring2/</url-pattern> </servlet-mapping>
从示例中可以看出,我们分别定义了两个spring servlet,第一个叫spring1,其配置文件为spring1-servlet.xml,其上下文也就是spring1-servlet.xml;第二个叫spring2,其上下文为spring2-servlet.xml。
2.依赖注入:
spring-servlet.xml中的bean可以引用父类applicationContext.xml上下文中的bean,例如在spring-servlet.xml中定义了一个bean,类名叫A,A类中有一个成员变量是B类的对象,而B类又是applicationContext.xml中的Bean,那么通过@resouce @autowired等注解或者在配置文件中声明都可以引用到B类的这个bean,但是反之则不行。比如B类中有一个A类的成员变量,通过@resource等方式来引用spring-servlet.xml中的A类的bean,在运行时会报错,提示要注入的bean不存在。其实很容易理解,前面说过,applicationContext.xml初始化在先,因此applicationContext.xml中的bean实例化在先,无法获得spring-servlet.xml的bean。不仅如此,也可能由于spring的servlet对应的上下文是子类,可能有多个,因此在spring1-servlet.xml和spring2-servlet.xml中可能有相同的bean类(比如类型相同、id、name都相同),如果作为父类的applicationContext.xml需要子类的bean,那么Spring框架应该从哪个子类中获得bean呢?有可能Spring的开发者出于这种考虑,设计了父类上下文中的bean不能引用子类上下文中的bean。
3.applicationContext.xml与dispatch-servlet.xml写成一个文件
可以把这两个文件写成一个,比如spring-servlet.xml,然后在web.xml声明根应用上下文为spring-servlet.xml,如下:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
这样spring-servlet.xml同时也具有原来的applicationContext.xml的作用。
但是根据上文,我们知道根上下文是在应用启动时初始化,而servlet对应的上下文随servlet初始化,他们是两个上下文,因此即便是写成同一个文件,也只是使用spring-servlet.xml同时充当根上下文对象,省去了一个xml文件,但是spring-servlet.xml仍会初始化两遍:第一遍是作为根上下文随应用启动时初始化,第二遍是作为spirng servlet对应的上下文随名称为spring的servlet初始化。即如果在spring-servlet.xml声明了一个bean,这个bean会在应用启动时,spring-servlet.xml作为根上下文初始化时,创建一个;然后在servlet启动时,spring-servlet.xml又作为servlet的上下文初始化时,再创建一个。当然,简单的springMVC应用一般只有一个spring servlet,因此applicationContext.xml也可以不用,而把所有的bean都注册到spring servlet对应的上下文,即把web.xml中的
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
这段代码删除掉,只保留spring-servlet.xml文件。这种情况下,如果有些bean需要在应用启动时初始化,那么设置spring servlet为<load-on-startup>1</load-on-startup>
即可。
特别注意: DispatcherServlet 一定会去加载一个 Spring XML 配置文件,如果没有配置 或 默认文件也不存在,则报错!
摘自:https://blog.csdn.net/mr_orange_klj/article/details/78633626