Servle过滤器详解

来源:互联网 发布:idea 10开发java web 编辑:程序博客网 时间:2024/05/20 02:24

Servle过滤器详解

  • Servlet过滤器的基本原理:      

     在Servlet作为过滤器使用时,它可以对客户的请求进行处理。处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止。例如,实现用户操作的某个功能,得过滤当前非登录用户的操作,还得过滤处理编码方式,一般是先处理统一编码方式,这两项工作可以在由两个过滤器组成的过滤链里进行处理,过滤链顾名思义就是多个过滤器顺序执行,执行完过滤编码方式后执行非登录过滤。当过滤链处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功,将把视图派发到指定的错误页面。



  • 过滤器生命周期的四个阶段:

1、实例化:Web容器在部署Web应用程序时对所有过滤器进行实例化。Web容器回调它的无参构造方法。

2、初始化:实例化完成之后,马上进行初始化工作。Web容器回调init()方法。

3、过滤:请求路径匹配过滤器的URL映射时。Web容器回调doFilter()方法——主要的工作方法。

4、销毁: Web容器在卸载Web应用程序前,Web容器回调destroy()方法。


  • Servlet过滤器开发步骤:

1、创建实现javax.servlet.Filter接口的类。

2、过滤器的xml配置。


  • Filter接口:

    过滤器类必须实现javax.servlet.Filter接口,此接口包含三个方法:


public void init(FilterConfig config) throws ServletException;//初始化


public void doFilter(ServletRequest request,  ServletResponse response,  FilterChain chain) throws  IOException,ServletException;//过滤


public void destroy();//销毁


  • FilterConfig接口:

在初始化过程中,容器使用 FilterConfig 将配置信息传递给过滤器,此接口又提供以下方法:


public String getFilterName();//获取过滤器名


public ServletContext getServletContext();//获取servlet上下文


public String getInitParameter(String name);//获取参数值


public Enumeration getInitParameterNames();//获取参数值组


  • FilterChain接口:

此接口用于调用过滤链中的下一个过滤器,如果不调用此方法,之后的过滤器就不会有效。


  • 字符集过滤器、Session过滤器、资源过滤器详细代码:

SetCharacterEncodingFilter.java:

[java] view plaincopy
  1. package com.tjcyjd.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. /** 
  13.  * 字符集编码过滤器 
  14.  *  
  15.  * @author yjd 
  16.  *  
  17.  */  
  18. public class SetCharacterEncodingFilter implements Filter {  
  19.   
  20.     public SetCharacterEncodingFilter() {  
  21.         System.out.println("回调字符集过滤器的无参构造方法!");  
  22.     }  
  23.   
  24.     private String charset; // 编码方式  
  25.     private boolean flag; // 标识是否启用过滤器  
  26.   
  27.     public void destroy() {  
  28.         // 销毁过滤器  
  29.         System.out.println("销毁字符集过滤器!");  
  30.   
  31.     }  
  32.   
  33.     public void doFilter(ServletRequest request, ServletResponse response,  
  34.             FilterChain chain) throws IOException, ServletException {  
  35.         if (flag && null != charset) { // 过滤器设为启用且字符编码不为空  
  36.             // 设置编码方式  
  37.             request.setCharacterEncoding(charset);  
  38.             response.setCharacterEncoding(charset);  
  39.             System.out.println("成功使用了字符集过滤器");  
  40.         } else {  
  41.             System.out.println("没有启用字符集过滤器");  
  42.         }  
  43.         chain.doFilter(request, response);  
  44.   
  45.     }  
  46.   
  47.     public void init(FilterConfig config) throws ServletException {  
  48.         // 初始化过滤器  
  49.         this.charset = config.getInitParameter("charset");  
  50.         this.flag = "true".equals(config.getInitParameter("flag"));  
  51.         System.out.println("设置的字符集编码方式为:" + charset + " 是否启用:" + flag);  
  52.   
  53.     }  
  54.   
  55. }  


SessionFilger.java:

