过滤器Filter高级应用

在filter中可以得到代表用户请求和响应的request、response对象,因此在编程中可以使用Decorator(装饰器)模式对request、response对象进行包装,再把包装对象传给目标资源,从而实现一些特殊需求。

一、Decorator设计模式

1.1、Decorator设计模式介绍

  当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强:

  1. 编写子类,覆盖需增强的方法。
  2. 使用Decorator设计模式对方法进行增强。
  3. 使用代理

      在阎宏博士的《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,代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequestWrapper;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: CharacterEncodingFilter
*<span class="hljs-javadoctag"> @Description</span>: 此过滤器用来解决解决get、post请求方式下的中文乱码问题
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-8-31 下午11:09:37
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CharacterEncodingFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>

    <span class="hljs-keyword">private</span> FilterConfig filterConfig = <span class="hljs-keyword">null</span>;
    <span class="hljs-comment">//设置默认的字符编码</span>
    <span class="hljs-keyword">private</span> String defaultCharset = <span class="hljs-string">"UTF-8"</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        <span class="hljs-comment">//得到在web.xml中配置的字符编码</span>
        String charset = filterConfig.getInitParameter(<span class="hljs-string">"charset"</span>);
        <span class="hljs-keyword">if</span>(charset==<span class="hljs-keyword">null</span>){
            charset = defaultCharset;
        }
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);
        response.setContentType(<span class="hljs-string">"text/html;charset="</span>+charset);

        MyCharacterEncodingRequest requestWrapper = <span class="hljs-keyword">new</span> MyCharacterEncodingRequest(request);
        chain.doFilter(requestWrapper, response);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {
        <span class="hljs-comment">//得到过滤器的初始化配置信息</span>
        <span class="hljs-keyword">this</span>.filterConfig = filterConfig;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }
}

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: MyCharacterEncodingRequest
*<span class="hljs-javadoctag"> @Description</span>: Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,
* (HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request对象的对应方法)
* 以避免用户在对request对象进行增强时需要实现request接口中的所有方法。
* 所以当需要增强request对象时,只需要写一个类继承HttpServletRequestWrapper类,然后在重写需要增强的方法即可
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-2 下午10:42:57
*     1.实现与被增强对象相同的接口 
    2、定义一个变量记住被增强对象
    3、定义一个构造函数,接收被增强对象
    4、覆盖需要增强的方法
    5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法
