javaweb學習總結——Filter高級開發

在filter中可以得到代表用戶請求和響應的request、response對象,因此在編程中可以使用Decorator(裝飾器)模式對request、response對象進行包裝,再把包裝對象傳給目標資源,從而實現一些特殊需求。

一、Decorator設計模式

1.1、Decorator設計模式介紹

  當某個對象的方法不適應業務需求時,通常有2種方式可以對方法進行增強:

  1. 編寫子類,覆蓋需增強的方法。
  2. 使用Decorator設計模式對方法進行增強。

  在閻宏博士的《JAVA與模式》一書中開頭是這樣描述裝飾(Decorator)模式的:裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案。裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。

  那么在實際應用中遇到需增強對象的方法時,到底選用哪種方式比較好呢?這個沒有具體的定式,只能是根據具體的需求來采用具體的方式,不過有一種情況下,必須使用Decorator設計模式:即被增強的對象,開發人員只能得到它的對象,無法得到它的class文件。比如request、response對象,開發人員之所以在servlet中能通過sun公司定義的HttpServletRequest\response接口去操作這些對象,是因為Tomcat服務器廠商編寫了request、response接口的實現類。web服務器在調用servlet時,會用這些接口的實現類創建出對象,然后傳遞給servlet程序。此種情況下,由于開發人員根本不知道服務器廠商編寫的request、response接口的實現類是哪個?在程序中只能拿到服務器廠商提供的對象,因此就只能采用Decorator設計模式對這些對象進行增強。

1.2、Decorator設計模式的實現

  1.首先看需要被增強對象繼承了什么接口或父類,編寫一個類也去繼承這些接口或父類。
2.在類中定義一個變量,變量類型即需增強對象的類型。
3.在類中定義一個構造函數,接收需增強的對象。
4.覆蓋需增強的方法,編寫增強的代碼。

?二、使用Decorator設計模式增強request對象

  Servlet API 中提供了一個request對象的Decorator設計模式的默認實現類HttpServletRequestWrapper,HttpServletRequestWrapper 類實現了request 接口中的所有方法,但這些方法的內部實現都是僅僅調用了一下所包裝的的 request 對象的對應方法,以避免用戶在對request對象進行增強時需要實現request接口中的所有方法。

2.1、使用Decorator模式包裝request對象解決get和post請求方式下的中文亂碼問題

  編寫一個用于處理中文亂碼的過濾器CharacterEncodingFilter,代碼如下:

復制代碼
復制代碼
  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.HttpServletRequestWrapper;13 import javax.servlet.http.HttpServletResponse;14 15 /**16 * @ClassName: CharacterEncodingFilter17 * @Description: 此過濾器用來解決解決get、post請求方式下的中文亂碼問題18 * @author: 孤傲蒼狼19 * @date: 2014-8-31 下午11:09:3720 *21 */ 22 public class CharacterEncodingFilter implements Filter {23 24     private FilterConfig filterConfig = null;25     //設置默認的字符編碼26     private String defaultCharset = "UTF-8";27 28     public void doFilter(ServletRequest req, ServletResponse resp,29             FilterChain chain) throws IOException, ServletException {30         31         HttpServletRequest request = (HttpServletRequest) req;32         HttpServletResponse response = (HttpServletResponse) resp;33         //得到在web.xml中配置的字符編碼34         String charset = filterConfig.getInitParameter("charset");35         if(charset==null){36             charset = defaultCharset;37         }38         request.setCharacterEncoding(charset);39         response.setCharacterEncoding(charset);40         response.setContentType("text/html;charset="+charset);41         42         MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);43         chain.doFilter(requestWrapper, response);44     }45 46     public void init(FilterConfig filterConfig) throws ServletException {47         //得到過濾器的初始化配置信息48         this.filterConfig = filterConfig;49     }50     51     public void destroy() {52 53     }54 }55 56 /**57 * @ClassName: MyCharacterEncodingRequest58 * @Description: Servlet API中提供了一個request對象的Decorator設計模式的默認實現類HttpServletRequestWrapper,59 * (HttpServletRequestWrapper類實現了request接口中的所有方法,但這些方法的內部實現都是僅僅調用了一下所包裝的的 request對象的對應方法)60 * 以避免用戶在對request對象進行增強時需要實現request接口中的所有方法。61 * 所以當需要增強request對象時,只需要寫一個類繼承HttpServletRequestWrapper類,然后在重寫需要增強的方法即可62 * @author: 孤傲蒼狼63 * @date: 2014-9-2 下午10:42:5764 *     1.實現與被增強對象相同的接口 65     2、定義一個變量記住被增強對象66     3、定義一個構造函數,接收被增強對象67     4、覆蓋需要增強的方法68     5、對于不想增強的方法,直接調用被增強對象(目標對象)的方法69 */ 70 class MyCharacterEncodingRequest extends HttpServletRequestWrapper{71     //定義一個變量記住被增強對象(request對象是需要被增強的對象)72     private HttpServletRequest request;73     //定義一個構造函數,接收被增強對象74     public MyCharacterEncodingRequest(HttpServletRequest request) {75         super(request);76         this.request = request;77     }78     /* 覆蓋需要增強的getParameter方法79      * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)80      */81     @Override82     public String getParameter(String name) {83         try{84             //獲取參數的值85             String value= this.request.getParameter(name);86             if(value==null){87                 return null;88             }89             //如果不是以get方式提交數據的,就直接返回獲取到的值90             if(!this.request.getMethod().equalsIgnoreCase("get")) {91                 return value;92             }else{93                 //如果是以get方式提交數據的,就對獲取到的值進行轉碼處理94                 value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());95                 return value;96             }97         }catch (Exception e) {98             throw new RuntimeException(e);99         }
100     }
101 }
復制代碼
復制代碼

  在web.xml文件中配置CharacterEncodingFilter