[java] view plaincopy
  1. package com.tjcyjd.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. /** 
  13.  * session过滤器 
  14.  *  
  15.  * @author yjd 
  16.  *  
  17.  */  
  18. public class SessionFilter implements Filter {  
  19.     public SessionFilter() {  
  20.         System.out.println("回调Session过滤器的无参构造方法!");  
  21.     }  
  22.   
  23.     private boolean flag; // 标识是否启用过滤器  
  24.   
  25.     public void destroy() {  
  26.         // 销毁过滤器  
  27.         System.out.println("销毁Session过滤器!");  
  28.   
  29.     }  
  30.   
  31.     public void doFilter(ServletRequest request, ServletResponse response,  
  32.             FilterChain chain) throws IOException, ServletException {  
  33.         if (flag) { // 过滤器设为启用  
  34.             System.out.println("成功使用了Session过滤器");  
  35.         } else {  
  36.             System.out.println("没有启用Session过滤器");  
  37.         }  
  38.         chain.doFilter(request, response);  
  39.   
  40.     }  
  41.   
  42.     public void init(FilterConfig config) throws ServletException {  
  43.         // 初始化过滤器  
  44.         this.flag = "true".equals(config.getInitParameter("flag"));  
  45.         System.out.println("设置Session过滤器是否启用:" + flag);  
  46.   
  47.     }  
  48.   
  49. }  

ResourceFilter.java:

[java] view plaincopy
  1. package com.tjcyjd.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. /** 
  13.  * Resource过滤器 
  14.  *  
  15.  * @author yjd 
  16.  *  
  17.  */  
  18. public class ResourceFilter implements Filter {  
  19.   
  20.     public ResourceFilter() {  
  21.         System.out.println("回调Resource过滤器的无参构造方法!");  
  22.     }  
  23.   
  24.     private boolean flag; // 标识是否启用过滤器  
  25.   
  26.     public void destroy() {  
  27.         // 销毁过滤器  
  28.         System.out.println("销毁Resource过滤器!");  
  29.   
  30.     }  
  31.   
  32.     public void doFilter(ServletRequest request, ServletResponse response,  
  33.             FilterChain chain) throws IOException, ServletException {  
  34.         if (flag) { // 过滤器设为启用  
  35.             System.out.println("成功使用了Resource过滤器");  
  36.         } else {  
  37.             System.out.println("没有启用Resource过滤器");  
  38.         }  
  39.         chain.doFilter(request, response);  
  40.   
  41.     }  
  42.   
  43.     public void init(FilterConfig config) throws ServletException {  
  44.         // 初始化过滤器  
  45.         this.flag = "true".equals(config.getInitParameter("flag"));  
  46.         System.out.println("设置Resource过滤器是否启用:" + flag);  
  47.   
  48.     }  
  49.   
  50. }  


控制器类FilterTest.java:

[java] view plaincopy
  1. package com.tjcyjd.controller;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class FilterTest extends HttpServlet {  
  12.     private static final long serialVersionUID = -4431292272342933498L;  
  13.   
  14.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  15.             throws ServletException, IOException {  
  16.         response.setContentType("text/html");  
  17.         PrintWriter out = response.getWriter();  
  18.         out.println("你看行不行??");  
  19.         out.flush();  
  20.         out.close();  
  21.     }  
  22.   
  23.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  24.             throws ServletException, IOException {  
  25.         doPost(request, response);  
  26.     }  
  27. }  