*/</span> 
class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
    <span class="hljs-comment">//定义一个变量记住被增强对象(request对象是需要被增强的对象)</span>
    <span class="hljs-keyword">private</span> HttpServletRequest request;
    <span class="hljs-comment">//定义一个构造函数,接收被增强对象</span>
    <span class="hljs-keyword">public</span> <span class="hljs-title">MyCharacterEncodingRequest</span>(HttpServletRequest request) {
        <span class="hljs-keyword">super</span>(request);
        <span class="hljs-keyword">this</span>.request = request;
    }
    <span class="hljs-comment">/* 覆盖需要增强的getParameter方法
     * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
     */</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> String <span class="hljs-title">getParameter</span>(String name) {
        <span class="hljs-keyword">try</span>{
            <span class="hljs-comment">//获取参数的值</span>
            String value= <span class="hljs-keyword">this</span>.request.getParameter(name);
            <span class="hljs-keyword">if</span>(value==<span class="hljs-keyword">null</span>){
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
            }
            <span class="hljs-comment">//如果不是以get方式提交数据的,就直接返回获取到的值</span>
            <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.request.getMethod().equalsIgnoreCase(<span class="hljs-string">"get"</span>)) {
                <span class="hljs-keyword">return</span> value;
            }<span class="hljs-keyword">else</span>{
                <span class="hljs-comment">//如果是以get方式提交数据的,就对获取到的值进行转码处理</span>
                value = <span class="hljs-keyword">new</span> String(value.getBytes(<span class="hljs-string">"ISO8859-1"</span>),<span class="hljs-keyword">this</span>.request.getCharacterEncoding());
                <span class="hljs-keyword">return</span> value;
            }
        }<span class="hljs-keyword">catch</span> (Exception e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }
}</code>

  在web.xml文件中配置CharacterEncodingFilter

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--配置字符过滤器,解决get、post请求方式下的中文乱码问题--></span>
  <span class="hljs-tag"><<span class="hljs-title">filter</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>CharacterEncodingFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-class</span>></span>me.gacl.web.filter.CharacterEncodingFilter<span class="hljs-tag"></<span class="hljs-title">filter-class</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>CharacterEncodingFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/*<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span></code>

  编写jsp测试页面,如下:

<code class="hljs xml has-numbering"><span class="vbscript"><%@ page language=<span class="hljs-string">"java"</span> pageEncoding=<span class="hljs-string">"UTF-8"</span>%></span>
<span class="vbscript"><%--引入jstl标签库 --%></span>
<span class="vbscript"><%@taglib uri=<span class="hljs-string">"http://java.sun.com/jsp/jstl/core"</span> prefix=<span class="hljs-string">"c"</span>%></span>
<span class="hljs-doctype"><!DOCTYPE HTML></span>
<span class="hljs-tag"><<span class="hljs-title">html</span>></span>
  <span class="hljs-tag"><<span class="hljs-title">head</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">title</span>></span>使用字符过滤器解决解决get、post请求方式下的中文乱码问题<span class="hljs-tag"></<span class="hljs-title">title</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">head</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">body</span>></span>
       <span class="vbscript"><%--使用c:url标签构建url,构建好的url存储在servletDemo1变量中--%></span>
       <span class="hljs-tag"><<span class="hljs-title">c:url</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"/servlet/ServletDemo1"</span> <span class="hljs-attribute">scope</span>=<span class="hljs-value">"page"</span> <span class="hljs-attribute">var</span>=<span class="hljs-value">"servletDemo1"</span>></span>
           <span class="vbscript"><%--构建的url的附带的中文参数 ,参数名是:username,值是:孤傲苍狼--%></span>
           <span class="hljs-tag"><<span class="hljs-title">c:param</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"username"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"孤傲苍狼"</span>></span><span class="hljs-tag"></<span class="hljs-title">c:param</span>></span>
       <span class="hljs-tag"></<span class="hljs-title">c:url</span>></span>
      <span class="vbscript"><%--使用<span class="hljs-keyword">get</span>的方式访问 --%></span>
       <span class="hljs-tag"><<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"${servletDemo1}"</span>></span>超链接(get方式请求)<span class="hljs-tag"></<span class="hljs-title">a</span>></span>
       <span class="hljs-tag"><<span class="hljs-title">hr</span>/></span>
       <span class="vbscript"><%--使用post方式提交表单 --%></span>
       <span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">action</span>=<span class="hljs-value">"${pageContext.request.contextPath}/servlet/ServletDemo1"</span> <span class="hljs-attribute">method</span>=<span class="hljs-value">"post"</span>></span>
           用户名:<span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"username"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"孤傲苍狼"</span> /></span>
           <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"submit"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"post方式提交"</span>></span>
       <span class="hljs-tag"></<span class="hljs-title">form</span>></span>

  <span class="hljs-tag"></<span class="hljs-title">body</span>></span>
<span class="hljs-tag"></<span class="hljs-title">html</span>></span></code>

  编写处理用户请求的ServletDemo1

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.controller;

<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.io.PrintWriter;

<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServlet;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ServletDemo1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span>

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span>(HttpServletRequest request, HttpServletResponse response)
            <span class="hljs-keyword">throws</span> ServletException, IOException {
        <span class="hljs-comment">//接收参数</span>
        String username = request.getParameter(<span class="hljs-string">"username"</span>);
        <span class="hljs-comment">//获取请求方式</span>
        String method = request.getMethod();
        <span class="hljs-comment">//获取输出流</span>
        PrintWriter out = response.getWriter();
        out.write(<span class="hljs-string">"请求的方式:"</span>+method);
        out.write(<span class="hljs-string">"<br/>"</span>);
        out.write(<span class="hljs-string">"接收到的参数:"</span>+username);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span>(HttpServletRequest request, HttpServletResponse response)
            <span class="hljs-keyword">throws</span> ServletException, IOException {
        doGet(request, response);
    }

}</code>

  测试结果如下:

  这里写图片描述

  从运行结果中可以看到,无论是get请求方式还是post请求方式,中文乱码问题都可以完美解决了。

2.2、使用Decorator模式包装request对象实现html标签转义功能

  编写一个html转义过滤器,代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequestWrapper;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: HtmlFilter
*<span class="hljs-javadoctag"> @Description</span>: html转义过滤器
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-2 下午11:28:41
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HtmlFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        MyHtmlRequest myrequest = <span class="hljs-keyword">new</span> MyHtmlRequest(request);
        chain.doFilter(myrequest, response);

    }


    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }


    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {

    }
}

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: MyHtmlRequest
*<span class="hljs-javadoctag"> @Description</span>: 使用Decorator模式包装request对象,实现html标签转义功能
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-2 下午11:29:09
*
*/</span> 
class MyHtmlRequest extends HttpServletRequestWrapper {

    <span class="hljs-keyword">private</span> HttpServletRequest request;

    <span class="hljs-keyword">public</span> <span class="hljs-title">MyHtmlRequest</span>(HttpServletRequest request) {
        <span class="hljs-keyword">super</span>(request);
        <span class="hljs-keyword">this</span>.request = request;
    }

