Servle過濾器詳解

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. }  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章