配置文件web.xml:

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
  5.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  6.     <!-- 配置字符集过滤器-->  
  7.     <filter>  
  8.         <filter-name>myCharsetFilter</filter-name>  
  9.         <filter-class>com.tjcyjd.filter.SetCharacterEncodingFilter</filter-class>  
  10.         <init-param>  
  11.             <param-name>charset</param-name>  
  12.             <param-value>UTF-8</param-value>  
  13.         </init-param>  
  14.         <init-param>  
  15.             <param-name>flag</param-name>  
  16.             <param-value>true</param-value>  
  17.         </init-param>  
  18.     </filter>  
  19.     <!-- 配置session过滤器-->  
  20.     <filter>  
  21.         <filter-name>mySessionFilter</filter-name>  
  22.         <filter-class>com.tjcyjd.filter.SessionFilter</filter-class>  
  23.         <init-param>  
  24.             <param-name>flag</param-name>  
  25.             <param-value>true</param-value>  
  26.         </init-param>  
  27.     </filter>  
  28.     <!-- 配置resource过滤器-->  
  29.     <filter>  
  30.         <filter-name>myResourceFilter</filter-name>  
  31.         <filter-class>com.tjcyjd.filter.ResourceFilter</filter-class>  
  32.         <init-param>  
  33.             <param-name>flag</param-name>  
  34.             <param-value>true</param-value>  
  35.         </init-param>  
  36.     </filter>  
  37.     <!-- 过滤器映射文件-->  
  38.     <filter-mapping>  
  39.         <filter-name>myCharsetFilter</filter-name>  
  40.         <url-pattern>/*</url-pattern>  
  41.     </filter-mapping>  
  42.     <filter-mapping>  
  43.         <filter-name>mySessionFilter</filter-name>  
  44.         <url-pattern>/*</url-pattern>  
  45.     </filter-mapping>  
  46.     <filter-mapping>  
  47.         <filter-name>myResourceFilter</filter-name>  
  48.         <url-pattern>/*</url-pattern>  
  49.     </filter-mapping>  
  50.   
  51.     <welcome-file-list>  
  52.         <welcome-file>index.jsp</welcome-file>  
  53.     </welcome-file-list>  
  54.     <!-- 配置servlet-->  
  55.     <servlet>  
  56.         <servlet-name>filterTest</servlet-name>  
  57.         <servlet-class>com.tjcyjd.controller.FilterTest</servlet-class>  
  58.     </servlet>  
  59.   
  60.     <servlet-mapping>  
  61.         <servlet-name>filterTest</servlet-name>  
  62.         <url-pattern>/test</url-pattern>  
  63.     </servlet-mapping>  
  64. </web-app>  

部署项目启动后,控制台打印的信息:

[plain] view plaincopy
  1. 回调Session过滤器的无参构造方法!  
  2. 设置Session过滤器是否启用:true  
  3. 回调Resource过滤器的无参构造方法!  
  4. 设置Resource过滤器是否启用:true  
  5. 回调字符集过滤器的无参构造方法!  
  6. 设置的字符集编码方式为:UTF-8 是否启用:true  


请求访问http://localhost:8080/2012-00001-filter/test时,过滤器执行信息如下:

[plain] view plaincopy
  1. 成功使用了字符集过滤器  
  2. 成功使用了Session过滤器  
  3. 成功使用了Resource过滤器  
可见,执行顺序和配置文件配置的映射顺序有关系,配置在前的先执行。


停止服务器控制台信息如下:

[plain] view plaincopy
  1. 销毁Session过滤器!  
  2. 销毁Resource过滤器!  
  3. 销毁字符集过滤器!  

从上面看出,init()和destroy()方法是和过滤器映射逆序执行的,估计类似栈吧,先把所有的过滤器放到栈里,先进后出,这样的理解不知道对不对。




  • 五个常用过滤器(转):

此接口用于调用过滤链中的下一个过滤器,如果不调用此方法,之后的过滤器就不会有效。

1、使用浏览器不缓存页面的过滤器:

ForceNoCacheFilter.java

[java] view plaincopy
  1. package filter;  
  2.   
  3. import javax.servlet.*;  
  4. import javax.servlet.http.HttpServletResponse;  
  5. import java.io.IOException;  
  6.   
  7. /** 
  8.  * 用于的使 Browser 不缓存页面的过滤器 
  9.  */  
  10. public class ForceNoCacheFilter implements Filter {  
  11.   
  12.     public void doFilter(ServletRequest request, ServletResponse response,  
  13.             FilterChain filterChain) throws IOException, ServletException {  
  14.         ((HttpServletResponse) response).setHeader("Cache-Control""no-cache");  
  15.         ((HttpServletResponse) response).setHeader("Pragma""no-cache");  
  16.         ((HttpServletResponse) response).setDateHeader("Expires", -1);  
  17.         filterChain.doFilter(request, response);  
  18.     }  
  19.   
  20.     public void destroy() {  
  21.     }  
  22.   
  23.     public void init(FilterConfig filterConfig) throws ServletException {  
  24.     }  
  25. }  

2、检查用户是否登录的过滤器:

CheckLoginFilter.java