    <span class="hljs-comment">/* 覆盖需要增强的getParameter方法
     * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
     */</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> String <span class="hljs-title">getParameter</span>(String name) {
        String value = <span class="hljs-keyword">this</span>.request.getParameter(name);
        <span class="hljs-keyword">if</span> (value == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
        <span class="hljs-comment">//调用filter转义value中的html标签</span>
        <span class="hljs-keyword">return</span> filter(value);
    }

    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @Method</span>: filter
    *<span class="hljs-javadoctag"> @Description</span>: 过滤内容中的html标签
    *<span class="hljs-javadoctag"> @Anthor</span>:孤傲苍狼
    *<span class="hljs-javadoctag"> @param</span> message
    *<span class="hljs-javadoctag"> @return</span>
    */</span> 
    <span class="hljs-keyword">public</span> String <span class="hljs-title">filter</span>(String message) {
        <span class="hljs-keyword">if</span> (message == <span class="hljs-keyword">null</span>){
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
        <span class="hljs-keyword">char</span> content[] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">char</span>[message.length()];
        message.getChars(<span class="hljs-number">0</span>, message.length(), content, <span class="hljs-number">0</span>);
        StringBuffer result = <span class="hljs-keyword">new</span> StringBuffer(content.length + <span class="hljs-number">50</span>);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < content.length; i++) {
            <span class="hljs-keyword">switch</span> (content[i]) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'<'</span>:
                result.append(<span class="hljs-string">"&lt;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'>'</span>:
                result.append(<span class="hljs-string">"&gt;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'&'</span>:
                result.append(<span class="hljs-string">"&amp;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'"'</span>:
                result.append(<span class="hljs-string">"&quot;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                result.append(content[i]);
            }
        }
        <span class="hljs-keyword">return</span> result.toString();
    }
}</code>

  在web.xml文件中配置HtmlFilter

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--配置Html过滤器,转义内容中的html标签--></span>
  <span class="hljs-tag"><<span class="hljs-title">filter</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>HtmlFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-class</span>></span>me.gacl.web.filter.HtmlFilter<span class="hljs-tag"></<span class="hljs-title">filter-class</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>HtmlFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/*<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span></code>

  编写jsp测试页面,如下:

<code class="hljs xml has-numbering"><span class="vbscript"><%@ page language=<span class="hljs-string">"java"</span> import=<span class="hljs-string">"java.util.*"</span> pageEncoding=<span class="hljs-string">"UTF-8"</span>%></span>
<span class="hljs-doctype"><!DOCTYPE HTML></span>
<span class="hljs-tag"><<span class="hljs-title">html</span>></span>
  <span class="hljs-tag"><<span class="hljs-title">head</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">title</span>></span>html过滤器测试<span class="hljs-tag"></<span class="hljs-title">title</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">head</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">body</span>></span>
       <span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">action</span>=<span class="hljs-value">"${pageContext.request.contextPath}/servlet/ServletDemo2"</span> <span class="hljs-attribute">method</span>=<span class="hljs-value">"post"</span>></span>
           留言:
           <span class="hljs-tag"><<span class="hljs-title">textarea</span> <span class="hljs-attribute">rows</span>=<span class="hljs-value">"8"</span> <span class="hljs-attribute">cols</span>=<span class="hljs-value">"70"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"message"</span>></span>
           <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/javascript"</span>></span><span class="javascript">
           <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){
               alert(<span class="hljs-string">"死循环了,我会不停地弹出了"</span>);
           }
           </span><span class="hljs-tag"></<span class="hljs-title">script</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"http://www.cnblogs.com"</span>></span>访问博客园<span class="hljs-tag"></<span class="hljs-title">a</span>></span>
           <span class="hljs-tag"></<span class="hljs-title">textarea</span>></span>
           <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"submit"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"发表"</span>></span>
       <span class="hljs-tag"></<span class="hljs-title">form</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">body</span>></span>
<span class="hljs-tag"></<span class="hljs-title">html</span>></span></code>

  编写处理用户请求的ServletDemo2

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.controller;

<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServlet;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ServletDemo2</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span>

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span>(HttpServletRequest request, HttpServletResponse response)
            <span class="hljs-keyword">throws</span> ServletException, IOException {
        <span class="hljs-comment">//获取用户输入的内容</span>
        String message = request.getParameter(<span class="hljs-string">"message"</span>);
        response.getWriter().write(<span class="hljs-string">"您上次的留言是:<br/>"</span> + message);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span>(HttpServletRequest request, HttpServletResponse response)
            <span class="hljs-keyword">throws</span> ServletException, IOException {
        doGet(request, response);
    }
}</code>

测试结果如下:

  这里写图片描述

  从运行结果中可以看到,所有的html标签都被转义输出了。

2.3、使用Decorator模式包装request对象实现敏感字符过滤功能

  编写一个敏感字符过滤器,代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.BufferedReader;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.io.InputStream;
<span class="hljs-keyword">import</span> java.io.InputStreamReader;
<span class="hljs-keyword">import</span> java.io.UnsupportedEncodingException;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequestWrapper;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: DirtyFilter
*<span class="hljs-javadoctag"> @Description</span>: 敏感词过滤器
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-6 上午10:43:11
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DirtyFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>

    <span class="hljs-keyword">private</span> FilterConfig config = <span class="hljs-keyword">null</span>;

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {
        <span class="hljs-keyword">this</span>.config = filterConfig;
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        DirtyRequest dirtyrequest = <span class="hljs-keyword">new</span> DirtyRequest(request);

        chain.doFilter(dirtyrequest, response);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }

    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @Method</span>: getDirtyWords
    *<span class="hljs-javadoctag"> @Description</span>: 获取敏感字符
    *<span class="hljs-javadoctag"> @Anthor</span>:孤傲苍狼
    *
    *<span class="hljs-javadoctag"> @return</span>
    */</span> 
    <span class="hljs-keyword">private</span> List<String> <span class="hljs-title">getDirtyWords</span>(){
        List<String> dirtyWords = <span class="hljs-keyword">new</span> ArrayList<String>();
        String dirtyWordPath = config.getInitParameter(<span class="hljs-string">"dirtyWord"</span>);
        InputStream inputStream = config.getServletContext().getResourceAsStream(dirtyWordPath);
        InputStreamReader is = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">try</span> {
            is = <span class="hljs-keyword">new</span> InputStreamReader(inputStream,<span class="hljs-string">"UTF-8"</span>);
        } <span class="hljs-keyword">catch</span> (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }
        BufferedReader reader = <span class="hljs-keyword">new</span> BufferedReader(is);
        String line;
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">while</span> ((line = reader.readLine())!= <span class="hljs-keyword">null</span>) {<span class="hljs-comment">//如果 line为空说明读完了</span>
                dirtyWords.add(line);
            }
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        } 
        <span class="hljs-keyword">return</span> dirtyWords;
    }

    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @ClassName</span>: DirtyRequest
    *<span class="hljs-javadoctag"> @Description</span>: 使用Decorator模式包装request对象,实现敏感字符过滤功能
    *<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
    *<span class="hljs-javadoctag"> @date</span>: 2014-9-6 上午11:56:35
    *
    */</span> 
    class DirtyRequest extends HttpServletRequestWrapper{

