1. 程式人生 > >JavaWeb學習 (二十四)————Filter(過濾器)常見應用

JavaWeb學習 (二十四)————Filter(過濾器)常見應用

一、統一全站字元編碼

  通過配置引數charset指明使用何種字元編碼,以處理Html Form請求引數的中文問題

複製程式碼
 1 package me.gacl.web.filter;
 2 
 3 import java.io.IOException;
 4 import javax.servlet.Filter;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.FilterConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletRequest;
 9 import javax.servlet.ServletResponse;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletRequestWrapper;
12 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: CharacterEncodingFilter
16 * @Description: 此過濾器用來解決全站中文亂碼問題
17 * @author: 孤傲蒼狼
18 * @date: 2014-8-31 下午11:09:37
19 *
20 */ 
21 public class CharacterEncodingFilter implements Filter {
22 
23     private FilterConfig filterConfig = null;
24     //設定預設的字元編碼
25     private String defaultCharset = "UTF-8";
26 
27     public void doFilter(ServletRequest req, ServletResponse resp,
28             FilterChain chain) throws IOException, ServletException {
29         
30         HttpServletRequest request = (HttpServletRequest) req;
31         HttpServletResponse response = (HttpServletResponse) resp;
32         String charset = filterConfig.getInitParameter("charset");
33         if(charset==null){
34             charset = defaultCharset;
35         }
36         request.setCharacterEncoding(charset);
37         response.setCharacterEncoding(charset);
38         response.setContentType("text/html;charset="+charset);
39         
40         MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
41         chain.doFilter(requestWrapper, response);
42     }
43 
44     public void init(FilterConfig filterConfig) throws ServletException {
45         //得到過濾器的初始化配置資訊
46         this.filterConfig = filterConfig;
47     }
48     
49     public void destroy() {
50 
51     }
52 }
53 
54 /*
55 1.實現與被增強物件相同的介面 
56 2、定義一個變數記住被增強物件
57 3、定義一個構造器,接收被增強物件
58 4、覆蓋需要增強的方法
59 5、對於不想增強的方法,直接呼叫被增強物件(目標物件)的方法
60  */
61  
62 class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
63     
64     private HttpServletRequest request;
65     public MyCharacterEncodingRequest(HttpServletRequest request) {
66         super(request);
67         this.request = request;
68     }
69     /* 重寫getParameter方法
70      * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
71      */
72     @Override
73     public String getParameter(String name) {
74         
75         try{
76             //獲取引數的值
77             String value= this.request.getParameter(name);
78             if(value==null){
79                 return null;
80             }
81             //如果不是以get方式提交資料的,就直接返回獲取到的值
82             if(!this.request.getMethod().equalsIgnoreCase("get")) {
83                 return value;
84             }else{
85                 //如果是以get方式提交資料的,就對獲取到的值進行轉碼處理
86                 value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
87                 return value;
88             }
89         }catch (Exception e) {
90             throw new RuntimeException(e);
91         }
92     }
93 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1  <filter>
 2       <filter-name>CharacterEncodingFilter</filter-name>
 3       <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>
 4       <init-param>
 5           <param-name>charset</param-name>
 6           <param-value>UTF-8</param-value>
 7       </init-param>
 8   </filter>
 9   