復制代碼
復制代碼
 1 <!--配置字符過濾器,解決get、post請求方式下的中文亂碼問題-->2   <filter>3       <filter-name>CharacterEncodingFilter</filter-name>4       <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>5   </filter>6   7   <filter-mapping>8       <filter-name>CharacterEncodingFilter</filter-name>9       <url-pattern>/*</url-pattern>
10   </filter-mapping>
復制代碼
復制代碼

  編寫jsp測試頁面,如下:

復制代碼
復制代碼
 1 <%@ page language="java" pageEncoding="UTF-8"%>2 <%--引入jstl標簽庫 --%>3 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>4 <!DOCTYPE HTML>5 <html>6   <head>7     <title>使用字符過濾器解決解決get、post請求方式下的中文亂碼問題</title>8   </head>9   
10   <body>
11        <%--使用c:url標簽構建url,構建好的url存儲在servletDemo1變量中--%>
12        <c:url value="/servlet/ServletDemo1" scope="page" var="servletDemo1">
13            <%--構建的url的附帶的中文參數 ,參數名是:username,值是:孤傲蒼狼--%>
14            <c:param name="username" value="孤傲蒼狼"></c:param>
15        </c:url>
16       <%--使用get的方式訪問 --%>
17        <a href="${servletDemo1}">超鏈接(get方式請求)</a>
18        <hr/>
19        <%--使用post方式提交表單 --%>
20        <form action="${pageContext.request.contextPath}/servlet/ServletDemo1" method="post">
21            用戶名:<input type="text" name="username" value="孤傲蒼狼" />
22            <input type="submit" value="post方式提交">
23        </form>
24        
25   </body>
26 </html>
復制代碼
復制代碼

  編寫處理用戶請求的ServletDemo1

復制代碼
復制代碼
 1 package me.gacl.web.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 ServletDemo1 extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         //接收參數
16         String username = request.getParameter("username");
17         //獲取請求方式
18         String method = request.getMethod();
19         //獲取輸出流
20         PrintWriter out = response.getWriter();
21         out.write("請求的方式:"+method);
22         out.write("<br/>");
23         out.write("接收到的參數:"+username);
24     }
25 
26     public void doPost(HttpServletRequest request, HttpServletResponse response)
27             throws ServletException, IOException {
28         doGet(request, response);
29     }
30 
31 }
復制代碼
復制代碼

  測試結果如下:

  

  從運行結果中可以看到,無論是get請求方式還是post請求方式,中文亂碼問題都可以完美解決了。

2.2、使用Decorator模式包裝request對象實現html標簽轉義功能

  編寫一個html轉義過濾器,代碼如下:

復制代碼
復制代碼
  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.HttpServletRequestWrapper;13 import javax.servlet.http.HttpServletResponse;14 15 /**16 * @ClassName: HtmlFilter17 * @Description: html轉義過濾器18 * @author: 孤傲蒼狼19 * @date: 2014-9-2 下午11:28:4120 *21 */ 22 public class HtmlFilter implements Filter {23 24     public void doFilter(ServletRequest req, ServletResponse resp,25             FilterChain chain) throws IOException, ServletException {26         27         HttpServletRequest request = (HttpServletRequest) req;28         HttpServletResponse response = (HttpServletResponse) resp;29 30         MyHtmlRequest myrequest = new MyHtmlRequest(request);31         chain.doFilter(myrequest, response);32         33     }34 35     36     public void destroy() {37         38     }39 40     41     public void init(FilterConfig filterConfig) throws ServletException {42         43     }44 }45 46 /**47 * @ClassName: MyHtmlRequest48 * @Description: 使用Decorator模式包裝request對象,實現html標簽轉義功能49 * @author: 孤傲蒼狼50 * @date: 2014-9-2 下午11:29:0951 *52 */ 53 class MyHtmlRequest extends HttpServletRequestWrapper {54 55     private HttpServletRequest request;56 57     public MyHtmlRequest(HttpServletRequest request) {58         super(request);59         this.request = request;60     }61 62     /* 覆蓋需要增強的getParameter方法63      * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)64      */65     @Override66     public String getParameter(String name) {67         String value = this.request.getParameter(name);68         if (value == null) {69             return null;70         }71         //調用filter轉義value中的html標簽72         return filter(value);73     }74 75     /**76     * @Method: filter77     * @Description: 過濾內容中的html標簽78     * @Anthor:孤傲蒼狼79     * @param message80     * @return81     */ 82     public String filter(String message) {83         if (message == null){84             return null;85         }86         char content[] = new char[message.length()];87         message.getChars(0, message.length(), content, 0);88         StringBuffer result = new StringBuffer(content.length + 50);89         for (int i = 0; i < content.length; i++) {90             switch (content[i]) {91             case '<':92                 result.append("&lt;");93                 break;94             case '>':95                 result.append("&gt;");96                 break;97             case '&':98                 result.append("&amp;");99                 break;
100             case '"':
101                 result.append("&quot;");
102                 break;
103             default:
104                 result.append(content[i]);
105             }
106         }
107         return result.toString();
108     }
109 }
復制代碼
復制代碼

  在web.xml文件中配置HtmlFilter

