从零开始学习java web,学习web最开始就不得不说web.xml,以前只知道web.xml对web应用来说很重要,却不知道为什么,现在来记录下学习web.xml的标签。
web.xml的加载过程(引用)
在web-app元素内,元素的配置顺序与工程的加载顺序无关,web.xml的加载过程为:
1.启动一个web项目,web容器(如tomcat)读取web.xml文件,读取其中的配置信息
2.容器创建一个servlet上下文(servletContext),这个web项目所有部分共享这个上下文
3.容器将转换为键值对,交给servletContext
4.容器创建中的监听器实例
5.触发contextInitialized方法,listener被调用(当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来处理。ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法contextInitialized;contextDestroyed,web.xml有contextLoaderListener监听器,spring等框架实现了本监听器的接口方法)
6.调用完contextInitialized方法后,容器再对filter初始化
7.容器对web.xml中的指定load-on-startup的值时,
1.当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet。
2.如果值小于0或未指定时,则表示只有在第一次请求的容器才在该servlet调用初始化函数(springMVC的初始化为此阶段。
3.正值越小,(优先级1,2,3...->递减)servlet的优先级越高,应用启动时就越先加载。
4.值相同时,容器就会自己选择顺序来加载。
一般我们会在web.xml中见到如下的标签
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>main.java.spring.test</servlet-class>
<init-param>
<param-name>test</param-name>
<param-value>我是测试param</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
1.1.1 servlet-name标签中是我们声明一个servlet的名字,其中MyServlet就是我声明的一个servlet。
1.1.2 servlet-class标签是我们什么的servlet的全路径,该类需要实现servlet接口(父类实现也可以)。
1.1.3 init-param是当容器初始化该servlet时初始化的键值对,一个servlet标签下可以定义多个,可以通过getInitParameter方法或者getServletConfig().getInitParameter方法获取这些参数。
1.1.4 servlet-mapping标签是定义外部访问路径的请求映射,此处我定义的是所有以 .do结尾的请求都将会被映射到MyServlet这个servlet下。
<context-param>
<param-name>myparam</param-name>
<param-value>我是context-param</param-value>
</context-param>
该标签将会被web容器优先读取转化为键值对交给servletContext,需要获取该键值对的值可以在servlet中用getServletContext().getInitParameter获取。这里和servlet里的 init-param 类似,不过context-param是所有的servlet共享的。
这些设置完之后我们就可以来看看这些标签到底是如何使用的:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<!-- 这是我配置的web.xml -->
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>myparam</param-name>
<param-value>我是context-param</param-value>
</context-param>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>main.java.spring.test</servlet-class>
<init-param>
<param-name>test</param-name>
<param-value>我是测试param</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
//这里是我写的测试servlet,对应web.xml中的 MyServlet
public class test extends HttpServlet {
@Override
public void init(ServletConfig arg0) throws ServletException {
super.init(arg0);
// TODO Auto-generated method stub
System.out.println("初始化servlet");
System.out.println(getServletContext().getInitParameter("myparam"));
System.out.println(getServletConfig().getInitParameter("test"));
System.out.println(getInitParameter("test"));
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("调用servlet");
System.out.println(getServletContext().getInitParameter("myparam"));
System.out.println(getServletConfig().getInitParameter("test"));
System.out.println(getInitParameter("test"));
}
}
将程序用web容器跑起来,访问 http://localhost:8081/spring/.do 重点是以 .do结尾都会映射到该servlet中,第一次访问输出如下:
初始化servlet
我是context-param
我是测试param
我是测试param
调用servlet
我是context-param
我是测试param
我是测试param
第二次访问输出如下:
调用servlet
我是context-param
我是测试param
我是测试param
servlet在容器启动后第一次访问才会去初始化,所以这里第一次访问时,会先调用init方法,再调用service方法。第二次访问由于该servlet已经初始化,所以只会执行service方法。
getServletContext()和getServletConfig()获取的servlet需要区分,getServletContext()是获取上下文,调用getInitParameter方法获取的是context-param里的值,getServletConfig()是获取当前的servlet,调用getInitParameter方法获取的是该servlet里init-param里的值。这里需要注意区分。