关于Servlet和Filter的运行机制的原理可以通过网络来获取一些资源进行了解,本文主要通过实验的方式来展示Servlet和Filter之间的运行机制。
1.准备工作
创建两个Filter和一个Servlet,并配置好执行的信息。
EncodingFilter:
说明:类EncodingFilter是一个Filter接口的实现类,其FilterName为EncodingFilter,对请求/TestServlet进行过滤。
@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进行过滤。
@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。
@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-1
图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)的话,输出内容又该是怎样的呢?
由于篇幅有限,在“实战-JavaWweb的Servlet和Filter运行机制(二)”中接续实践。
本文出自 “野马红尘” 博客,谢绝转载!