文章目录
- 1. url地址
- 2. HTTP协议(应用层;HTTP=TCP+80)
- 3. Servlet组件
- 3.1. javax.servlet.Servlet接口
- 3.2 javax.servlet.http.HttpServlet
- 3.3. javax.servlet.ServletRequest接口
- 3.4 javax.servlet.ServletResponse
- 3.5 javax.servlet.http.HttpServletRequest
- 3.6 javax.servlet.http.HttpServletResponse
- 3.7.javax.servlet.ServletConfig接口
- 3.8 javax.servlet.ServletContext 接口
- 3.9 javax.servelt.http.HttpSession接口
- 3.10 javax.servlet.http.Cookie
- 3.11 javax.servlet.RequestDispatcher接口
- 4. WebServlet Annotation
- 5. Listener&Event
- 6.Filter组件
- 参考文献
1. url地址
url地址 = 应用层协议+主机IP地址或域名+端口号+资源所在路径/文件名
/s表示文件路径
?表示查询字符串和url地址的分隔符
然后服务器就可以搜到url以及后面连着的查询字符串。
查询字符串用名值对的形式表示
汉字转换为ascii码用的是base64
2. HTTP协议(应用层;HTTP=TCP+80)
HTTP请求格式
- 请求方法+URI+HTTP协议版本
- 请求头(包括浏览器类型,所用语言,请求正文类型等)
- 请求正文(和请求头之间用只有CRLF(\r\n)的行(空行)间隔;请求头里面可以包括客户以POST方式提交的表单)
常见请求方式:GET POST HEAD PUT DELETE
HTTP响应格式
- HTTP协议版本、状态码(404客户端错误,405服务器不支持客户端请求方式,500服务器内部错误)、描述
- 响应头HEAD
- 响应正文
3. Servlet组件
3.1. javax.servlet.Servlet接口
- The servlet is constructed, then initialized with the
init
method. - Any calls from clients to the
service
method are handled. - The servlet is taken out of service, then destroyed with the
destroy
method, then garbage collected and finalized.
package javax.servlet;
public interface Servlet{
public void init(ServletConfig config){
//Servlet指行构造函数创建后,
//由init负责初始化Servlet对象。即容器在创建好Servlet对象后会调用init方法。
}
public void service(ServletRequest req,ServletResponse res)
throws ServletException,IOException{
//负责响应客户端请求,为客户提供相应服务。
//当容器接收到客户端要求访问特定Servlet对象的请求时,就会调用改Servlet对象的service()方法。
}
public void destroy(){
//负责释放Servlet对象占用的资源。
//当Servlt对象结束生命周期时,容器会调用该方法。
}
}
3.2 javax.servlet.http.HttpServlet
3.2.1 GenericServlet
package javax.servlet;
public abstract class GenericServlet{
public void init(ServletConfig config)throws ServletExcpeiton{
this.config = config;
init();
}
public void init()throws ServletException{
//do something to init. e.g. getInitParameter...
}
public java.lang.String getInitParameter(java.lang.String name){}
public java.util.Enumeration getParameternames(){}
ServletContext getServletContext(){
//只是提供方便,实际上还是从ServletConfig处调用config.getservletContext().
}
}
3.2.2 HttpServlet
抽象类,为了快速开发http协议的servlet而创造。
package javax.servlet.http;
public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable{
public void service(ServletRequest req,ServletResponse res)
throws SevrletException,IOExcepiton{
//这个是为了实现GenericServlet的service方法
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
service(request,response);//这里调用下面的那个保护方法
}
protected void service(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String method = "do" + request.getMethod();
//doGet,doPost,doHead,doDelete,doTrace,doPut,...
Method m = null;
try{
m = this.getClass().getDeclaredMethod(method,
HttpServletRequest.class,
HttpServletResponse.class);
m.invoke(this.request);
}catch(Exception e){
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest req,HttpServletResponse res)
throws ServletException,IOException{
//...
}
}
一个例子:
@WebServlet(
urlPatterns = { "/a" },
initParams = {
@WebInitParam(name = "server", value = "www.dlut.edu.cn"),
@WebInitParam(name = "port", value = "80")
})
public class AServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");//在PrintWriter之前,是有效的charset设置。
PrintWriter out = response.getWriter();
Enumeration<String> params = getServletConfig().getInitParameterNames();
while(params.hasMoreElements()) {
String param_name = params.nextElement();
String param_value = getServletConfig().getInitParameter(param_name);
out.println("param-name: " + param_name + ", param-value: " + param_value + "<br>");
}
out.println("---------------------------------------------<br>");
ServletContext context = getServletContext();
params = context.getInitParameterNames();
while(params.hasMoreElements()) {
String param_name = params.nextElement();
String param_value = context.getInitParameter(param_name);
out.println("context param-name: " + param_name + ", context param-value: " + param_value + "<br>");
}
}
3.3. javax.servlet.ServletRequest接口
package javax.servlet;
public interface ServletRequest{
Object getAttribute(String name){}
void setAttribute(String name, Object o){}
Enumeration<String> getAttributeNames(){}
String getParameter(String name){}//url中?后面带的用这个←
Enumeration<String> getParameterNames(){}
String[] getParameterValues(String name){}
String getContentType(){
//Returns the MIME type of the body of the request,
//or null if the type is not known.
}
RequestDispatcher getRequestDispatcher(String path){
//可以相对路径也可以绝对路径。所谓相对路径就是指相对当前Servlet组件的路径;
//所谓绝对路径就是以符号/开头,/表示当前Web应用的url入口。
}
ServletContext getServletContext(){
}
}
3.4 javax.servlet.ServletResponse
headers+两次回车换行+context
写为主。服务器通过网络向浏览器传数据。
package javax.servlet;
public interface ServletResponse
{
PrintWriter getWriter(){
//返回一个PrintWriter
//默认charset是ISO-8859-1
}
ServletOutputStream getOutputStream(){
//Returns a ServletOutputStream suitable for writing binary data in the response.
}
void setCharacterEncoding(String charset){}
void setContentType(String type){
//response.setContextType("text/html;charse=tutf-8");
//如果在getWriter以前写setContextType的话就要写charset.
//如果在getWriter以后or相应提交以后写setContextType的话就没法改charset了,只能用PrintWriter的charset
}
}
在Servlet的service中可能调用ServletResponse和ServletRequest的抛出IllegalStateException的方法,但是service只是throw ServletExcpetion和IOExcpetion的原因:
IllegalStatementException是RuntimeExcpetion,不是检查异常,是由Java运行自动抛出、自动处理,不用我们捕获
3.5 javax.servlet.http.HttpServletRequest
HttpServletRequest接口是ServletRequest接口的子接口。HttpServlet类的重载service方法以及doGet和doPost等方法都有一个HttpServletRequest参数。
注意!上下文路径是请求URI的开始部分;上下文路径总是以/开头,但是结尾没有/。
比如请求URI为/sample/foo/bar,那么上下文路径是/sample.
package javax.servlet.http;
public interface HttpServletRequest extends ServletRequest
{
public String getContextPath(){
//返回客户端所请求访问Web应用的URL入口(或者说是URI)。比如客户端访问http://localhost:8080/helloapp/info的话,调用该方法就返回/helloapp。这和ServletContext.getContextPath不同:ServletContext.getContextPath()返回的是Web项目的路径。
}
public String getServletPath(){
//返回调用这个Servet的request的URL。如果url-pattern是/*的话返回空字符串。
}
public String getPathInfo(){
//返回与客户端发送请求URL相联系的额外路径信息。额外的路径信息实在Servlet路径之后,查询字符串之前的路径,以/开头。比如MyServlet映射为/MyServlet/*,用户请求的URL为/MyServlet/test/foo,则返回/test/foo。如果唯有额外路劲信息则返回null。
}
public Collection<String> getHeaderNames(){}
public Collection<String> getHeaders(String name){}
public String getHeader(String name){}
public Cookie[] getCookies(){}
public String getMethod(){/* GET, POST,PUT, HEAD, DELETE, TRACE*/}
public HttpSession getSession(){}
}
3.6 javax.servlet.http.HttpServletResponse
package javax.servlet.http;
public interface HttpServletResponse{
public void addCookie(Cookie cookie){}
public void addHeader(Striing name,String value){}
public String encodeURL(String url){/*使用session id对url进行编码。不需要编码的话就不变*/}
public String encodeRedirectURL(String url){}
public void sendRedirect(String location){}
public void sendError(int sc, String msg)throws java.io.IOException{}
}
一个例子:
public class LoginSevrlet extends HttpServelt{
public void doGet(HttpServletRequest req,HttpServtelResponse res)
throws ServletExcpetion,IOExcetion{
res.setContentType("text/html;charset=utf-8");
String name = req.getParamenter("name");
if("master".equals(name)){
res.sendRedirect("success.html")
}else{
res.sendError(HttpServeltResponse.SC_SERVICE_UNAVALIABLE,"服务器繁忙,请稍后再试");
}
}
public void doPost(HttpServletRequest req,HttpServletResponse res){
doGet(req,res);
}
}
HttpServletResponse节后的sendRdirect()方法和RequestDispatcher接口的forward()方法都可以利用另外的资源(Servlet/JSP/HTML)来为客户端服务。但是这两种方法有本质区别:重定向URL会变,forward的URL不变;重定向可不仅可以搞位于同意主机上的不同web应用程序,还可以搞到qi’ta服务器上的web应用程序资源。
3.7.javax.servlet.ServletConfig接口
Servlet接口的void init(ServletConfig config)
方法有一个ServletConfig
类型的参数。当Servlet容器初始化一个Servlet对象的时候,会为这个Servlet对象创建一个ServletConfig
对象。在ServletConfig
对象中包含了Servlet的初始化信息。
1)String getInitParameter(String name)
:根据给定的初始化参数名,返回匹配的初始化参数值
2) Enumeration<String> getInitParameterNames()
:返回所有初始化参数名
因为Servlet可以getServletConfig(),所以可以通过ServletConfig来getInitParameter()
<servlet>
<servlet-name>Font</servlet-name>
<servlet-class>mypack.FontServer</servlet-class>
<init-param>
<param-name>color</param-name>
<param-value>blue</param-value>
<init-param>
<init-param>
<param-name>color</param-name>
<param-value>green</param-value>
<init-param>
</servlet>
<servlet-mapping>
<servlet-name>Font</servlet-name>
<url-pattern>/font</url-pattern>
</servlet-mapping>
3)getServletName():返回web.xml中ret的ret位置的值。
4)getServletContext():返回一个ServletContext对象。
3.8 javax.servlet.ServletContext 接口
ServletContext是Servlet和Servlet容器之间季节通信的接口。Servlet容器在创建一个Web应用时,会为他创建一个ServletContext对象。
每个web应用都有唯一的ServletContext做总管家,每个Servlet对象通过这个总管家来访问容器中的各种资源。
ServletContext的方法由如下几种:
package javax.servlet;
public interface ServletContext{
//1)用于在Web应用范围内获取共享数据:
public Object getAttribute(String name){}
public void setAttribute(String name, java.lang.Object object){}
public Enumeration<String> getAttributeNames(){}
//2) 用于访问当前Web应用资源:
public getContextPath(){}/*返回web应用的项目根目录*/
public getInitParameter(String name){}
public getInitParameterNames(){}
public getServletContextName(){}
public RequestDispatcher
getRequestDispatcher(String path){}/*path必须是绝对路径,被解释为上下文根路径*/
//3)访问Servlet容器中的其他Web应用
public getContext(String uripath){}/*根据参数指定的uri,返回当前Servlet容器中其他Web应用的ServletContext对象。*/
//4) 访问服务器端的文件系统资源
public getRealPath(String path){}/*根据参数指定的虚拟路径,返回文件系统中的一个真实路径*/
public getResource(String path){}/*返回一个用于读取参数指定的文件的输入流*/
public getResourceAsStream(String path){}/*返回一个用于读取参数指定的文件的输入流。在ServletContextListener中有所体现*/
}
3.9 javax.servelt.http.HttpSession接口
Session用来跟踪用户跨页面request,并且可用于存储用户信息。比如用来保存购物车数据。这个数据保存在session里面最合适,ServletContext和ServletConfig都不合适。Serlet container使用这个接口来创建HTTP Server和HTTP Client之间的session。当application在一个session中存储了一个object或者删除了一个object,session检查这个object有木有实现HttpSessionBindingListener接口。如果实现了的话就notifies这个object,告诉它它被绑定/解绑于这个session。如果session到期了或者invalidated了,也会发通知。
package javax.servlet.http;
public interface HttpSession{//需要存储到硬盘文件的session需要实现Seriaziable序列化接口
//1)在HttpSession对象中查找,移除,设置属性
public java.lang.Object getAttribute(String name){}
public java.util.Enumeration getAttributeNames(){}
public void removeAttribute(java.lang.String name){}
public void setAttribute(java.lang.String name,java.lang.Object value){}
//2)和生存时间有关的参数
public long getCreationTime(){}//获取session创建时间,起点为Jan 1, 1970 GMT
public long getLastAccessedTime(){}//获取上次与服务器交互时间,起点为 Jan 1, 1970 GMT. 毫秒
public setMaxInactiveInterval(int interval){/*在ServletAPI中设置超时时间(session最大的不活动间隔时间),单位是秒;负值的话永不失效*/}
}
超时时间也可以在web.xml里面设置:
<session-config>
<session-time-out>30 <!--单位为分钟,针对单个应用--></session-time-out>
</session-config>
项目的web.xml中设置的话针对单个应用,Tomcat的/conf/web.xml中设置的话针对的是整个容器。
优先级: Servlet中API设置>程序web.xml设置> Tomcat/conf/web.xml设置。
如果超时了(本次访问和上次访问间隔时间大于session最大不活动时间),上次会话结束,客户端服务器之间产生新session,和新的sessionID;原来session中的属性全部丢失。
**session的获取:**HttpServletRequest 的 getSession() 方法
HttpSession session = request.getSession();
Cart cart = new Cart();//Cart类已经实现了序列化接口
session.setAttribute("mycart",Cart);
request.getSession使得当前HttpServlet支持会话。如果会话已经存在,就返回相应的HttpSession对象。否则就创建一个新会话,并返回新建的HttpSession对象。相当于request.getSession(true)。
注意:jsp中,如果制定了<%@page session=“false”%>,那么JSP中无法直接访问内置的session变量。同时也不会主动创建session。因为此时JSP未能自动指行request.getSession()操作获取session。
request如何携带ID(跟踪会话)
-
cookie实现session。
-
url重写来跟踪会话
<a href="maillogin.hsp">
改为
<a href="%=response.encodeURL("maillogin.jsp")%>">
- 隐藏域
孙鑫P457
3.10 javax.servlet.http.Cookie
Cookie使在客户端访问Web服务器的时候,客户端在硬盘上存放的信息。就好像是服务器送给客户端的小点心一样。服务器可以根据Cookie来判断跟踪客户的状态。
Cookie的运行机制由HTTP协议规定,多数Web服务器和浏览器都支持Cookie。Web服务器为了支持Cookie,要具备以下功能:
- 在HTTP相应结果中添加Cookie数据。
- 解析HTTP请求中的Cookie数据。
客户端浏览器为了支持Cookie,需要支持一下功能:
- 解析HTTP相应结果中的Cookie数据
- 把Cookie数据保存到本地硬盘
- 读取本地硬盘上的Cookie数据,把它添加到HTTP请求中。
Tomcat作为Web服务器,提供了javax.servlet.http.Cookie 来让服务器访问Cookie。
package javax.servlet.http;
public class Cookie extends Object implements Clonable, Serializable{
//服务器从客户端读
String getName(){}
String getValue(){}
//服务器向客户端写
void setMaxAge(int expiry){}
void setValue(String newValue)
}
//服务器从客户端读Cookie:
PrintWriter out = response.getWriter();
Cookie [] cookies = request.getCookies();
if(cookies != null){
for(int i = 0;i < cookies.length;i ++){
out.println("name" + cookie[i].getName());
out.println("value" + cookie[i].getValue());
out.println("max age" + cookie.getMaxage());
}
}else{
out.println("No cookie.");
}
//服务器向客户端写Cookie
//调用HttpServletResponse中的addCookie()方法,把Cookie添加到HTTP相应结果中:
Cookie theCookie = new Cookie("username","Emanon");
response.addCookie(theCookie);
Cookie有效期为-1代表着这个Cookie仅存于当前浏览器,其他浏览器进程无法访问这个Cookie。
3.11 javax.servlet.RequestDispatcher接口
void forward(ServletRequest request, ServletResponse response)
转法一个request从一个servlet到server上的另一个地方(比如servlet,JSP文件或者html文件)void include(ServletRequest request, ServletResponse response)
在response里包含了某种资源(比如servlet,JSP页面,HTML文件)的内容
使用:
Servlet可以通过两种方式得到Request Dispatcher对象:
* (1)调用ServletContext的getReuqestDispatcher(String path)
* (2)调用ServletRequest的getRequestDispatcher(String path)
两者path的意义都是指定目标组件的路径。但是从ServletContext调用的RequestDispatcher的路径必须是绝对路径但是从RequestDispatcher得到的RequestDispatcherc的参数就既可以是绝对路径y又可以是相对路径。
@WebServlet("/ASerlet")
public class MyServlet extends HttpServelt
{
void doGet(HttpServletRequest request, HttpServletResponse)
throws ServletException, HttpException
{
//...
request.getRequestDispatcher("login.html").forward(requestm,response);
//转发一个相对路径
}
void doPost(HttpServletRequest reuqest, HttpServletResponse response)
{
request.getRequestDispatcher("AServlet").forward(request,response);
//转发一个相对路径~
}
}
4. WebServlet Annotation
- name属性可以指定也可以不指定,通过getServletName()取得。如果不指定,则为Servlet的完整类名(带着包名的那种)
- urlpattern可以设置多个值,也可以用正则表达式。常用
- /* 或者/ : 拦截所有
- *.do 拦截后缀;拦截后缀必须使用相对路径。
- /user/test 拦截绝对路径
- 不可以有/*.do
- 只有value属性的时候可以不写value=
- value属性和urlpattern属性是等价的
声明Filter:
@WebFilter(dispatcherTypes = {DispatcherType.REQUEST },
urlPatterns= {"/user/test", "/user/example"})
声明Servlet
@WebServlet(urlPatterns= {"/user/test", "/user/example"})
声明监听器
@WebListener
被@WebListener标注的类必须实现以下至少一个监听接口:
javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.ServletRequestListener
javax.servlet.ServletRequestAttributeListener
javax.servlet.http.HttpSessionListener
javax.servlet.http.HttpSessionAttributeListener
@WebInitParam
和@WebFilter和@WebServlet一起使用,充当<init-param>子元素
@ClientEndpoint
5. Listener&Event
5.1 ServletContextListener
ServletContextListener接口可以监听ServletContext对象的生命周期。ServletContext就是那个Servlet总管家,也实际上是监听Web应用的生命周期。
当Servlet容器启动或终止Web应用时,会触发SevrletConetxtEvent时间。该事件由ServletContextListener来处理:
package javax.servlet;
public interface ServletContextListener{
default void contextInitialized(ServletContextEvent sce){
//当Servlet容器qidongWeb应用的时候调用该方法。调用完后,容器再对Filter进行初始化,并且对那些在Web应用启动时就需要被初始化的Servlet进行初始化。
}
default void contextDestroyed(ServletContextEvent sce){
//dangServlet种植Web应用的时候第哦啊用,调用之前,会先销毁所有Servlet和Filter。
}
}
我们自己可以定义自己的MyServletContextListener:
package mypack;
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContext sce){
ServletContext = sce.getServletContext();
String jndi = sc.getInitParameter("jndi");
Context ctx = null;
try{
ctx = new Initialcontext();
DataSource ds = (DataSource)ctx.lookup(jndi);
sc.setAttribute("datasource",ds);
}catch(Exception e){
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce){
ServletContext context = sce.getServletContext();
Counter counter = (Counter)context.getAttribute("datasource");
if(counter != null)
{
System.out.println("曾经来过");
}
}
}
用户自定义的MyServletContextListener监听器只有现象servlet容器注册,servlet容器启动或终止的时候才会调用该监听器的相关方法。在web.xml中,元素用于向容器注册监听器:
<web-app>
<listener>
<listener-class>mypack.MyServletContextListener</listener-classlistener-context>
</listener>
</web-app>
5.2 HttpSessionBindingListener
如果一个对象实现了这个接口,当他被绑定到Session/被Session删除的时候,Servlet容器会通知这个对象。而这个对象在接收到通知后,可以做一些初始化或者清除状态的操作。
5.3 ServletContextEvent
package javax.servlet;
public class ServletContextEvent extends java.util.EventObject
implements Serializable{
ServletContext getServletContext(){
//Return the ServletContext that changed.
}
}
6.Filter组件
6.1 javax.servlet.Filter 接口
- filter可以对一部分客户请求进行预处理操作,然后再把请求转发给相应的Web组件。等到Web组件生成了相应结果后,过滤器还能对相应结果进行检查和修改,然后再把修改后的相应结果发给客户。各web组件中的相同操作可以放到一个过滤器里面完成,这样减少了重复编码。
- 责任链设计模式
一些Filter的应用:加密,压缩,图像转换,身份验证,登陆,etc
一个例子
//MyFilter.java
public class MyFilter implements Filter
{
private FilterConfig config;
public void init(FilterConfig config){
this.config = config;
//在web应用启动的时候,Servlet容器先创建了包含过滤器配置信息的FilterConfig对象,然后创建了Filter对象。接着调用Filter对象的init方法。在init里面可以通过config这个大管家来读取web.xml文件中为过滤器配置的初始化参数。
}
public void doFilter(ServletReqest request,ServletResponse response)
throws ServletException,IOExcpetion
{
//pre-filter code
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
HttpSession session = request.getSession();
String username = session.getParameter("username");
if(usernmae == null || username.lenght() == 0)
{
request.getDispatcher("login.html").forward(request,response);
}
//这个方法完成实际的过滤操作。当客户请求访问的URL和过滤器的URL匹配的时候,Servlet容器将先调用过滤器的doFilter方法。FilterChain用于访问后续过滤器或者web组件。
chain.doFilter(request,response);
//post-filter code
}
public void destroy()
{
config = null;
}
}
6.2 配置文件书写
发布过滤器的时候,必须在web.xml文件中加入元素和元素,或者Annotation一下。元素用来定义一些过滤器,如下所示:
例1:
<filter>
<filter-name>f1</filter-name>
<filter-class>f1.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>f1</filter-name>
<url-pattern>/*</url-pattern>
<dispacther>REQUEST</dispatcher>
</filter-mapping>
这里url-pattern表示所有的url地址都要经过这个filter过滤。dispatcher的子元素不写的话默认发布方式是REQUEST。
例2:
如果有一个这样的Servlet,如何写一个针对他的Filter呢?
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>a.Servlet</servlet-class>
</servlet>
<servelt-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
答案:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>b.MyFilter</filter-class>
<filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servelt-name>AServelt</servlet-name>
<dispatcher>REQUEST</diapatcher>
</filter-mapping>
另外,用Annotationd写的话
@WebFilter(dispactherTypes={DispatcherType.REQUEST},urlPatterns={"/a"})
这样写注解就很简洁。还可以:
@WebFilter(dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE},
urlPatterns= {"/a"})
访问资源经过多个过滤器的过滤器执行顺序
若使用web.xml声明,优先匹配<url-pattern>
,然后是<servlet-name>
.若有多个,按照声明顺序。
Enum DispatcherType
servelt3.0规范中,<filter-mapping>
中的子标签<dispatcher>
里面的元素会被转化为枚举类型DispatcherType。DispatcherType由五个可能值,并且可以在一个<filter-mapping>
中加入任意数目的<dispatcher>
,使得filteri将会作用于:
- 1)直接从客户端过来的request(REQUEST)
- 2)forward来的request(FORWARD)
- 3)include来的request(INCLUDE)
- 4)通过类的request(ERROR):
<error-page>
<error-code>400</error-code>
<location>/filter/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/filter/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/filter/error.jsp</location>
</error-page>
上面的意思是,HTTP请求相应的状态码只要是400,404,500直以,容器就会请求转发到error.jsp之下,这就出发了一次error,走进了DispatcherFilter。但是要注意,虽然把请求转发到error.jsp是一次forward过程,但是配置成<dispatcher>FORWARD</dispatcher>
的话并不会走Dispatcher过滤器。
- 5)还有ASYNC异步而来的请求。有这个的Filter可以拦截异步servlet。
这五种dispatcher方法可以单独使用也可以组合使用。配置多个<dispatcher></dispatcher>
即可。
参考文献
孙鑫 深入详解Servlet/JSP
孙卫琴 Tomcat与Java Wev开发技术详解