Java Web Servlet 加载 web.xml 启动过程
web.xml启动
一、web.xml简单参数说明
1、display-name
<!--定义了web应用的名称
一般display-name都不用写的 ,只是一个标记
-->
<display-name>tcDemo1</display-name>
2、context-param
<!-- spring config -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml </param-value>
</context-param>
3、listener
<!--ContextLoaderListener监听器的作用就是启动Web容器时,
自动装配ApplicationContext的配置信息
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
4、filter
<!-- 字符集过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!--
HiddenHttpMethodFilter过滤器
restful风格编码
如果不加HiddenHttpMethodFilter过滤器 就不支持 put和delet
<input type="hidden" name="_method" value="DELETE">
-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<servlet-name>springMVC3</servlet-name>
<url-pattern>/</url-pattern>
</filter-mapping>
5、servlet
<!--
//配置Spring MVC,指定处理请求的Servlet,有两种方式:
1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml
2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。
这里使用的是第二种方式
-->
<!-- Springmvc的核心控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定springmvc的配置文件的地址
servlet范围内的参数,只能在servlet的init()方法中取得,
初始化servlet getServletConfig().getInitParameter("initParam")
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml</param-value>
</init-param>
<!--负数或者0代表延时加载,第一次调用的时候采取加载
数字越小优先级越高
-->
<load-on-startup>0</load-on-startup>
</servlet>
6、welcome-file-list
<!--定义欢迎页面-->
<!--如果index.html在/WEB-INF目录下,要配置成/WEB-INF/index.jsp
如果index.html在/WEB-INF目录下,访问方法:
127.0.0.1:8080/tcDemo1/ 可以访问,
127.0.0.1:8080/tcDemo1/index.html 不可访问,不可以添加index.html
根目录可以
-->
<welcome-file-list>
<welcome-file>/WEB-INF/index.jsp</welcome-file>
</welcome-file-list>
7、error-page
<!--定义错误页面-->
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
二、web.xml启动顺序
- 启动一个web项目,web容器(如tomcat)读取web.xml文件,读取其中的配置信息节点context-param、listener
- 容器将创建一个ServletContext(又称为:Servlet上下文),应用范围内即整个WEB项目都能使用这个Servlet上下文。
a: 容器中所有的servlet都共享同一个ServletContext
b:每个servlet都有它独有的serveltConfig信息,相互之间不共享 - 容器将< context-param >转化为键值对,并交给ServletContext。
- 容器创建< listener >中的类实例,即创建监听。(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)
1、web容器去读取web.xml文件,并且运行ContextLoaderListener监听器,该监听器因为实现了ServletContextListener接口,所以当发现容器生成了一个ServletContext实例的时候,便会执行ServletContextListener接口的初始化方法,在该初始化方法中根据contextConfigLocation指定的位置去读取spring的主要配置文件,然后生成web应用上下文WebApplicationContext,并且将其作为一个属性注入到ServletContext中。(作为servletContext的一个attribute,属性)并且在WebApplicationContext中保留了一个servletContext。
2、监听中会有contextInitialized(ServletContextEvent args)初始化方法
还有有一个contextDestroyed(ServletContextEvent event) 销毁方法。(用于关闭应用前释放资源,比如说数据库连接的关闭。)
ps:
触发contextInitialized方法,listener被调用(当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法contextInitialized;contextDestroyed,web.xml有contextLoaderListener监听器,spring等框架实现了本监听器的接口方法)
- 初始化WebApplicationContext以后,启动了“业务层”的spring容器,并开始加载并初始化applicationContext配置文件中所扫描的类。
- 然后就是初始化filter,最后初始化servlet。
三、web.xml问题
-
webApplicationContext和servletContext关系?
web项目,WebApplicationContext的生成必须要在web容器存在的情况下才能实现,因为他需要ServletContext,而ServletContext是web容器生成的。
-
context-param,listener,filter,servlet配置语句在web.xml中的顺序,改变web.xml位置顺序其启动顺序是否会变呢?
启动顺序: ServletContext -> context-param(无顺序)-> listener(无顺序)-> filter(书写顺序) -> servlet(load-on-startup优先级)–>spring
1、web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring]
2、web.xml节点的加载顺序与它们在web.xml中位置的先后无关。即使把servlet的配置放在最前面,其加载顺序还是会在最后。
3、但是在同一类型的配置项中,其在web.xml的顺序会影响其启动的顺序,比如有两个filter,filter1在配置文件中先于filter2,则filter1先于filter2被加载实例化。
4、某类配置节点而言,位置的先后是有要求的必须在后定义,否则当解析到时,它的还没有定义。
-
applicationContext.xml和dispatcher-servlet.xml加载顺序?
先加载applicationContext.xml 再加载dispatcher-servlet.xml
1、applicationContext.xml 是Spring的全局配置文件,用来控制Spring特性,管理Bean的容器。是随ContextLoaderListener而加载的
2、dispatcher-servlet.xml是SpringMVC中用作控制器,拦截器、转发view等作用。是随DispatcherServlet而加载的
web.xml配置
一、web.xml头定义
//web.xml v2.3
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>
</web-app>
//web.xml v2.4
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
//web.xml v2.5
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
//web.xml v3.0
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
</web-app>
//Web4.0
//在SpringMVC中JSP页面通过${message}始终无法获取这个变量在Controller传递过来的值。
//偶然发现问题在于web.xml文件中声明的Web2.3不支持如上的变量引用,所以就创建了Web4.0的项目,将其开头声明替换成Web4.0的就解决了
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
</web-app>
二、 web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--定义了web应用的名称 一般display-name都不用写的 ,只是一个标记-->
<display-name>tcDemo1</display-name>
<!--****************************上下文初始化参数***************************-->
<!-- 全局应用参数 -->
<!-- webapp.root"这个字符串可以随便写任何字符串。如果不配置默认值是"webapp.root"。
可以用System.getProperty("webapp.root")来动态获项目的运行路径。
一般返回结果例如:/usr/local/tomcat6/webapps/项目名
通过getServletContext().getInitParameter("contextParam")的方式获取;
-->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>business.root</param-value>
</context-param>
<!-- spring config -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml</param-value>
</context-param>
<!--加载Log4J 配置文件 注意路径-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/classes/log4j.properties</param-value>
</context-param>
<!--ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--Log4jConfigListener已经包含了WebAppRootListener的功能
WebAppRootListener来监听器运行时的项目路径
-->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!--定义欢迎页面-->
<!--如果index.html在/WEB-INF目录下,要配置成/WEB-INF/index.jsp
如果index.html在/WEB-INF目录下,访问方法:
127.0.0.1:8080/tcDemo1/ 可以访问,
127.0.0.1:8080/tcDemo1/index.html 不可访问,不可以添加index.html
根目录可以
-->
<welcome-file-list>
<welcome-file>/WEB-INF/index.jsp</welcome-file>
</welcome-file-list>
<!--定义错误页面-->
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>414</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>505</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>400</error-code>
<location>/error.jsp</location>
</error-page>
<!--****************************过滤器配置*********************************-->
<!-- 字符集过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!--
restful风格编码 如果不加HiddenHttpMethodFilter过滤器 就不支持 put和delet
<input type="hidden" name="_method" value="DELETE">
-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<servlet-name>springMVC3</servlet-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
//配置Spring MVC,指定处理请求的Servlet,有两种方式:
1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml
2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。
这里使用的是第二种方式
-->
<!-- Springmvc的核心控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定springmvc的配置文件的地址
servlet范围内的参数,只能在servlet的init()方法中取得,
初始化servlet getServletConfig().getInitParameter("initParam")
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml</param-value>
</init-param>
<!--负数或者0代表延时加载,第一次调用的时候采取加载
数字越小优先级越高
-->
<load-on-startup>0</load-on-startup>
</servlet>
<!-- 这里有三种配置url-pattern方案
1、*.do:后缀为.do的请求才能够访问到该servlet[用这个]
2、/ :所有请求都能够访问到该servlet(除jsp),包括静态请求(处理会有问题,不用)
3、/* :有问题,因为访问jsp也会到该servlet,而访问jsp时,我们不需要这样,也不用
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
参考资料:
https://blog.youkuaiyun.com/qq_40693828/article/details/81086588?biz_id=102
https://www.cnblogs.com/roy-blog/p/7656834.html