復制代碼
復制代碼
 1 <!--配置Html過濾器,轉義內容中的html標簽-->2   <filter>3       <filter-name>HtmlFilter</filter-name>4       <filter-class>me.gacl.web.filter.HtmlFilter</filter-class>5   </filter>6   7   <filter-mapping>8       <filter-name>HtmlFilter</filter-name>9       <url-pattern>/*</url-pattern>
10   </filter-mapping>
復制代碼
復制代碼

  編寫jsp測試頁面,如下:

復制代碼
復制代碼
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <!DOCTYPE HTML>3 <html>4   <head>5     <title>html過濾器測試</title>6   </head>7   8   <body>9        <form action="${pageContext.request.contextPath}/servlet/ServletDemo2" method="post">
10            留言:
11            <textarea rows="8" cols="70" name="message">
12            <script type="text/javascript">
13            while(true){
14                alert("死循環了,我會不停地彈出了");
15            }
16            </script>
17         <a href="http://www.cnblogs.com">訪問博客園</a>
18            </textarea>
19            <input type="submit" value="發表">
20        </form>
21   </body>
22 </html>
復制代碼
復制代碼

  編寫處理用戶請求的ServletDemo2

復制代碼
復制代碼
 1 package me.gacl.web.controller;2 3 import java.io.IOException;4 5 import javax.servlet.ServletException;6 import javax.servlet.http.HttpServlet;7 import javax.servlet.http.HttpServletRequest;8 import javax.servlet.http.HttpServletResponse;9 
10 public class ServletDemo2 extends HttpServlet {
11 
12     public void doGet(HttpServletRequest request, HttpServletResponse response)
13             throws ServletException, IOException {
14         //獲取用戶輸入的內容
15         String message = request.getParameter("message");
16         response.getWriter().write("您上次的留言是:<br/>" + message);
17     }
18 
19     public void doPost(HttpServletRequest request, HttpServletResponse response)
20             throws ServletException, IOException {
21         doGet(request, response);
22     }
23 }
復制代碼
復制代碼

測試結果如下:

  

  從運行結果中可以看到,所有的html標簽都被轉義輸出了。

2.3、使用Decorator模式包裝request對象實現敏感字符過濾功能

  編寫一個敏感字符過濾器,代碼如下:

復制代碼
復制代碼
  1 package me.gacl.web.filter;2 3 import java.io.BufferedReader;4 import java.io.IOException;5 import java.io.InputStream;6 import java.io.InputStreamReader;7 import java.io.UnsupportedEncodingException;8 import java.util.ArrayList;9 import java.util.List;10 import javax.servlet.Filter;11 import javax.servlet.FilterChain;12 import javax.servlet.FilterConfig;13 import javax.servlet.ServletException;14 import javax.servlet.ServletRequest;15 import javax.servlet.ServletResponse;16 import javax.servlet.http.HttpServletRequest;17 import javax.servlet.http.HttpServletRequestWrapper;18 import javax.servlet.http.HttpServletResponse;19 20 /**21 * @ClassName: DirtyFilter22 * @Description: 敏感詞過濾器23 * @author: 孤傲蒼狼24 * @date: 2014-9-6 上午10:43:1125 *26 */ 27 public class DirtyFilter implements Filter {28 29     private FilterConfig config = null;30     31     @Override32     public void init(FilterConfig filterConfig) throws ServletException {33         this.config = filterConfig;34     }35 36     @Override37     public void doFilter(ServletRequest req, ServletResponse resp,38             FilterChain chain) throws IOException, ServletException {39         40         HttpServletRequest request = (HttpServletRequest) req;41         HttpServletResponse response = (HttpServletResponse) resp;42         DirtyRequest dirtyrequest = new DirtyRequest(request);43         44         chain.doFilter(dirtyrequest, response);45     }46 47     @Override48     public void destroy() {49 50     }51     52     /**53     * @Method: getDirtyWords54     * @Description: 獲取敏感字符55     * @Anthor:孤傲蒼狼56     *57     * @return58     */ 59     private List<String> getDirtyWords(){60         List<String> dirtyWords = new ArrayList<String>();61         String dirtyWordPath = config.getInitParameter("dirtyWord");62         InputStream inputStream = config.getServletContext().getResourceAsStream(dirtyWordPath);63         InputStreamReader is = null;64         try {65             is = new InputStreamReader(inputStream,"UTF-8");66         } catch (UnsupportedEncodingException e2) {67             e2.printStackTrace();68         }69         BufferedReader reader = new BufferedReader(is);70         String line;71         try {72             while ((line = reader.readLine())!= null) {//如果 line為空說明讀完了73                 dirtyWords.add(line);74             }75         } catch (IOException e) {76             e.printStackTrace();77         } 78         return dirtyWords;79     }80     81     /**82     * @ClassName: DirtyRequest83     * @Description: 使用Decorator模式包裝request對象,實現敏感字符過濾功能84     * @author: 孤傲蒼狼85     * @date: 2014-9-6 上午11:56:3586     *87     */ 88     class DirtyRequest extends HttpServletRequestWrapper{89 90         private List<String> dirtyWords = getDirtyWords();91         private HttpServletRequest request;92         public DirtyRequest(HttpServletRequest request) {93             super(request);94             this.request = request;95         }96         /* 重寫getParameter方法,實現對敏感字符的過濾97          * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)98          */99         @Override
100         public String getParameter(String name) {
101             
102             String value = this.request.getParameter(name);
103             if(value==null){
104                 return null;
105             }
106             
107             for(String dirtyWord : dirtyWords){
108                 if(value.contains(dirtyWord)){
109                     System.out.println("內容中包含敏感詞:"+dirtyWord+",將會被替換成****");
110                     //替換敏感字符
111                     value = value.replace(dirtyWord, "****");
112                 }
113             }
114             return value;
115         }
116     }
117 }
復制代碼
復制代碼

  在web.xml文件中配置DirtyFilter

復制代碼
復制代碼
 1  <!--配置敏感字符過濾器-->2   <filter>3       <filter-name>DirtyFilter</filter-name>4       <filter-class>me.gacl.web.filter.DirtyFilter</filter-class>5       <!-- 配置要過濾的敏感字符文件 -->6       <init-param>7          <param-name>dirtyWord</param-name>    8          <param-value>/WEB-INF/DirtyWord.txt</param-value>9     </init-param>
10   </filter>
11   
12   <filter-mapping>
13       <filter-name>DirtyFilter</filter-name>
14       <url-pattern>/*</url-pattern>
15   </filter-mapping>
復制代碼
復制代碼

  當用戶填寫的內容包含一些敏感字符時,在DirtyFilter過濾器中就會將這些敏感字符替換掉。

  我們如果將上述的CharacterEncodingFilter、HtmlFilter、DirtyFilter這三個過濾器聯合起來使用,那么就相當于是把request對象包裝了3次,request對象的getParameter方法經過3次重寫,使得getParameter方法的功能大大增強,可以同時解決中文亂碼,html標簽轉義,敏感字符過濾這些需求。

  在實際開發中完全可以將上述的三個過濾器合并成一個,讓合并后的過濾器具有解決中文亂碼,html標簽轉義,敏感字符過濾這些功能,例如:

復制代碼
復制代碼
  1 package me.gacl.web.filter;2 3 import java.io.BufferedReader;4 import java.io.IOException;5 import java.io.InputStream;6 import java.io.InputStreamReader;7 import java.io.UnsupportedEncodingException;8 import java.util.ArrayList;9 import java.util.List;10 11 import javax.servlet.Filter;12 import javax.servlet.FilterChain;13 import javax.servlet.FilterConfig;14 import javax.servlet.ServletException;15 import javax.servlet.ServletRequest;16 import javax.servlet.ServletResponse;17 import javax.servlet.http.HttpServletRequest;18 import javax.servlet.http.HttpServletRequestWrapper;19 import javax.servlet.http.HttpServletResponse;20 21 /**22 * @ClassName: AdvancedFilter23 * @Description: 這個過濾器是用來解決中文亂碼,轉義內容中的html標簽,過濾內容中的敏感字符的24 * @author: 孤傲蒼狼25 * @date: 2014-9-6 下午6:17:3726 *27 */ 28 public class AdvancedFilter implements Filter {29 30     private FilterConfig filterConfig = null;31     //設置默認的字符編碼32     private String defaultCharset = "UTF-8";33     34     @Override35     public void init(FilterConfig filterConfig) throws ServletException {36         //得到過濾器的初始化配置信息37         this.filterConfig = filterConfig;38     }39 40     @Override41     public void doFilter(ServletRequest req, ServletResponse resp,42             FilterChain chain) throws IOException, ServletException {43         HttpServletRequest request = (HttpServletRequest) req;44         HttpServletResponse response = (HttpServletResponse) resp;45         //得到在web.xml中配置的字符編碼46         String charset = filterConfig.getInitParameter("charset");47         if(charset==null){48             charset = defaultCharset;49         }50         request.setCharacterEncoding(charset);51         response.setCharacterEncoding(charset);52         response.setContentType("text/html;charset="+charset);53         54         AdvancedRequest requestWrapper = new AdvancedRequest(request);55         chain.doFilter(requestWrapper, response);56     }57 58     @Override59     public void destroy() {60 61     }62 63     class AdvancedRequest extends HttpServletRequestWrapper{64         65         private List<String> dirtyWords = getDirtyWords();66         67         //定義一個變量記住被增強對象(request對象是需要被增強的對象)68         private HttpServletRequest request;69         //定義一個構造函數,接收被增強對象70         public AdvancedRequest(HttpServletRequest request) {71             super(request);72             this.request = request;73         }74         /* 覆蓋需要增強的getParameter方法75          * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)76          */77         @Override78         public String getParameter(String name) {79             try{80                 //獲取參數的值81                 String value= this.request.getParameter(name);82                 if(value==null){83                     return null;84                 }85                 //如果不是以get方式提交數據的,就直接返回獲取到的值86                 if(!this.request.getMethod().equalsIgnoreCase("get")) {87                     //調用filter轉義value中的html標簽88                     value= filter(value);89                 }else{90                     //如果是以get方式提交數據的,就對獲取到的值進行轉碼處理91                     value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());92                     //調用filter轉義value中的html標簽93                     value= filter(value);94                 }95                 96                 for(String dirtyWord : dirtyWords){97                     if(value.contains(dirtyWord)){98                         System.out.println("內容中包含敏感詞:"+dirtyWord+",將會被替換成****");99                         //替換敏感字符
100                         value = value.replace(dirtyWord, "****");
101                     }
102                 }
103                 return value;
104             }catch (Exception e) {
105                 throw new RuntimeException(e);
106             }
107         }
108     }
109 
110     /**
111     * @Method: filter
112     * @Description: 過濾內容中的html標簽
113     * @Anthor:孤傲蒼狼
114     * @param value
115     * @return
116     */ 
117     public String filter(String value) {
118         if (value == null){
119             return null;
120         }
121         char content[] = new char[value.length()];
122         value.getChars(0, value.length(), content, 0);
123         StringBuffer result = new StringBuffer(content.length + 50);
124         for (int i = 0; i < content.length; i++) {
125             switch (content[i]) {
126             case '<':
127                 result.append("&lt;");
128                 break;
129             case '>':
130                 result.append("&gt;");
131                 break;
132             case '&':
133                 result.append("&amp;");
134                 break;
135             case '"':
136                 result.append("&quot;");
137                 break;
138             default:
139                 result.append(content[i]);
140             }
141         }
142         return (result.toString());
143     }
144     
145     /**
146     * @Method: getDirtyWords
147     * @Description: 獲取敏感字符
148     * @Anthor:孤傲蒼狼
149     *
150     * @return
151     */ 
152     private List<String> getDirtyWords(){
153         List<String> dirtyWords = new ArrayList<String>();
154         String dirtyWordPath = filterConfig.getInitParameter("dirtyWord");
155         InputStream inputStream = filterConfig.getServletContext().getResourceAsStream(dirtyWordPath);
156         InputStreamReader is = null;
157         try {
158             is = new InputStreamReader(inputStream,defaultCharset);
159         } catch (UnsupportedEncodingException e2) {
160             e2.printStackTrace();
161         }
162         BufferedReader reader = new BufferedReader(is);
163         String line;
164         try {
165             while ((line = reader.readLine())!= null) {//如果 line為空說明讀完了
166                 dirtyWords.add(line);
167             }
168         } catch (IOException e) {
169             e.printStackTrace();
170         } 
171         return dirtyWords;
172     }
173 }
復制代碼
復制代碼

  在web.xml文件中配置AdvancedFilter

