写java web程序的人一定对web.xml很熟悉。但却不知道它的具体含义,比如spring集成时,配置文件是什么意思。要想搞清楚,必须弄清楚原生的servlet api的知识。
1,servlet
Servlet可以看成是一次对请求的处理方式,类似于spring中的controller。在一个web应用中,会有很多的servlet,web应用容器会管理这些全部的servlet实例。在api中,servlet角色的行为被定义在了Servlet接口中:最主要的有inti()和service()方法。web容器要初始化一个servlet,要读取它的配置文件,配置信息有servletConfig接口处理。然后有一个GenericServlet同时实现了servlet和servletConfig接口,是所有servlet类的基类,不过它仅仅是将servletConfig的配置信息导入了,真正具有处理请求功能的servlet实现类是httpservlet,它继承自GenericServlet。它的service()方法是一个大的if,选择是get还是post等,真正的请求放在doget和dopost方法里面。我们自己写的servlet只要继承httpservlet即可,复写doget和dopost,不能复写service方法。
2,serlvetContext
这也是一个接口,它主要处理web应用的根环境,也就是整个应用的上下文,即所有serlvet实例的上下文,为不是具体的某一个servlet实例的上下文,这个可能有误解。查看它的api后发现,我们可以通过它得到application作用域的对象,以及初始化根上下文的参数和全部的servlet实例等等。总而言之它就是根上下文,管理全部的web应用相关的资源。web.xml文件其实就是servletcontext的初始化配置文件。
这样,在web应用刚启动的时候,会根据web.xml文件来初始化根上下文,包括全局的变量和各种servlet和listener等。
3,web.xml中的context-param参数
是根上下文的初始化参数,我们可以通过
getServletContext().getInitParameter(String name)
方法得到这些参数。助注意这个参数与application域内的参数不一样,它仅仅是初始化参数,并不在application域对象内。
4,servlet初始化参数
是servlet启动的参数,可以通过
getServletConfig().getInitParameter("name")
方法得到。
5,Listener:
Listener当然有很多,这里只说与servlet相关的。
ServletContextListener监听器用于监听servletcontext初始化和销毁。在serlvetcontext初始化之后和销毁之前处理一下逻辑。
相应的处理函数:
@Override
public void contextInitialized(ServletContextEvent sce) {
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
也就是说当servletcontext创建好之后,会调用contextInitialized()方法。
实现了监听器类后要在web.xml 文件中注册。
下面结合具体实例说明:
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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<context-param>
<param-name>c</param-name>
<param-value>lzy</param-value>
</context-param>
<!-- 配置spring核心servlet -->
<servlet>
<servlet-name>a</servlet-name>
<servlet-class>com.test.HelloServlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>ly</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>a</servlet-name>
<url-pattern>/hello.view</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.test.ContextParamListener</listener-class>
</listener>
</web-app>
配置了根上下文的初始化参数和一个servlet(及servlet的初始化参数)
listener:
package com.test;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextParamListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
String param = sce.getServletContext().getInitParameter("c");
sce.getServletContext().setAttribute("p", param);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
这个监听器读取了servletcontext的初始化参数,并且赋值到application域对象中,名字为p,这样servlet中就可以访问到新的参数了。
Servlet:
package com.test;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer;
try {
writer = response.getWriter();
writer.write("hello");
writer.close();
System.out.println(getServletConfig().getInitParameter("name"));
System.out.println(getServletContext().getInitParameter("c"));
System.out.println(getServletContext().getAttribute("p"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
小结:
context-param是web根上下文的初始化参数
init-param是servlet的初始化参数
listener监听器会被web容器在发生相应的事件时调用(观察者模式)
再看spring:
这样看来,spring就是用spring自身提供的一个servletcontextlistener的实现,根据context-param来读取配置文件,初始化自己的bean容器。当然这个容器是在根上下文内。spring mvc是一个特殊的servlet,原本servlet用来转发不同的请求,springmvc用一个servlet处理全部的请求,将这些请求转发到不同的controller。