[java] view plaincopy
  1. package filter;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6. import java.util.StringTokenizer;  
  7.   
  8. import javax.servlet.Filter;  
  9. import javax.servlet.FilterChain;  
  10. import javax.servlet.FilterConfig;  
  11. import javax.servlet.ServletException;  
  12. import javax.servlet.ServletRequest;  
  13. import javax.servlet.ServletResponse;  
  14. import javax.servlet.http.HttpServletRequest;  
  15. import javax.servlet.http.HttpServletResponse;  
  16. import javax.servlet.http.HttpSession;  
  17.   
  18. /** 
  19.  * 用于检测用户是否登陆的过滤器,如果未登录,则重定向到指的登录页面 
  20.  *  
  21.  *  
  22.  * 配置参数 
  23.  *  
  24.  *  
  25.  * checkSessionKey 需检查的在 Session 中保存的关键字 
  26.  *  
  27.  * redirectURL 如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath 
  28.  *  
  29.  * notCheckURLList 不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath 
  30.  *  
  31.  */  
  32. public class CheckLoginFilter implements Filter {  
  33.     protected FilterConfig filterConfig = null;  
  34.     private String redirectURL = null;  
  35.     private List notCheckURLList = new ArrayList();  
  36.     private String sessionKey = null;  
  37.   
  38.     public void doFilter(ServletRequest servletRequest,  
  39.             ServletResponse servletResponse, FilterChain filterChain)  
  40.             throws IOException, ServletException {  
  41.         HttpServletRequest request = (HttpServletRequest) servletRequest;  
  42.         HttpServletResponse response = (HttpServletResponse) servletResponse;  
  43.   
  44.         HttpSession session = request.getSession();  
  45.         if (sessionKey == null) {  
  46.             filterChain.doFilter(request, response);  
  47.             return;  
  48.         }  
  49.         if ((!checkRequestURIIntNotFilterList(request))  
  50.                 && session.getAttribute(sessionKey) == null) {  
  51.             response.sendRedirect(request.getContextPath() + redirectURL);  
  52.             return;  
  53.         }  
  54.         filterChain.doFilter(servletRequest, servletResponse);  
  55.     }  
  56.   
  57.     public void destroy() {  
  58.         notCheckURLList.clear();  
  59.     }  
  60.   
  61.     private boolean checkRequestURIIntNotFilterList(HttpServletRequest request) {  
  62.         String uri = request.getServletPath()  
  63.                 + (request.getPathInfo() == null ? "" : request.getPathInfo());  
  64.         return notCheckURLList.contains(uri);  
  65.     }  
  66.   
  67.     public void init(FilterConfig filterConfig) throws ServletException {  
  68.         this.filterConfig = filterConfig;  
  69.         redirectURL = filterConfig.getInitParameter("redirectURL");  
  70.         sessionKey = filterConfig.getInitParameter("checkSessionKey");  
  71.   
  72.         String notCheckURLListStr = filterConfig  
  73.                 .getInitParameter("notCheckURLList");  
  74.   
  75.         if (notCheckURLListStr != null) {  
  76.             StringTokenizer st = new StringTokenizer(notCheckURLListStr, ";");  
  77.             notCheckURLList.clear();  
  78.             while (st.hasMoreTokens()) {  
  79.                 notCheckURLList.add(st.nextToken());  
  80.             }  
  81.         }  
  82.     }  
  83. }  

3、字符集编码过滤器:

CharacterEncodingFilter.java

[java] view plaincopy
  1. package filter;  
  2.   
  3. import javax.servlet.*;  
  4. import java.io.IOException;  
  5.   
  6. /** 
  7.  * 用于设置 HTTP 请求字符编码的过滤器,通过过滤器参数encoding指明使用何种字符编码,用于处理Html Form请求参数的中文问题 
  8.  */  
  9. public class CharacterEncodingFilter implements Filter {  
  10.     protected FilterConfig filterConfig = null;  
  11.     protected String encoding = "";  
  12.   
  13.     public void doFilter(ServletRequest servletRequest,  
  14.             ServletResponse servletResponse, FilterChain filterChain)  
  15.             throws IOException, ServletException {  
  16.         if (encoding != null)  
  17.             servletRequest.setCharacterEncoding(encoding);  
  18.         filterChain.doFilter(servletRequest, servletResponse);  
  19.     }  
  20.   
  21.     public void destroy() {  
  22.         filterConfig = null;  
  23.         encoding = null;  
  24.     }  
  25.   
  26.     public void init(FilterConfig filterConfig) throws ServletException {  
  27.         this.filterConfig = filterConfig;  
  28.         this.encoding = filterConfig.getInitParameter("encoding");  
  29.   
  30.     }  
  31. }  