        <span class="hljs-keyword">private</span> List<String> dirtyWords = getDirtyWords();
        <span class="hljs-keyword">private</span> HttpServletRequest request;
        <span class="hljs-keyword">public</span> <span class="hljs-title">DirtyRequest</span>(HttpServletRequest request) {
            <span class="hljs-keyword">super</span>(request);
            <span class="hljs-keyword">this</span>.request = request;
        }
        <span class="hljs-comment">/* 重写getParameter方法,实现对敏感字符的过滤
         * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
         */</span>
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> String <span class="hljs-title">getParameter</span>(String name) {

            String value = <span class="hljs-keyword">this</span>.request.getParameter(name);
            <span class="hljs-keyword">if</span>(value==<span class="hljs-keyword">null</span>){
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
            }

            <span class="hljs-keyword">for</span>(String dirtyWord : dirtyWords){
                <span class="hljs-keyword">if</span>(value.contains(dirtyWord)){
                    System.out.println(<span class="hljs-string">"内容中包含敏感词:"</span>+dirtyWord+<span class="hljs-string">",将会被替换成****"</span>);
                    <span class="hljs-comment">//替换敏感字符</span>
                    value = value.replace(dirtyWord, <span class="hljs-string">"****"</span>);
                }
            }
            <span class="hljs-keyword">return</span> value;
        }
    }
}</code>

  在web.xml文件中配置DirtyFilter

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--配置敏感字符过滤器--></span>
  <span class="hljs-tag"><<span class="hljs-title">filter</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>DirtyFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-class</span>></span>me.gacl.web.filter.DirtyFilter<span class="hljs-tag"></<span class="hljs-title">filter-class</span>></span>
      <span class="hljs-comment"><!-- 配置要过滤的敏感字符文件 --></span>
      <span class="hljs-tag"><<span class="hljs-title">init-param</span>></span>
         <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>dirtyWord<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span>    
         <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>/WEB-INF/DirtyWord.txt<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">init-param</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>DirtyFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/*<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span></code>

  当用户填写的内容包含一些敏感字符时,在DirtyFilter过滤器中就会将这些敏感字符替换掉。

  我们如果将上述的CharacterEncodingFilter、HtmlFilter、DirtyFilter这三个过滤器联合起来使用,那么就相当于是把request对象包装了3次,request对象的getParameter方法经过3次重写,使得getParameter方法的功能大大增强,可以同时解决中文乱码,html标签转义,敏感字符过滤这些需求。

  在实际开发中完全可以将上述的三个过滤器合并成一个,让合并后的过滤器具有解决中文乱码,html标签转义,敏感字符过滤这些功能,例如:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.BufferedReader;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.io.InputStream;
