FilterChain 执行过程

下面是一个避免提交数据乱码问题的EncodingFilter:

   1. package anni; 
   2. import java.io.IOException; 
   3. import javax.servlet.Filter; 
   4. import javax.servlet.FilterChain; 
   5. import javax.servlet.FilterConfig; 
   6. import javax.servlet.ServletException; 
   7. import javax.servlet.ServletRequest; 
   8. import javax.servlet.ServletResponse; 
   9. public class EncodingFilter implements Filter { 
  10. public void init(FilterConfig config) throws ServletException {} 
  11. public void destroy() {} 
  12. public void doFilter(ServletRequest request, 
  13. ServletResponse response, 
  14. FilterChain chain) 
  15. throws IOException, ServletException { 
  16. request.setCharacterEncoding("gb2312"); 
  17. chain.doFilter(request, response); 
  18. } 
  19. } 

package anni; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class EncodingFilter implements Filter { public void init(FilterConfig config) throws ServletException {} public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("gb2312"); chain.doFilter(request, response); } }

相应的web.xml为:

   1. <filter> 
   2. <filter-name>EncodingFilter</filter-name> 
   3. <filter-class>anni.EncodingFilter</filter-class> 
   4. </filter> 
   5. <filter-mapping> 
   6. <filter-name>EncodingFilter</filter-name> 
   7. <url-pattern>/*</url-pattern> 
   8. </filter-mapping> 

<filter> <filter-name>EncodingFilter</filter-name> <filter-class>anni.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

过滤控制访问权限的SecurityFilter:

   1. public void doFilter(ServletRequest request, 
   2. ServletResponse response, 
   3. FilterChain chain) 
   4. throws IOException, ServletException { 
   5. HttpServletRequest req = (HttpServletRequest) request; 
   6. HttpServletResponse res = (HttpServletResponse) response; 
   7. HttpSession session = req.getSession(); 
   8. if (session.getAttribute("username") != null) { 
   9. chain.doFilter(request, response); 
  10. } else { 
  11. res.sendRedirect("../failure.jsp"); 
  12. } 
  13. } 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(); if (session.getAttribute("username") != null) { chain.doFilter(request, response); } else { res.sendRedirect("../failure.jsp"); } }

相应的web.xml为:

   1. <filter> 
   2. <filter-name>SecurityFilter</filter-name> 
   3. <filter-class>anni.SecurityFilter</filter-class> 
   4. </filter> 
   5. <filter-mapping> 
   6. <filter-name>SecurityFilter</filter-name> 
   7. <url-pattern>/admin/*</url-pattern> 
   8. </filter-mapping> 

<filter> <filter-name>SecurityFilter</filter-name> <filter-class>anni.SecurityFilter</filter-class> </filter> <filter-mapping> <filter-name>SecurityFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>

EncodingFilter负责设置编码,SecurityFilter负责控制权限,那这两个过滤器是怎么起作用的呢?它们两个同时过滤一个请求时谁先谁后呢?

所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的 doFilter()方法。执行的顺序就如上图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的 chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的 chain.doFilter()之后的代码,最后返回响应。

因此在07-02中执行的代码顺序是:

   1.

      执行EncodingFilter.doFilter()中chain.doFilter()之前的部分:request.setCharacterEncoding("gb2312");
   2.

      执行SecurityFilter.doFilter()中chain.doFilter()之前的部分:判断用户是否已登录。

      如果用户已登录,则访问请求的资源:/admin/index.jsp。

      如果用户未登录,则页面重定向到:/failure.jsp。
   3.

      执行SecurityFilter.doFilter()中chain.doFilter()之后的部分:这里没有代码。
   4.

      执行EncodingFilter.doFilter()中chain.doFilter()之后的部分:这里也没有代码。

过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。

你可能感兴趣的:(jsp,xml,Web,servlet)