关于Servlet和Filter的运行机制的原理可以通过网络来获取一些资源进行了解,本文主要通过实验的方式来展示Servlet和Filter之间的运行机制。
1.准备工作
创建两个Filter和一个Servlet,并配置好执行的信息。
EncodingFilter:
说明:类EncodingFilter是一个Filter接口的实现类,其FilterName为EncodingFilter,对请求/TestServlet进行过滤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@WebFilter
(filterName =
"EncodingFilter"
, urlPatterns = {
"/TestServlet"
})
public
class
EncodingFilter
implements
Filter {
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
}
@Override
public
void
doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws
IOException, ServletException {
System.out.println(
"1进入EncodingFilter"
);
response.setContentType(
"text/plain;charset=utf-8"
);
response.setCharacterEncoding(
"UTF-8"
);
response.getWriter().println(
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date())
+
" EncodingFilter output doFilter Before "
);
chain.doFilter(request, response);
response.getWriter().println(
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date())
+
" EncodingFilter output doFilter After "
);
System.out.println(
"6退出EncodingFilter"
);
}
@Override
public
void
destroy() {
}
}
|
RequestFilter:
说明:类RequestFilter是一个Filter接口的实现类,其FilterName为RequestFilter,对请求/TestServlet进行过滤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@WebFilter
(filterName =
"RequestFilter"
, urlPatterns = {
"/TestServlet"
})
public
class
RequestFilter
implements
Filter {
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
}
@Override
public
void
doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws
IOException, ServletException {
System.out.println(
"2进入RequestFilter"
);
response.getWriter().println(
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date())
+
" RequestFilter output doFilter Before "
);
response.getWriter().println(
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date())
+
" RequestFilter output doFilter After "
);
System.out.println(
"5退出RequestFilter"
);
}
@Override
public
void
destroy() {
}
}
|
TestServlet:
说明:类TestServlet是一HttpServlet的子类类,其ServletName为TestServlet,请求URL为/TestServlet。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@WebServlet
(name=
"TestServlet"
,urlPatterns={
"/TestServlet"
})
public
class
TestServlet
extends
HttpServlet {
private
static
final
long
serialVersionUID = -1920658493279782543L;
@Override
protected
void
service(HttpServletRequest req, HttpServletResponse resp)
throws
ServletException, IOException {
System.out.println(
"3进入TestServlet"
);
resp.getWriter().println(
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date())
+
" TestServlet output "
);
System.out.println(
"4退出TestServlet"
);
}
}
|
2.部署,执行
在Servlet2.x中我们需要把Servlet和Filter都配置到web.xml,而Servlet3.x中已经不需要这么做了,可参见上面的代码,可以看出通过注解的方式即可实现配置。
部署环境是Apache Tomcat v7.0。
按照1中代码内容所示,期望的执行顺序是:
EncodingFilter-->RequestFilter-->TestServlet-->RequestFilter->EncodingFilter.
请求:localhost:8080/TestFilter/TestServlet 后如下面图所示即可看出运行结果:
图a-2
注意到图a-1的输出内容和图a-2的地址栏请求和页面内容可以看到,程序运行的结果完全按照我们的期望来执行的。
3.问题
a.上述注解中并没有指定Filter的顺序,那么两个Filter是如何排列顺序的呢?注解中并没有可以指定该顺序的属性,我们知道在Servlet2.x中通过在web.xml配置Filter的顺序来实现的。
b.从上述程序中的EncodingFilter和RequestFilter都执行了chain.doFilter(request,response)方面,如果有Filter没有执行到chain.doFilter(request,response)的话,输出内容又该是怎样的呢?
本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1570689,如需转载请自行联系原作者