<span class="hljs-keyword">import</span> java.io.InputStreamReader;
<span class="hljs-keyword">import</span> java.io.UnsupportedEncodingException;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequestWrapper;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: AdvancedFilter
*<span class="hljs-javadoctag"> @Description</span>: 这个过滤器是用来解决中文乱码,转义内容中的html标签,过滤内容中的敏感字符的
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-6 下午6:17:37
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AdvancedFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>

    <span class="hljs-keyword">private</span> FilterConfig filterConfig = <span class="hljs-keyword">null</span>;
    <span class="hljs-comment">//设置默认的字符编码</span>
    <span class="hljs-keyword">private</span> String defaultCharset = <span class="hljs-string">"UTF-8"</span>;

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {
        <span class="hljs-comment">//得到过滤器的初始化配置信息</span>
        <span class="hljs-keyword">this</span>.filterConfig = filterConfig;
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        <span class="hljs-comment">//得到在web.xml中配置的字符编码</span>
        String charset = filterConfig.getInitParameter(<span class="hljs-string">"charset"</span>);
        <span class="hljs-keyword">if</span>(charset==<span class="hljs-keyword">null</span>){
            charset = defaultCharset;
        }
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);
        response.setContentType(<span class="hljs-string">"text/html;charset="</span>+charset);

        AdvancedRequest requestWrapper = <span class="hljs-keyword">new</span> AdvancedRequest(request);
        chain.doFilter(requestWrapper, response);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }

    class AdvancedRequest extends HttpServletRequestWrapper{

        <span class="hljs-keyword">private</span> List<String> dirtyWords = getDirtyWords();

        <span class="hljs-comment">//定义一个变量记住被增强对象(request对象是需要被增强的对象)</span>
        <span class="hljs-keyword">private</span> HttpServletRequest request;
        <span class="hljs-comment">//定义一个构造函数,接收被增强对象</span>
        <span class="hljs-keyword">public</span> <span class="hljs-title">AdvancedRequest</span>(HttpServletRequest request) {
            <span class="hljs-keyword">super</span>(request);
            <span class="hljs-keyword">this</span>.request = request;
        }
        <span class="hljs-comment">/* 覆盖需要增强的getParameter方法
         * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
         */</span>
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> String <span class="hljs-title">getParameter</span>(String name) {
            <span class="hljs-keyword">try</span>{
                <span class="hljs-comment">//获取参数的值</span>
                String value= <span class="hljs-keyword">this</span>.request.getParameter(name);
                <span class="hljs-keyword">if</span>(value==<span class="hljs-keyword">null</span>){
                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
                }
                <span class="hljs-comment">//如果不是以get方式提交数据的,就直接返回获取到的值</span>
                <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.request.getMethod().equalsIgnoreCase(<span class="hljs-string">"get"</span>)) {
                    <span class="hljs-comment">//调用filter转义value中的html标签</span>
                    value= filter(value);
                }<span class="hljs-keyword">else</span>{
                    <span class="hljs-comment">//如果是以get方式提交数据的,就对获取到的值进行转码处理</span>
                    value = <span class="hljs-keyword">new</span> String(value.getBytes(<span class="hljs-string">"ISO8859-1"</span>),<span class="hljs-keyword">this</span>.request.getCharacterEncoding());
                    <span class="hljs-comment">//调用filter转义value中的html标签</span>
                    value= filter(value);
                }

                <span class="hljs-keyword">for</span>(String dirtyWord : dirtyWords){
                    <span class="hljs-keyword">if</span>(value.contains(dirtyWord)){
                        System.out.println(<span class="hljs-string">"内容中包含敏感词:"</span>+dirtyWord+<span class="hljs-string">",将会被替换成****"</span>);
                        <span class="hljs-comment">//替换敏感字符</span>
                        value = value.replace(dirtyWord, <span class="hljs-string">"****"</span>);
                    }
                }
                <span class="hljs-keyword">return</span> value;
            }<span class="hljs-keyword">catch</span> (Exception e) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
            }
        }
    }

    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @Method</span>: filter
    *<span class="hljs-javadoctag"> @Description</span>: 过滤内容中的html标签
    *<span class="hljs-javadoctag"> @Anthor</span>:孤傲苍狼
    *<span class="hljs-javadoctag"> @param</span> value
    *<span class="hljs-javadoctag"> @return</span>
    */</span> 
    <span class="hljs-keyword">public</span> String <span class="hljs-title">filter</span>(String value) {
        <span class="hljs-keyword">if</span> (value == <span class="hljs-keyword">null</span>){
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
        <span class="hljs-keyword">char</span> content[] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">char</span>[value.length()];
        value.getChars(<span class="hljs-number">0</span>, value.length(), content, <span class="hljs-number">0</span>);
        StringBuffer result = <span class="hljs-keyword">new</span> StringBuffer(content.length + <span class="hljs-number">50</span>);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < content.length; i++) {
            <span class="hljs-keyword">switch</span> (content[i]) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'<'</span>:
                result.append(<span class="hljs-string">"&lt;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'>'</span>:
                result.append(<span class="hljs-string">"&gt;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'&'</span>:
                result.append(<span class="hljs-string">"&amp;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'"'</span>:
                result.append(<span class="hljs-string">"&quot;"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                result.append(content[i]);
            }
        }
        <span class="hljs-keyword">return</span> (result.toString());
    }

    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @Method</span>: getDirtyWords
    *<span class="hljs-javadoctag"> @Description</span>: 获取敏感字符
    *<span class="hljs-javadoctag"> @Anthor</span>:孤傲苍狼
    *
    *<span class="hljs-javadoctag"> @return</span>
    */</span> 
    <span class="hljs-keyword">private</span> List<String> <span class="hljs-title">getDirtyWords</span>(){
        List<String> dirtyWords = <span class="hljs-keyword">new</span> ArrayList<String>();
        String dirtyWordPath = filterConfig.getInitParameter(<span class="hljs-string">"dirtyWord"</span>);
        InputStream inputStream = filterConfig.getServletContext().getResourceAsStream(dirtyWordPath);
        InputStreamReader is = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">try</span> {
            is = <span class="hljs-keyword">new</span> InputStreamReader(inputStream,defaultCharset);
        } <span class="hljs-keyword">catch</span> (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }
        BufferedReader reader = <span class="hljs-keyword">new</span> BufferedReader(is);
        String line;
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">while</span> ((line = reader.readLine())!= <span class="hljs-keyword">null</span>) {<span class="hljs-comment">//如果 line为空说明读完了</span>
                dirtyWords.add(line);
            }
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        } 
        <span class="hljs-keyword">return</span> dirtyWords;
    }
}</code>

  在web.xml文件中配置AdvancedFilter