10   <filter-mapping>
11       <filter-name>CharacterEncodingFilter</filter-name>
12       <url-pattern>/*</url-pattern>
13   </filter-mapping>
複製程式碼

二、禁止瀏覽器快取所有動態頁面

  有3 個HTTP 響應頭欄位都可以禁止瀏覽器快取當前頁面,它們在 Servlet 中的示例程式碼如下:

1 response.setDateHeader("Expires",-1);
2 response.setHeader("Cache-Control","no-cache");
3 response.setHeader("Pragma","no-cache"); 

  並不是所有的瀏覽器都能完全支援上面的三個響應頭,因此最好是同時使用上面的三個響應頭。

  • Expires資料頭:值為GMT時間值,為-1指瀏覽器不要快取頁面
  • Cache-Control響應頭有兩個常用值:
  • no-cache指瀏覽器不要快取當前頁面。
  • max-age:xxx指瀏覽器快取頁面xxx秒。
複製程式碼
 1 package me.gacl.web.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 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: NoCacheFilter
16 * @Description: 禁止瀏覽器快取所有動態頁面
17 * @author: 孤傲蒼狼
18 * @date: 2014-8-31 下午11:25:40
19 *
20 */ 
21 public class NoCacheFilter implements Filter {
22 
23 
24     public void doFilter(ServletRequest req, ServletResponse resp,
25             FilterChain chain) throws IOException, ServletException {
26         //把ServletRequest強轉成HttpServletRequest
27         HttpServletRequest request = (HttpServletRequest) req;
28         //把ServletResponse強轉成HttpServletResponse
29         HttpServletResponse response = (HttpServletResponse) resp;
30         //禁止瀏覽器快取所有動態頁面
31         response.setDateHeader("Expires", -1);
32         response.setHeader("Cache-Control", "no-cache");
33         response.setHeader("Pragma", "no-cache");
34         
35         chain.doFilter(request, response);
36     }
37 
38     public void init(FilterConfig filterConfig) throws ServletException {
39 
40     }
41     
42     public void destroy() {
43         
44     }
45 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1   <filter>
 2       <filter-name>NoCacheFilter</filter-name>
 3       <filter-class>me.gacl.web.filter.NoCacheFilter</filter-class>
 4   </filter>
 5   
 6   <filter-mapping>
 7       <filter-name>NoCacheFilter</filter-name>
 8         <!--只攔截Jsp請求-->
 9       <servlet-name>*.jsp</servlet-name>
10   </filter-mapping>
複製程式碼

三、控制瀏覽器快取頁面中的靜態資源

  有些動態頁面中引用了一些圖片或css檔案以修飾頁面效果,這些圖片和css檔案經常是不變化的,所以為減輕伺服器的壓力,可以使用filter控制瀏覽器快取這些檔案,以提升伺服器的效能。

複製程式碼
 1 package me.gacl.web.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 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: CacheFilter
16 * @Description: 控制快取的filter
17 * @author: 孤傲蒼狼
18 * @date: 2014-9-1 下午9:39:38
19 *
20 */ 
21 public class CacheFilter implements Filter {
22 
23     private FilterConfig filterConfig;
24 
25     public void doFilter(ServletRequest req, ServletResponse resp,
26             FilterChain chain) throws IOException, ServletException {
27     
28         HttpServletRequest request = (HttpServletRequest) req;
29         HttpServletResponse response = (HttpServletResponse) resp;
30         
31         //1.獲取使用者想訪問的資源
32         String uri = request.getRequestURI(); 
33         
34         //2.得到使用者想訪問的資源的字尾名
35         String ext = uri.substring(uri.lastIndexOf(".")+1);
36         
37         //得到資源需要快取的時間
38         String time = filterConfig.getInitParameter(ext);
39         if(time!=null){
40             long t = Long.parseLong(time)*3600*1000;
41             //設定快取
42             response.setDateHeader("expires", System.currentTimeMillis() + t);
43         }
44         
45         chain.doFilter(request, response);
46 
47     }
48 
49     public void init(FilterConfig filterConfig) throws ServletException {
50         this.filterConfig = filterConfig;
51     }
52     
53     public void destroy() {
54         
55     }
56 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1  <!-- 配置快取過濾器 -->
 2    <filter>
 3       <filter-name>CacheFilter</filter-name>
 4       <filter-class>me.gacl.web.filter.CacheFilter</filter-class>
 5        <!-- 配置要快取的web資源以及快取時間,以小時為單位 -->
 6       <init-param>
 7           <param-name>css</param-name>
 8           <param-value>4</param-value>
 9       </init-param>
10       <init-param>
11           <param-name>jpg</param-name>
12           <param-value>1</param-value>
13       </init-param>
14       <init-param>
15           <param-name>js</param-name>
16           <param-value>4</param-value>
17       </init-param>
18       <init-param>
19           <param-name>png</param-name>
20           <param-value>4</param-value>
21       </init-param>
22   </filter>
23   <!-- 配置要快取的web資源的字尾-->
24   <filter-mapping>
25       <filter-name>CacheFilter</filter-name>
26       <url-pattern>*.jpg</url-pattern>
27   </filter-mapping>
28   
29   <filter-mapping>
30       <filter-name>CacheFilter</filter-name>
31       <url-pattern>*.css</url-pattern>
32   </filter-mapping>
33   
34   <filter-mapping>
35       <filter-name>CacheFilter</filter-name>
36       <url-pattern>*.js</url-pattern>
37   </filter-mapping>
38    <filter-mapping>
39       <filter-name>CacheFilter</filter-name>
40       <url-pattern>*.png</url-pattern>
41   </filter-mapping>
複製程式碼

四、實現使用者自動登陸

  思路是這樣的:

  1、在使用者登陸成功後,傳送一個名稱為user的cookie給客戶端,cookie的值為使用者名稱和md5加密後的密碼。
  2、編寫一個AutoLoginFilter,這個filter檢查使用者是否帶有名稱為user的cookie來,如果有,則呼叫dao查詢cookie的使用者名稱和密碼是否和資料庫匹配,匹配則向session中存入user物件(即使用者登陸標記),以實現程式完成自動登陸。

  核心程式碼如下:

  處理使用者登入的控制器:LoginServlet

複製程式碼
 1 package me.gacl.web.controller;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.Cookie;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import me.gacl.dao.UserDao;
12 import me.gacl.domain.User;
13 import me.gacl.util.WebUtils;
14 
15 public class LoginServlet extends HttpServlet {
16 
17     public void doGet(HttpServletRequest request, HttpServletResponse response)
18             throws ServletException, IOException {
19 
20         String username = request.getParameter("username");
21         String password = request.getParameter("password");
22         
23         UserDao dao = new UserDao();
24         User user = dao.find(username, password);
25         if(user==null){
26             request.setAttribute("message", "使用者名稱或密碼不對!!");
27             request.getRequestDispatcher("/message.jsp").forward(request, response);
28             return;
29         }
30         request.getSession().setAttribute("user", user);
31         //傳送自動登陸cookie給客戶端瀏覽器進行儲存
32         sendAutoLoginCookie(request,response,user);
33         request.getRequestDispatcher("/index.jsp").forward(request, response);
34     }
35 
36     /**
37     * @Method: sendAutoLoginCookie
38     * @Description: 傳送自動登入cookie給客戶端瀏覽器
39     * @Anthor:孤傲蒼狼
40     *
41     * @param request
42     * @param response
43     * @param user
44     */ 
45     private void sendAutoLoginCookie(HttpServletRequest request, HttpServletResponse response, User user) {
46         if (request.getParameter("logintime")!=null) {
47             int logintime = Integer.parseInt(request.getParameter("logintime"));
48             //建立cookie,cookie的名字是autologin,值是使用者登入的使用者名稱和密碼,使用者名稱和密碼之間使用.進行分割,密碼經過md5加密處理
49             Cookie cookie = new Cookie("autologin",user.getUsername() + "." + WebUtils.md5(user.getPassword()));
50             //設定cookie的有效期
51             cookie.setMaxAge(logintime);
52             //設定cookie的有效路徑
53             cookie.setPath(request.getContextPath());
54             //將cookie寫入到客戶端瀏覽器
55             response.addCookie(cookie);
56         }
57     }
58     
59     public void doPost(HttpServletRequest request, HttpServletResponse response)
60             throws ServletException, IOException {
61 
62         doGet(request, response);
63     }
64 
65 }
複製程式碼

  處理使用者自動登入的過濾器:AutoLoginFilter

複製程式碼
 1 package me.gacl.web.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.Cookie;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 
15 import me.gacl.dao.UserDao;
16 import me.gacl.domain.User;
17 import me.gacl.util.WebUtils;
18 
19 public class AutoLoginFilter implements Filter {
20 
21     public void doFilter(ServletRequest req, ServletResponse resp,
22             FilterChain chain) throws IOException, ServletException {
23         
24         HttpServletRequest request = (HttpServletRequest) req;
25         HttpServletResponse response = (HttpServletResponse) resp;
26         //如果已經登入了,就直接chain.doFilter(request, response)放行
27         if(request.getSession().getAttribute("user")!=null){
28             chain.doFilter(request, response);
29             return;
30         }
31         
32         //1.得到使用者帶過來的authlogin的cookie
33         String value = null;
34         Cookie cookies[] = request.getCookies();
35         for(int i=0;cookies!=null && i<cookies.length;i++){
36             if(cookies[i].getName().equals("autologin")){
37                 value = cookies[i].getValue();
38             }
39         }
40         
41         //2.得到 cookie中的使用者名稱和密碼 
42         if(value!=null){
43             String username = value.split("\\.")[0];
44             String password = value.split("\\.")[1];
45             
46             //3.呼叫dao獲取使用者對應的密碼
47             UserDao dao = new UserDao();
48             User user = dao.find(username);
49             String dbpassword = user.getPassword();
50             
51             //4.檢查使用者帶過來的md5的密碼和資料庫中的密碼是否匹配,如匹配則自動登陸
52             if(password.equals(WebUtils.md5(dbpassword))){
53                 request.getSession().setAttribute("user", user);
54             }
55         }
56         
57         chain.doFilter(request, response);
58     }
59     
60     public void destroy() {
61         
62     }
63 
64     public void init(FilterConfig filterConfig) throws ServletException {
65 
66     }
67 }
複製程式碼

  如果想取消自動登入,那麼可以在使用者登出時刪除自動登入cookie,核心程式碼如下:

複製程式碼
 1 package me.gacl.web.controller;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.Cookie;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class CancelAutoLoginServlet extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         //移除儲存在session中的user
16         request.getSession().removeAttribute("user");
17         //移除自動登入的cookie
18         removeAutoLoginCookie(request,response);
19         //登出使用者後跳轉到登入頁面
20         request.getRequestDispatcher("/login.jsp").forward(request, response);
21     }
22 
23     /**
24     * @Method: removeAutoLoginCookie
25     * @Description: 刪除自動登入cookie,
26     *     JavaWeb中刪除cookie的方式就是新建立一個cookie,新建立的cookie與要刪除的cookie同名,
27     *     設定新建立的cookie的cookie的有效期設定為0,有效路徑與要刪除的cookie的有效路徑相同
28     * @Anthor:孤傲蒼狼
29     *
30     * @param request
31     * @param response
32     */ 
33     private void removeAutoLoginCookie(HttpServletRequest request, HttpServletResponse response) {
34         //建立一個名字為autologin的cookie
35         Cookie cookie = new Cookie("autologin","");
36          //將cookie的有效期設定為0,命令瀏覽器刪除該cookie
37         cookie.setMaxAge(0);
38         //設定要刪除的cookie的path
39         cookie.setPath(request.getContextPath());
40         response.addCookie(cookie);
41     }
42     
43     public void doPost(HttpServletRequest request, HttpServletResponse response)
44             throws ServletException, IOException {
45         doGet(request, response);
46     }
47 }
複製程式碼

  以上就是過濾器的幾個常見應用場景。

  通過配置引數charset指明使用何種字元編碼,以處理Html Form請求引數的中文問題