4、资源保护过滤器:

SecurityFilter.java

[java] view plaincopy
  1. package filter;  
  2.   
  3. import javax.servlet.Filter;  
  4. import javax.servlet.FilterConfig;  
  5. import javax.servlet.ServletRequest;  
  6. import javax.servlet.ServletResponse;  
  7. import javax.servlet.FilterChain;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import java.io.IOException;  
  11. import java.util.Iterator;  
  12. import java.util.Set;  
  13. import java.util.HashSet; //      
  14.   
  15. /** 
  16.  * 资源保护过滤器 
  17.  */  
  18. public class SecurityFilter implements Filter {  
  19.     // the login page uri  
  20.     private static final String LOGIN_PAGE_URI = "login.jsf";  
  21.   
  22.     // a set of restricted resources  
  23.     private Set restrictedResources;  
  24.   
  25.     public void init(FilterConfig filterConfig) throws ServletException {  
  26.         this.restrictedResources = new HashSet();  
  27.         this.restrictedResources.add("/createProduct.jsp");  
  28.         this.restrictedResources.add("/editProduct.jsp");  
  29.         this.restrictedResources.add("/productList.jsp");  
  30.     }  
  31.   
  32.     public void doFilter(ServletRequest req, ServletResponse res,  
  33.             FilterChain chain) throws IOException, ServletException {  
  34.   
  35.         String contextPath = ((HttpServletRequest) req).getContextPath();  
  36.         String requestUri = ((HttpServletRequest) req).getRequestURI();  
  37.   
  38.         if (this.contains(requestUri, contextPath)  
  39.                 && !this.authorize((HttpServletRequest) req)) {  
  40.             ((HttpServletRequest) req).getRequestDispatcher(LOGIN_PAGE_URI)  
  41.                     .forward(req, res);  
  42.         } else {  
  43.             chain.doFilter(req, res);  
  44.         }  
  45.     }  
  46.   
  47.     public void destroy() {  
  48.     }  
  49.   
  50.     private boolean contains(String value, String contextPath) {  
  51.         Iterator ite = this.restrictedResources.iterator();  
  52.   
  53.         while (ite.hasNext()) {  
  54.             String restrictedResource = (String) ite.next();  
  55.   
  56.             if ((contextPath + restrictedResource).equalsIgnoreCase(value)) {  
  57.                 return true;  
  58.             }  
  59.         }  
  60.   
  61.         return false;  
  62.     }  
  63.   
  64.     private boolean authorize(HttpServletRequest req) {  
  65.         // 处理用户登录  
  66.         /* 
  67.          * UserBean user = 
  68.          * (UserBean)req.getSession().getAttribute(BeanNames.USER_BEAN); 
  69.          *  
  70.          * if (user != null && user.getLoggedIn()) { //user logged in return 
  71.          * true; } else { return false; } 
  72.          */  
  73.         return true;  
  74.     }  
  75. }  


5、限制用户浏览权限:

RightFilter.java

[java] view plaincopy
  1. package filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12.   
  13. public class RightFilter implements Filter {  
  14.   
  15.     public void destroy() {  
  16.   
  17.     }  
  18.   
  19.     public void doFilter(ServletRequest sreq, ServletResponse sres,  
  20.             FilterChain arg2) throws IOException, ServletException {  
  21.         // 获取uri地址  
  22.         HttpServletRequest request = (HttpServletRequest) sreq;  
  23.         String uri = request.getRequestURI();  
  24.         String ctx = request.getContextPath();  
  25.         uri = uri.substring(ctx.length());  
  26.         // 判断admin级别网页的浏览权限  
  27.         if (uri.startsWith("/admin")) {  
  28.             if (request.getSession().getAttribute("admin") == null) {  
  29.                 request.setAttribute("message""您没有这个权限");  
  30.                 request.getRequestDispatcher("/login.jsp").forward(sreq, sres);  
  31.                 return;  
  32.             }  
  33.         }  
  34.         // 判断manage级别网页的浏览权限  
  35.         if (uri.startsWith("/manage")) {  
  36.             // 这里省去  
  37.         }  
  38.     }  
  39.   
  40.     // 下面还可以添加其他的用户权限,省去。  
  41.   
  42.     public void init(FilterConfig arg0) throws ServletException {  
  43.   
  44.     }  
  45.   
  46. }