<code class="hljs livecodeserver has-numbering"><<span class="hljs-built_in">filter</span>>
      <<span class="hljs-built_in">filter</span>-name>AdvancedFilter</<span class="hljs-built_in">filter</span>-name>
      <<span class="hljs-built_in">filter</span>-class>me.gacl.web.<span class="hljs-built_in">filter</span>.AdvancedFilter</<span class="hljs-built_in">filter</span>-class>
      <init-<span class="hljs-built_in">param</span>>
         <<span class="hljs-built_in">param</span>-name>charset</<span class="hljs-built_in">param</span>-name>    
         <<span class="hljs-built_in">param</span>-<span class="hljs-built_in">value</span>>UTF-<span class="hljs-number">8</span></<span class="hljs-built_in">param</span>-<span class="hljs-built_in">value</span>>
    </init-<span class="hljs-built_in">param</span>>
      <init-<span class="hljs-built_in">param</span>>
         <<span class="hljs-built_in">param</span>-name>dirtyWord</<span class="hljs-built_in">param</span>-name>    
         <<span class="hljs-built_in">param</span>-<span class="hljs-built_in">value</span>>/WEB-INF/DirtyWord.txt</<span class="hljs-built_in">param</span>-<span class="hljs-built_in">value</span>>
    </init-<span class="hljs-built_in">param</span>>
  </<span class="hljs-built_in">filter</span>>

  <<span class="hljs-built_in">filter</span>-mapping>
      <<span class="hljs-built_in">filter</span>-name>AdvancedFilter</<span class="hljs-built_in">filter</span>-name>
      <url-pattern><span class="hljs-comment">/*</url-pattern>
  </filter-mapping></span></code>

  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对数据进行压缩后再写出给浏览器,以此完成响应正文件压缩功能。

  编写压缩过滤器,代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.ByteArrayOutputStream;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.io.OutputStreamWriter;
<span class="hljs-keyword">import</span> java.io.PrintWriter;
<span class="hljs-keyword">import</span> java.util.zip.GZIPOutputStream;

<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletOutputStream;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponseWrapper;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: GzipFilter
*<span class="hljs-javadoctag"> @Description</span>: 压缩过滤器,将web应用中的文本都经过压缩后再输出到浏览器
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-7 上午10:52:42
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GzipFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        BufferResponse myresponse = <span class="hljs-keyword">new</span> BufferResponse(response);
        chain.doFilter(request, myresponse);
        <span class="hljs-comment">//拿出缓存中的数据,压缩后再打给浏览器</span>
        <span class="hljs-keyword">byte</span> out[] = myresponse.getBuffer();
        System.out.println(<span class="hljs-string">"原始大小:"</span> + out.length);

        ByteArrayOutputStream bout = <span class="hljs-keyword">new</span> ByteArrayOutputStream();
        <span class="hljs-comment">//压缩输出流中的数据</span>
        GZIPOutputStream gout = <span class="hljs-keyword">new</span> GZIPOutputStream(bout);
        gout.write(out);
        gout.close();

        <span class="hljs-keyword">byte</span> gzip[] = bout.toByteArray();
        System.out.println(<span class="hljs-string">"压缩后的大小:"</span> + gzip.length);

        response.setHeader(<span class="hljs-string">"content-encoding"</span>, <span class="hljs-string">"gzip"</span>);
        response.setContentLength(gzip.length);
        response.getOutputStream().write(gzip);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {

    }
}

class BufferResponse extends HttpServletResponseWrapper{

    <span class="hljs-keyword">private</span> ByteArrayOutputStream bout = <span class="hljs-keyword">new</span> ByteArrayOutputStream();
    <span class="hljs-keyword">private</span> PrintWriter pw;
    <span class="hljs-keyword">private</span> HttpServletResponse response;
    <span class="hljs-keyword">public</span> <span class="hljs-title">BufferResponse</span>(HttpServletResponse response) {
        <span class="hljs-keyword">super</span>(response);
        <span class="hljs-keyword">this</span>.response = response;
    }
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> ServletOutputStream <span class="hljs-title">getOutputStream</span>() <span class="hljs-keyword">throws</span> IOException {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MyServletOutputStream(bout);
    }
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> PrintWriter <span class="hljs-title">getWriter</span>() <span class="hljs-keyword">throws</span> IOException {
        pw = <span class="hljs-keyword">new</span> PrintWriter(<span class="hljs-keyword">new</span> OutputStreamWriter(bout,<span class="hljs-keyword">this</span>.response.getCharacterEncoding()));
        <span class="hljs-keyword">return</span> pw;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">byte</span>[] <span class="hljs-title">getBuffer</span>(){
        <span class="hljs-keyword">try</span>{
            <span class="hljs-keyword">if</span>(pw!=<span class="hljs-keyword">null</span>){
                pw.close();
            }
            <span class="hljs-keyword">if</span>(bout!=<span class="hljs-keyword">null</span>){
                bout.flush();
                <span class="hljs-keyword">return</span> bout.toByteArray();
            }


            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }<span class="hljs-keyword">catch</span> (Exception e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }
}

class MyServletOutputStream extends ServletOutputStream{

    <span class="hljs-keyword">private</span> ByteArrayOutputStream bout;
    <span class="hljs-keyword">public</span> <span class="hljs-title">MyServletOutputStream</span>(ByteArrayOutputStream bout){
        <span class="hljs-keyword">this</span>.bout = bout;
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">write</span>(<span class="hljs-keyword">int</span> b) <span class="hljs-keyword">throws</span> IOException {
        <span class="hljs-keyword">this</span>.bout.write(b);
    }
}</code>

  在web.xml中配置压缩过滤器

<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">filter</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">description</span>></span>配置压缩过滤器<span class="hljs-tag"></<span class="hljs-title">description</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-class</span>></span>me.gacl.web.filter.GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-class</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter</span>></span>

  <span class="hljs-comment"><!--jsp文件的输出的内容都经过压缩过滤器压缩后才输出 --></span>
  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>*.jsp<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
      <span class="hljs-comment"><!-- 配置过滤器的拦截方式--></span>
      <span class="hljs-comment"><!-- 对于在Servlet中通过
          request.getRequestDispatcher("jsp页面路径").forward(request, response) 
      方式访问的Jsp页面的要进行拦截 --></span>
      <span class="hljs-tag"><<span class="hljs-title">dispatcher</span>></span>FORWARD<span class="hljs-tag"></<span class="hljs-title">dispatcher</span>></span>
      <span class="hljs-comment"><!--对于直接以URL方式访问的jsp页面进行拦截,过滤器的拦截方式默认就是 REQUEST--></span>
      <span class="hljs-tag"><<span class="hljs-title">dispatcher</span>></span>REQUEST<span class="hljs-tag"></<span class="hljs-title">dispatcher</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span>
  <span class="hljs-comment"><!--js文件的输出的内容都经过压缩过滤器压缩后才输出 --></span>
  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>*.js<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span>
  <span class="hljs-comment"><!--css文件的输出的内容都经过压缩过滤器压缩后才输出 --></span>
  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>*.css<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span>
  <span class="hljs-comment"><!--html文件的输出的内容都经过压缩过滤器压缩后才输出 --></span>
  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>GzipFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>*.html<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span></code>
3.2、response增强案例——缓存数据到内存

  对于页面中很少更新的数据,例如商品分类,为避免每次都要从数据库查询分类数据,因此可把分类数据缓存在内存或文件中,以此来减轻数据库压力,提高系统响应速度。

  编写缓存数据的过滤器,代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> me.gacl.web.filter;

<span class="hljs-keyword">import</span> java.io.ByteArrayOutputStream;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.io.OutputStreamWriter;
<span class="hljs-keyword">import</span> java.io.PrintWriter;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Map;

<span class="hljs-keyword">import</span> javax.servlet.Filter;
<span class="hljs-keyword">import</span> javax.servlet.FilterChain;
<span class="hljs-keyword">import</span> javax.servlet.FilterConfig;
<span class="hljs-keyword">import</span> javax.servlet.ServletException;
<span class="hljs-keyword">import</span> javax.servlet.ServletOutputStream;
<span class="hljs-keyword">import</span> javax.servlet.ServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.ServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;
<span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponseWrapper;

<span class="hljs-javadoc">/**
*<span class="hljs-javadoctag"> @ClassName</span>: WebResourceCachedFilter
*<span class="hljs-javadoctag"> @Description</span>: Web资源缓存过滤器
*<span class="hljs-javadoctag"> @author</span>: 孤傲苍狼
*<span class="hljs-javadoctag"> @date</span>: 2014-9-8 上午12:20:16
*
*/</span> 
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebResourceCachedFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> {</span>
    <span class="hljs-javadoc">/**
    *<span class="hljs-javadoctag"> @Field</span>: map
    *          缓存Web资源的Map容器
    */</span> 
    <span class="hljs-keyword">private</span> Map<String,<span class="hljs-keyword">byte</span>[]> map = <span class="hljs-keyword">new</span> HashMap<String,<span class="hljs-keyword">byte</span>[]>();

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span>(FilterConfig filterConfig) <span class="hljs-keyword">throws</span> ServletException {

    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doFilter</span>(ServletRequest req, ServletResponse resp,
            FilterChain chain) <span class="hljs-keyword">throws</span> IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        <span class="hljs-comment">//1.得到用户请求的uri</span>
        String uri = request.getRequestURI();
        <span class="hljs-comment">//2.看缓存中有没有uri对应的数据</span>
        <span class="hljs-keyword">byte</span> b[] = map.get(uri);
        <span class="hljs-comment">//3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回</span>
        <span class="hljs-keyword">if</span>(b!=<span class="hljs-keyword">null</span>){
            <span class="hljs-comment">//根据字节数组和指定的字符编码构建字符串</span>
            String webResourceHtmlStr = <span class="hljs-keyword">new</span> String(b,response.getCharacterEncoding());
            System.out.println(webResourceHtmlStr);
            response.getOutputStream().write(b);
            <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-comment">//4.如果缓存没有,让目标资源执行,并捕获目标资源的输出</span>
        BufferResponse myresponse = <span class="hljs-keyword">new</span> BufferResponse(response);
        chain.doFilter(request, myresponse);
        <span class="hljs-comment">//获取缓冲流中的内容的字节数组</span>
        <span class="hljs-keyword">byte</span> out[] = myresponse.getBuffer();
        <span class="hljs-comment">//5.把资源的数据以用户请求的uri为关键字保存到缓存中</span>
        map.put(uri, out);
        <span class="hljs-comment">//6.把数据打给浏览器</span>
        response.getOutputStream().write(out);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">destroy</span>() {

    }

    class BufferResponse extends HttpServletResponseWrapper{
        <span class="hljs-keyword">private</span> ByteArrayOutputStream bout = <span class="hljs-keyword">new</span> ByteArrayOutputStream();  <span class="hljs-comment">//捕获输出的缓存</span>
        <span class="hljs-keyword">private</span> PrintWriter pw;
        <span class="hljs-keyword">private</span> HttpServletResponse response;
        <span class="hljs-keyword">public</span> <span class="hljs-title">BufferResponse</span>(HttpServletResponse response) {
            <span class="hljs-keyword">super</span>(response);
            <span class="hljs-keyword">this</span>.response = response;
        }
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> ServletOutputStream <span class="hljs-title">getOutputStream</span>() <span class="hljs-keyword">throws</span> IOException {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MyServletOutputStream(bout);
        }
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> PrintWriter <span class="hljs-title">getWriter</span>() <span class="hljs-keyword">throws</span> IOException {
            pw = <span class="hljs-keyword">new</span> PrintWriter(<span class="hljs-keyword">new</span> OutputStreamWriter(bout,<span class="hljs-keyword">this</span>.response.getCharacterEncoding()));
            <span class="hljs-keyword">return</span> pw;
        }

        <span class="hljs-keyword">public</span> <span class="hljs-keyword">byte</span>[] <span class="hljs-title">getBuffer</span>(){
            <span class="hljs-keyword">try</span>{
                <span class="hljs-keyword">if</span>(pw!=<span class="hljs-keyword">null</span>){
                    pw.close();
                }
                <span class="hljs-keyword">return</span> bout.toByteArray();
            }<span class="hljs-keyword">catch</span> (Exception e) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
            }
        }
    }

    class MyServletOutputStream extends ServletOutputStream{
        <span class="hljs-keyword">private</span> ByteArrayOutputStream bout;
        <span class="hljs-keyword">public</span> <span class="hljs-title">MyServletOutputStream</span>(ByteArrayOutputStream bout){  <span class="hljs-comment">//接收数据写到哪里</span>
            <span class="hljs-keyword">this</span>.bout = bout;
        }
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">write</span>(<span class="hljs-keyword">int</span> b) <span class="hljs-keyword">throws</span> IOException {
            bout.write(b);
        }
    }
}</code>

  在web.xml中配置Web资源缓存过滤器

<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">filter</span>></span>
       <span class="hljs-tag"><<span class="hljs-title">description</span>></span>Web资源缓存过滤器<span class="hljs-tag"></<span class="hljs-title">description</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>WebResourceCachedFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-class</span>></span>me.gacl.web.filter.WebResourceCachedFilter<span class="hljs-tag"></<span class="hljs-title">filter-class</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">filter-mapping</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">filter-name</span>></span>WebResourceCachedFilter<span class="hljs-tag"></<span class="hljs-title">filter-name</span>></span>
      <span class="hljs-comment"><!-- 映射需要缓存输出的JSP页面,这几个页面都只是单纯作为输入UI,不会有太多的变化,因此可以缓存输出 --></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/login.jsp<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/test.jsp<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
      <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/test2.jsp<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">filter-mapping</span>></span></code>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值