複製程式碼
 1 package me.gacl.web.filter;
 2 
 3 import java.io.IOException;
 4 import javax.servlet.Filter;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.FilterConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletRequest;
 9 import javax.servlet.ServletResponse;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletRequestWrapper;
12 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: CharacterEncodingFilter
16 * @Description: 此過濾器用來解決全站中文亂碼問題
17 * @author: 孤傲蒼狼
18 * @date: 2014-8-31 下午11:09:37
19 *
20 */ 
21 public class CharacterEncodingFilter implements Filter {
22 
23     private FilterConfig filterConfig = null;
24     //設定預設的字元編碼
25     private String defaultCharset = "UTF-8";
26 
27     public void doFilter(ServletRequest req, ServletResponse resp,
28             FilterChain chain) throws IOException, ServletException {
29         
30         HttpServletRequest request = (HttpServletRequest) req;
31         HttpServletResponse response = (HttpServletResponse) resp;
32         String charset = filterConfig.getInitParameter("charset");
33         if(charset==null){
34             charset = defaultCharset;
35         }
36         request.setCharacterEncoding(charset);
37         response.setCharacterEncoding(charset);
38         response.setContentType("text/html;charset="+charset);
39         
40         MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
41         chain.doFilter(requestWrapper, response);
42     }
43 
44     public void init(FilterConfig filterConfig) throws ServletException {
45         //得到過濾器的初始化配置資訊
46         this.filterConfig = filterConfig;
47     }
48     
49     public void destroy() {
50 
51     }
52 }
53 
54 /*
55 1.實現與被增強物件相同的介面 
56 2、定義一個變數記住被增強物件
57 3、定義一個構造器,接收被增強物件
58 4、覆蓋需要增強的方法
59 5、對於不想增強的方法,直接呼叫被增強物件(目標物件)的方法
60  */
61  
62 class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
63     
64     private HttpServletRequest request;
65     public MyCharacterEncodingRequest(HttpServletRequest request) {
66         super(request);
67         this.request = request;
68     }
69     /* 重寫getParameter方法
70      * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
71      */
72     @Override
73     public String getParameter(String name) {
74         
75         try{
76             //獲取引數的值
77             String value= this.request.getParameter(name);
78             if(value==null){
79                 return null;
80             }
81             //如果不是以get方式提交資料的,就直接返回獲取到的值
82             if(!this.request.getMethod().equalsIgnoreCase("get")) {
83                 return value;
84             }else{
85                 //如果是以get方式提交資料的,就對獲取到的值進行轉碼處理
86                 value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
87                 return value;
88             }
89         }catch (Exception e) {
90             throw new RuntimeException(e);
91         }
92     }
93 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1  <filter>
 2       <filter-name>CharacterEncodingFilter</filter-name>
 3       <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>
 4       <init-param>
 5           <param-name>charset</param-name>
 6           <param-value>UTF-8</param-value>
 7       </init-param>
 8   </filter>
 9   
