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.mzph.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;保我明…