復制代碼
復制代碼
 1   <filter>2       <filter-name>AdvancedFilter</filter-name>3       <filter-class>me.gacl.web.filter.AdvancedFilter</filter-class>4       <init-param>5          <param-name>charset</param-name>    6          <param-value>UTF-8</param-value>7     </init-param>8       <init-param>9          <param-name>dirtyWord</param-name>    
10          <param-value>/WEB-INF/DirtyWord.txt</param-value>
11     </init-param>
12   </filter>
13   
14   <filter-mapping>
15       <filter-name>AdvancedFilter</filter-name>
16       <url-pattern>/*</url-pattern>
17   </filter-mapping>
復制代碼
復制代碼

  AdvancedFilter過濾器同時具有解決中文亂碼,轉義內容中的html標簽,過濾內容中的敏感字符這些功能。

三、使用Decorator設計模式增強response對象

  Servlet? API 中提供了response對象的Decorator設計模式的默認實現類HttpServletResponseWrapper ,HttpServletResponseWrapper類實現了response接口中的所有方法,但這些方法的內部實現都是僅僅調用了一下所包裝的的 response對象的對應方法,以避免用戶在對response對象進行增強時需要實現response接口中的所有方法。

3.1、response增強案例——壓縮響應正文內容

  應用HttpServletResponseWrapper對象,壓縮響應正文內容。

  具體思路:通過filter向目標頁面傳遞一個自定義的response對象。在自定義的response對象中,重寫getOutputStream方法和getWriter方法,使目標資源調用此方法輸出頁面內容時,獲得的是我們自定義的ServletOutputStream對象。在我們自定義的ServletOuputStream對象中,重寫write方法,使寫出的數據寫出到一個buffer中。當頁面完成輸出后,在filter中就可得到頁面寫出的數據,從而我們可以調用GzipOuputStream對數據進行壓縮后再寫出給瀏覽器,以此完成響應正文件壓縮功能。

  編寫壓縮過濾器,代碼如下:

復制代碼
復制代碼
  1 package me.gacl.web.filter;2 3 import java.io.ByteArrayOutputStream;4 import java.io.IOException;5 import java.io.OutputStreamWriter;6 import java.io.PrintWriter;7 import java.util.zip.GZIPOutputStream;8 9 import javax.servlet.Filter;10 import javax.servlet.FilterChain;11 import javax.servlet.FilterConfig;12 import javax.servlet.ServletException;13 import javax.servlet.ServletOutputStream;14 import javax.servlet.ServletRequest;15 import javax.servlet.ServletResponse;16 import javax.servlet.http.HttpServletRequest;17 import javax.servlet.http.HttpServletResponse;18 import javax.servlet.http.HttpServletResponseWrapper;19 20 /**21 * @ClassName: GzipFilter22 * @Description: 壓縮過濾器,將web應用中的文本都經過壓縮后再輸出到瀏覽器23 * @author: 孤傲蒼狼24 * @date: 2014-9-7 上午10:52:4225 *26 */ 27 public class GzipFilter implements Filter {28 29     public void doFilter(ServletRequest req, ServletResponse resp,30             FilterChain chain) throws IOException, ServletException {31         32         HttpServletRequest request = (HttpServletRequest) req;33         HttpServletResponse response = (HttpServletResponse) resp;34         35         BufferResponse myresponse = new BufferResponse(response);36         chain.doFilter(request, myresponse);37         //拿出緩存中的數據,壓縮后再打給瀏覽器38         byte out[] = myresponse.getBuffer();39         System.out.println("原始大小:" + out.length);40         41         ByteArrayOutputStream bout = new ByteArrayOutputStream();42         //壓縮輸出流中的數據43         GZIPOutputStream gout = new GZIPOutputStream(bout);44         gout.write(out);45         gout.close();46         47         byte gzip[] = bout.toByteArray();48         System.out.println("壓縮后的大小:" + gzip.length);49         50         response.setHeader("content-encoding", "gzip");51         response.setContentLength(gzip.length);52         response.getOutputStream().write(gzip);53     }54     55     public void destroy() {56         57     }58 59     public void init(FilterConfig filterConfig) throws ServletException {60         61     }62 }63 64 class BufferResponse extends HttpServletResponseWrapper{65 66     private ByteArrayOutputStream bout = new ByteArrayOutputStream();67     private PrintWriter pw;68     private HttpServletResponse response;69     public BufferResponse(HttpServletResponse response) {70         super(response);71         this.response = response;72     }73     @Override74     public ServletOutputStream getOutputStream() throws IOException {75         return new MyServletOutputStream(bout);76     }77     @Override78     public PrintWriter getWriter() throws IOException {79         pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));80         return pw;81     }82     83     public byte[] getBuffer(){84         try{85             if(pw!=null){86                 pw.close();87             }88             if(bout!=null){89                 bout.flush();90                 return bout.toByteArray();91             }92             93             94             return null;95         }catch (Exception e) {96             throw new RuntimeException(e);97         }98     }99 }
100 
101 class MyServletOutputStream extends ServletOutputStream{
102 
103     private ByteArrayOutputStream bout;
104     public MyServletOutputStream(ByteArrayOutputStream bout){
105         this.bout = bout;
106     }
107     
108     @Override
109     public void write(int b) throws IOException {
110         this.bout.write(b);
111     }
112 }
復制代碼
復制代碼

  在web.xml中配置壓縮過濾器

復制代碼
復制代碼
 1  <filter>2       <description>配置壓縮過濾器</description>3       <filter-name>GzipFilter</filter-name>4       <filter-class>me.gacl.web.filter.GzipFilter</filter-class>5   </filter>6   7   <!--jsp文件的輸出的內容都經過壓縮過濾器壓縮后才輸出 -->8   <filter-mapping>9       <filter-name>GzipFilter</filter-name>
10       <url-pattern>*.jsp</url-pattern>
11       <!-- 配置過濾器的攔截方式-->
12       <!-- 對于在Servlet中通過
13           request.getRequestDispatcher("jsp頁面路徑").forward(request, response) 
14       方式訪問的Jsp頁面的要進行攔截 -->
15       <dispatcher>FORWARD</dispatcher>
16       <!--對于直接以URL方式訪問的jsp頁面進行攔截,過濾器的攔截方式默認就是 REQUEST-->
17       <dispatcher>REQUEST</dispatcher>
18   </filter-mapping>
19   <!--js文件的輸出的內容都經過壓縮過濾器壓縮后才輸出 -->
20   <filter-mapping>
21       <filter-name>GzipFilter</filter-name>
22       <url-pattern>*.js</url-pattern>
23   </filter-mapping>
24   <!--css文件的輸出的內容都經過壓縮過濾器壓縮后才輸出 -->
25   <filter-mapping>
26       <filter-name>GzipFilter</filter-name>
27       <url-pattern>*.css</url-pattern>
28   </filter-mapping>
29   <!--html文件的輸出的內容都經過壓縮過濾器壓縮后才輸出 -->
30   <filter-mapping>
31       <filter-name>GzipFilter</filter-name>
32       <url-pattern>*.html</url-pattern>
33   </filter-mapping>
復制代碼
復制代碼

?3.2、response增強案例——緩存數據到內存

  對于頁面中很少更新的數據,例如商品分類,為避免每次都要從數據庫查詢分類數據,因此可把分類數據緩存在內存或文件中,以此來減輕數據庫壓力,提高系統響應速度。

  編寫緩存數據的過濾器,代碼如下:

復制代碼
復制代碼
  1 package me.gacl.web.filter;2 3 import java.io.ByteArrayOutputStream;4 import java.io.IOException;5 import java.io.OutputStreamWriter;6 import java.io.PrintWriter;7 import java.util.HashMap;8 import java.util.Map;9 10 import javax.servlet.Filter;11 import javax.servlet.FilterChain;12 import javax.servlet.FilterConfig;13 import javax.servlet.ServletException;14 import javax.servlet.ServletOutputStream;15 import javax.servlet.ServletRequest;16 import javax.servlet.ServletResponse;17 import javax.servlet.http.HttpServletRequest;18 import javax.servlet.http.HttpServletResponse;19 import javax.servlet.http.HttpServletResponseWrapper;20 21 /**22 * @ClassName: WebResourceCachedFilter23 * @Description: Web資源緩存過濾器24 * @author: 孤傲蒼狼25 * @date: 2014-9-8 上午12:20:1626 *27 */ 28 public class WebResourceCachedFilter implements Filter {29     /**30     * @Field: map31     *          緩存Web資源的Map容器32     */ 33     private Map<String,byte[]> map = new HashMap<String,byte[]>();34     35     @Override36     public void init(FilterConfig filterConfig) throws ServletException {37 38     }39 40     @Override41     public void doFilter(ServletRequest req, ServletResponse resp,42             FilterChain chain) throws IOException, ServletException {43         HttpServletRequest request = (HttpServletRequest) req;44         HttpServletResponse response = (HttpServletResponse) resp;45         //1.得到用戶請求的uri46         String uri = request.getRequestURI();47         //2.看緩存中有沒有uri對應的數據48         byte b[] = map.get(uri);49         //3.如果緩存中有,直接拿緩存的數據打給瀏覽器,程序返回50         if(b!=null){51             //根據字節數組和指定的字符編碼構建字符串52             String webResourceHtmlStr = new String(b,response.getCharacterEncoding());53             System.out.println(webResourceHtmlStr);54             response.getOutputStream().write(b);55             return;56         }57         //4.如果緩存沒有,讓目標資源執行,并捕獲目標資源的輸出58         BufferResponse myresponse = new BufferResponse(response);59         chain.doFilter(request, myresponse);60         //獲取緩沖流中的內容的字節數組61         byte out[] = myresponse.getBuffer();62         //5.把資源的數據以用戶請求的uri為關鍵字保存到緩存中63         map.put(uri, out);64         //6.把數據打給瀏覽器65         response.getOutputStream().write(out);66     }67 68     @Override69     public void destroy() {70 71     }72 73     class BufferResponse extends HttpServletResponseWrapper{74         private ByteArrayOutputStream bout = new ByteArrayOutputStream();  //捕獲輸出的緩存75         private PrintWriter pw;76         private HttpServletResponse response;77         public BufferResponse(HttpServletResponse response) {78             super(response);79             this.response = response;80         }81         @Override82         public ServletOutputStream getOutputStream() throws IOException {83             return new MyServletOutputStream(bout);84         }85         @Override86         public PrintWriter getWriter() throws IOException {87             pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));88             return pw;89         }90         91         public byte[] getBuffer(){92             try{93                 if(pw!=null){94                     pw.close();95                 }96                 return bout.toByteArray();97             }catch (Exception e) {98                 throw new RuntimeException(e);99             }
100         }
101     }
102 
103     class MyServletOutputStream extends ServletOutputStream{
104         private ByteArrayOutputStream bout;
105         public MyServletOutputStream(ByteArrayOutputStream bout){  //接收數據寫到哪里
106             this.bout = bout;
107         }
108         @Override
109         public void write(int b) throws IOException {
110             bout.write(b);
111         }
112     }
113 }
復制代碼
復制代碼

  在web.xml中配置Web資源緩存過濾器

復制代碼
復制代碼
 1   <filter>2        <description>Web資源緩存過濾器</description>3       <filter-name>WebResourceCachedFilter</filter-name>4       <filter-class>me.gacl.web.filter.WebResourceCachedFilter</filter-class>5   </filter>6   7   <filter-mapping>8       <filter-name>WebResourceCachedFilter</filter-name>9       <!-- 映射需要緩存輸出的JSP頁面,這幾個頁面都只是單純作為輸入UI,不會有太多的變化,因此可以緩存輸出 -->
10       <url-pattern>/login.jsp</url-pattern>
11       <url-pattern>/test.jsp</url-pattern>
12       <url-pattern>/test2.jsp</url-pattern>
13   </filter-mapping>
復制代碼

本文轉自左正博客園博客,原文鏈接:http://www.cnblogs.com/soundcode/p/6290378.html,如需轉載請自行聯系原作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/257287.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/257287.shtml
英文地址,請注明出處:http://en.pswp.cn/news/257287.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

html期末網頁設計,求網頁設計的期末作業一份 HTML的

1&#xff0e; 課程設計建議主題方向&#xff1a;電子商務類網站、門戶類網站、專題類網站。整體要求&#xff1a;主題鮮明、健康&#xff1b;風格自然、內容充實、完整&#xff1b;布局合理&#xff0c;配色和諧。(5分)2&#xff0e; 網站至少包括15張頁面(包括首頁)&#x…

Android(java)學習筆記10:同步中的死鎖問題以及線程通信問題

1. 同步弊端&#xff1a; &#xff08;1&#xff09;效率低 &#xff08;2&#xff09;如果出現了同步嵌套&#xff0c;就容易產生死鎖問題 死鎖問題及其代碼 &#xff1a; &#xff08;1&#xff09;是指兩個或者兩個以上的線程在執行的過程中&#xff0c;因爭奪資源產生的一種…

4源代碼的下載和編譯

1、Android移植主要就是Linux內核移植&#xff0c;而Linux內核移植主要是Linux驅動移植&#xff0c;為了開發和測試Linux驅動&#xff0c;要在Ubuntu下搭建兩套開發環境&#xff1a;Android應用程序開發環境和Linux內核開發環境&#xff1b; 2、Android源代碼包括&#xff1a;內…

在html中三個圖片切換,輕松搞定網頁中的圖片切換

生活中經常看到&#xff0c;像新浪等很多門戶網站的首頁都有滾動圖片的展示&#xff0c;如下圖所示&#xff1a;某網站首頁滾動切換圖片這樣不但可以減少文字的單一、乏味&#xff0c;而且可以直觀內容&#xff0c;更好的吸引用戶。那在我們做軟件系統時&#xff0c;是否也可以…

python 進程編程速成

python具有thread多線程庫&#xff0c;但多線程并不是真正的多線程&#xff0c;不能充分利用多核CPU資源。 在大多數情況下&#xff0c;python可以使用multiprocessing多進程庫&#xff0c;可以輕松完成從單進程到并發執行的轉換。 multiprocessing庫支持子進程、通信和共享數據…

requirejs(shim)處理加載非AMD規范的js庫

使用requirejs加載模塊&#xff0c;模塊的定義得遵守AMD規范&#xff0c;也即定義模塊的時候使用如下函數定義模塊: 1 define(function(){ 2 var private function(){ 3 console.log(私有方法...); 4 }; 5 return { 6 public:funct…

關于常用meta的總結

入行也半年了&#xff0c;無數次的想過寫博客也無數次的想過第一篇會寫什么&#xff0c;一直沒有落實。今天心血來潮把博客開了&#xff0c;那就寫點東西吧。第一篇就寫一寫看似簡單但又經常不注意到的meta標簽吧。&#xff08;博主經驗尚淺&#xff0c;有許多理解不到位的地方…

計算機應用基礎18春在線作業1答案,東師計算機應用基礎-18春在線作業1.docx

東師計算機應用基礎18春在線作業11、A 2、C 3、C 4、C 5、B一、單選題共25題&#xff0c;62.5分1、國際區位、全拼雙音、五筆字型和自然碼是不同種類的漢字A外碼B內碼C字型碼D交換碼正確答案是&#xff1a;A2、漢字字形碼的使用是在____A輸入時B內部傳送時C輸出時D兩臺計算機之…

jQuery Validate 驗證,校驗規則寫在控件中的具體例子

將校驗規則寫到控件中 <script src"../js/jquery.js" type"text/javascript"></script> <script src"../js/jquery.validate.js" type"text/javascript"></script> <script src"./js/jquery.metadata…

在oracle中使用Trigger

1、初始目標 在對表h1插入一條數據時&#xff0c;同時插入一條重復的數據&#xff08;只有主鍵不同&#xff09; 2、在PL/SQL里New一個Trigger或者手動敲入代碼 先說明一下&#xff0c;表h1包括4列ID、C1、C2、C3 create or replace trigger Trigger_Testafter insert on h1for…

html突出顯示,javascript-記住html頁面中突出顯示的文本(向html頁面添加注釋)

我有一個HTML文件,我正在用webkit打開它,我想開發一個應用程序,這樣,在打開它之后,我應該能夠選擇一些文本并將其突出顯示(例如,按下“ highlight text”按鈕).并且它應該記住突出顯示的文本,以便下次打開時應自動突出顯示相同的文本…要存儲哪些信息,以便下次可以突出顯示相同…

cygwin

根據cygwin user guide翻譯整理&#xff0c;希望對大家有所幫助。有錯誤清指出。 1 引言 cygwin是一個在windows平臺上運行的unix模擬環境&#xff0c;是cygnus solutions公司開發的自由軟件&#xff08;該公司開發了很多好東西&#xff0c;著名的還有eCos&#xff0c;不…

JAVA wait(), notify(),sleep具體解釋

在CSDN開了博客后&#xff0c;一直也沒在上面公布過文章&#xff0c;直到前一段時間與一位前輩的對話&#xff0c;才發現技術博客的重要&#xff0c;立志要把CSDN的博客建好。但一直沒有找到好的開篇的主題&#xff0c;今天再看JAVA線程相互排斥、同步的時候又有了新的體會&…

通過鍵盤上下鍵 JS事件,控制候選詞的選擇項

效果圖 JS代碼 //上下鍵 選擇事件 searchBackgroud 為樣式&#xff0c;只做標記&#xff0c;無實質樣式&#xff0c;因為和其他樣式不兼容&#xff0c;只能添加CSS$(document).keydown(function (event) {var upDownClickNum $("#SearchTips .searchBackgroud ").l…

物理競賽得獎學計算機,物理競賽林紫琪帶你探索清華學堂計算機科學實驗班”(姚班)...

林紫琪&#xff0c;34屆全國中學生物理競賽全國第22名&#xff0c;獲得女生最高分&#xff0c;入選國家集訓隊&#xff0c;現就讀于清華姚班。這是一條小科普&#xff1a;“清華學堂計算機科學實驗班”(姚班)由世界著名計算機科學家姚期智院士于2005年創辦&#xff0c;致力于培…

Jmeter===Jmeter中使用CSV Data Set Config參數化不重復數據執行N遍(轉)

Jmeter中使用CSV Data Set Config參數化不重復數據執行N遍 要求&#xff1a; 今天要測試上千條數據&#xff0c;且每條數據要求執行多次&#xff0c;&#xff08;模擬多用戶多次抽獎&#xff09; 1.用戶id有175個&#xff0c;且沒有任何排序規則&#xff1b; 2.要求175個用戶都…

[轉]wireshark 實用過濾表達式(針對ip、協議、端口、長度和內容) 實例介紹

首先說幾個最常用的關鍵字&#xff0c;“eq” 和 “”等同&#xff0c;可以使用 “and” 表示并且&#xff0c;“or”表示或者。“!" 和 "not” 都表示取反。 一、針對wireshark最常用的自然是針對IP地址的過濾。其中有幾種情況&#xff1a; &#xff08;1&#xff0…

[Flexbox] Using order to rearrange flexbox children

Using the order property we alter the order in which flexbox children appear on the page, without making changes to the dom. Desktop Mobile 轉載于:https://www.cnblogs.com/Answer1215/p/5453671.html

計算機怎么更改用戶頭像像,Win10系統電腦賬戶頭像怎么改成系統默認狀態?

為了保護電腦的安全&#xff0c;我們可以設置登錄賬號密碼&#xff0c;而賬號的頭像也是可以自行更換的。但是&#xff0c;某些時候&#xff0c;因為一些原因&#xff0c;我們需要將Win10系統賬戶的頭像去掉&#xff0c;即改成默認狀態。但是很多人都不清楚該怎么操作&#xff…

SPFA模板

今天去聽2015ZJOI浙江省隊第二試的集訓&#xff0c;早上就是聽得云里霧里的ORZ&#xff0c;下午某兩集訓隊大神過來將題目&#xff0c;第一個進了IOI的我只聽懂了10%ORZ&#xff0c;第二個人機交互很好玩&#xff0c;找個時間單獨寫下。 順便附帶膜拜各位聚聚&#xff0c;保我明…