10   <filter-mapping>
11       <filter-name>CharacterEncodingFilter</filter-name>
12       <url-pattern>/*</url-pattern>
13   </filter-mapping>
複製程式碼

二、禁止瀏覽器快取所有動態頁面

  有3 個HTTP 響應頭欄位都可以禁止瀏覽器快取當前頁面,它們在 Servlet 中的示例程式碼如下:

1 response.setDateHeader("Expires",-1);
2 response.setHeader("Cache-Control","no-cache");
3 response.setHeader("Pragma","no-cache"); 

  並不是所有的瀏覽器都能完全支援上面的三個響應頭,因此最好是同時使用上面的三個響應頭。

  • Expires資料頭:值為GMT時間值,為-1指瀏覽器不要快取頁面
  • Cache-Control響應頭有兩個常用值:
  • no-cache指瀏覽器不要快取當前頁面。
  • max-age:xxx指瀏覽器快取頁面xxx秒。
複製程式碼
 1 package me.gacl.web.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 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: NoCacheFilter
16 * @Description: 禁止瀏覽器快取所有動態頁面
17 * @author: 孤傲蒼狼
18 * @date: 2014-8-31 下午11:25:40
19 *
20 */ 
21 public class NoCacheFilter implements Filter {
22 
23 
24     public void doFilter(ServletRequest req, ServletResponse resp,
25             FilterChain chain) throws IOException, ServletException {
26         //把ServletRequest強轉成HttpServletRequest
27         HttpServletRequest request = (HttpServletRequest) req;
28         //把ServletResponse強轉成HttpServletResponse
29         HttpServletResponse response = (HttpServletResponse) resp;
30         //禁止瀏覽器快取所有動態頁面
31         response.setDateHeader("Expires", -1);
32         response.setHeader("Cache-Control", "no-cache");
33         response.setHeader("Pragma", "no-cache");
34         
35         chain.doFilter(request, response);
36     }
37 
38     public void init(FilterConfig filterConfig) throws ServletException {
39 
40     }
41     
42     public void destroy() {
43         
44     }
45 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1   <filter>
 2       <filter-name>NoCacheFilter</filter-name>
 3       <filter-class>me.gacl.web.filter.NoCacheFilter</filter-class>
 4   </filter>
 5   
 6   <filter-mapping>
 7       <filter-name>NoCacheFilter</filter-name>
 8         <!--只攔截Jsp請求-->
 9       <servlet-name>*.jsp</servlet-name>
10   </filter-mapping>
複製程式碼

三、控制瀏覽器快取頁面中的靜態資源

  有些動態頁面中引用了一些圖片或css檔案以修飾頁面效果,這些圖片和css檔案經常是不變化的,所以為減輕伺服器的壓力,可以使用filter控制瀏覽器快取這些檔案,以提升伺服器的效能。

複製程式碼
 1 package me.gacl.web.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 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15 * @ClassName: CacheFilter
16 * @Description: 控制快取的filter
17 * @author: 孤傲蒼狼
18 * @date: 2014-9-1 下午9:39:38
19 *
20 */ 
21 public class CacheFilter implements Filter {
22 
23     private FilterConfig filterConfig;
24 
25     public void doFilter(ServletRequest req, ServletResponse resp,
26             FilterChain chain) throws IOException, ServletException {
27     
28         HttpServletRequest request = (HttpServletRequest) req;
29         HttpServletResponse response = (HttpServletResponse) resp;
30         
31         //1.獲取使用者想訪問的資源
32         String uri = request.getRequestURI(); 
33         
34         //2.得到使用者想訪問的資源的字尾名
35         String ext = uri.substring(uri.lastIndexOf(".")+1);
36         
37         //得到資源需要快取的時間
38         String time = filterConfig.getInitParameter(ext);
39         if(time!=null){
40             long t = Long.parseLong(time)*3600*1000;
41             //設定快取
42             response.setDateHeader("expires", System.currentTimeMillis() + t);
43         }
44         
45         chain.doFilter(request, response);
46 
47     }
48 
49     public void init(FilterConfig filterConfig) throws ServletException {
50         this.filterConfig = filterConfig;
51     }
52     
53     public void destroy() {
54         
55     }
56 }
複製程式碼

  web.xml檔案中的配置如下:

複製程式碼
 1  <!-- 配置快取過濾器 -->
 2    <filter>
 3       <filter-name>CacheFilter</filter-name>
 4       <filter-class>me.gacl.web.filter.CacheFilter</filter-class>
 5        <!-- 配置要快取的web資源以及快取時間,以小時為單位 -->
 6       <init-param>
 7           <param-name>css</param-name>
 8           <param-value>4</param-value>
 9       </init-param>
10       <init-param>
11           <param-name>jpg</param-name>
12           <param-value>1</param-value>
13       </init-param>
14       <init-param>
15           <param-name>js</param-name>
16           <param-value>4</param-value>
17       </init-param>
18       <init-param>
19           <param-name>png</param-name>
20           <param-value>4</param-value>
21       </init-param>
22   </filter>
23   <!-- 配置要快取的web資源的字尾-->
24   <filter-mapping>
25       <filter-name>CacheFilter</filter-name>
26       <url-pattern>*.jpg</url-pattern>
27   </filter-mapping>
28   
29   <filter-mapping>
30       <filter-name>CacheFilter</filter-name>
31       <url-pattern>*.css</url-pattern>
32   </filter-mapping>
33   
34   <filter-mapping>
35       <filter-name>CacheFilter</filter-name>
36       <url-pattern>*.js</url-pattern>
37   </filter-mapping>
38    <filter-mapping>
39       <filter-name>CacheFilter</filter-name>
40       <url-pattern>*.png</url-pattern>
41   </filter-mapping>
複製程式碼

四、實現使用者自動登陸

  思路是這樣的:

  1、在使用者登陸成功後,傳送一個名稱為user的cookie給客戶端,cookie的值為使用者名稱和md5加密後的密碼。
  2、編寫一個AutoLoginFilter,這個filter檢查使用者是否帶有名稱為user的cookie來,如果有,則呼叫dao查詢cookie的使用者名稱和密碼是否和資料庫匹配,匹配則向session中存入user物件(即使用者登陸標記),以實現程式完成自動登陸。

  核心程式碼如下:

  處理使用者登入的控制器:LoginServlet

複製程式碼
 1 package me.gacl.web.controller;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.Cookie;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import me.gacl.dao.UserDao;
12 import me.gacl.domain.User;
13 import me.gacl.util.WebUtils;
14 
15 public class LoginServlet extends HttpServlet {
16 
17     public void doGet(HttpServletRequest request, HttpServletResponse response)
18             throws ServletException, IOException {
19 
20         String username = request.getParameter("username");
21         String password = request.getParameter("password");
22         
23         UserDao dao = new UserDao();
24         User user = dao.find(username, password);
25         if(user==null){
26             request.setAttribute("message", "使用者名稱或密碼不對!!");
27             request.getRequestDispatcher("/message.jsp").forward(request, response);
28             return;
29         }
30         request.getSession().setAttribute("user", user);
31         //傳送自動登陸cookie給客戶端瀏覽器進行儲存
32         sendAutoLoginCookie(request,response,user);
33         request.getRequestDispatcher("/index.jsp").forward(request, response);
34     }
35 
36     /**
37     * @Method: sendAutoLoginCookie
38     * @Description: 傳送自動登入cookie給客戶端瀏覽器
39     * @Anthor:孤傲蒼狼
40     *
41     * @param request
42     * @param response
43     * @param user
44     */ 
45     private void sendAutoLoginCookie(HttpServletRequest request, HttpServletResponse response, User user) {
46         if (request.getParameter("logintime")!=null) {
47             int logintime = Integer.parseInt(request.getParameter("logintime"));
48             //建立cookie,cookie的名字是autologin,值是使用者登入的使用者名稱和密碼,使用者名稱和密碼之間使用.進行分割,密碼經過md5加密處理
49             Cookie cookie = new Cookie("autologin",user.getUsername() + "." + WebUtils.md5(user.getPassword()));
50             //設定cookie的有效期
51             cookie.setMaxAge(logintime);
52             //設定cookie的有效路徑
53             cookie.setPath(request.getContextPath());
54             //將cookie寫入到客戶端瀏覽器
55             response.addCookie(cookie);
56         }
57     }
58     
59     public void doPost(HttpServletRequest request, HttpServletResponse response)
60             throws ServletException, IOException {
61 
62         doGet(request, response);
63     }
64 
65 }
複製程式碼

  處理使用者自動登入的過濾器:AutoLoginFilter

複製程式碼
 1 package me.gacl.web.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.Cookie;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 
15 import me.gacl.dao.UserDao;
16 import me.gacl.domain.User;
17 import me.gacl.util.WebUtils;
18 
19 public class AutoLoginFilter implements Filter {
20 
21     public void doFilter(ServletRequest req, ServletResponse resp,
22             FilterChain chain) throws IOException, ServletException {
23         
24         HttpServletRequest request = (HttpServletRequest) req;
25         HttpServletResponse response = (HttpServletResponse) resp;
26         //如果已經登入了,就直接chain.doFilter(request, response)放行
27         if(request.getSession().getAttribute("user")!=null){
28             chain.doFilter(request, response);
29             return;
30         }
31         
32         //1.得到使用者帶過來的authlogin的cookie
33         String value = null;
34         Cookie cookies[] = request.getCookies();
35         for(int i=0;cookies!=null && i<cookies.length;i++){
36             if(cookies[i].getName().equals("autologin")){
37                 value = cookies[i].getValue();
38             }
39         }
40         
41         //2.得到 cookie中的使用者名稱和密碼 
42         if(value!=null){
43             String username = value.split("\\.")[0];
44             String password = value.split("\\.")[1];
45             
46             //3.呼叫dao獲取使用者對應的密碼
47             UserDao dao = new UserDao();
48             User user = dao.find(username);
49             String dbpassword = user.getPassword();
50             
51             //4.檢查使用者帶過來的md5的密碼和資料庫中的密碼是否匹配,如匹配則自動登陸
52             if(password.equals(WebUtils.md5(dbpassword))){
53                 request.getSession().setAttribute("user", user);
54             }
55         }
56         
57         chain.doFilter(request, response);
58     }
59     
60     public void destroy() {
61         
62     }
63 
64     public void init(FilterConfig filterConfig) throws ServletException {
65 
66     }
67 }
複製程式碼

  如果想取消自動登入,那麼可以在使用者登出時刪除自動登入cookie,核心程式碼如下:

複製程式碼
 1 package me.gacl.web.controller;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.Cookie;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class CancelAutoLoginServlet extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         //移除儲存在session中的user
16         request.getSession().removeAttribute("user");
17         //移除自動登入的cookie
18         removeAutoLoginCookie(request,response);
19         //登出使用者後跳轉到登入頁面
20         request.getRequestDispatcher("/login.jsp").forward(request, response);
21     }
22 
23     /**
24     * @Method: removeAutoLoginCookie
25     * @Description: 刪除自動登入cookie,
26     *     JavaWeb中刪除cookie的方式就是新建立一個cookie,新建立的cookie與要刪除的cookie同名,
27     *     設定新建立的cookie的cookie的有效期設定為0,有效路徑與要刪除的cookie的有效路徑相同
28     * @Anthor:孤傲蒼狼
29     *
30     * @param request
31     * @param response
32     */ 
33     private void removeAutoLoginCookie(HttpServletRequest request, HttpServletResponse response) {
34         //建立一個名字為autologin的cookie
35         Cookie cookie = new Cookie("autologin","");
36          //將cookie的有效期設定為0,命令瀏覽器刪除該cookie
37         cookie.setMaxAge(0);
38         //設定要刪除的cookie的path
39         cookie.setPath(request.getContextPath());
40         response.addCookie(cookie);
41     }
42     
43     public void doPost(HttpServletRequest request, HttpServletResponse response)
44             throws ServletException, IOException {
45         doGet(request, response);
46     }
47 }
複製程式碼

  以上就是過濾器的幾個常見應用場景。