zoukankan      html  css  js  c++  java
  • 过滤器修改response

      过滤器通过doFilter方法的第二个参数ServletResponse将输出发送给客户,但servletResponse参数没有为过滤器提供servlet或jsp页面的访问;执行doFilter方法时,servlet或jsp还没修改,当调用FilterChain的doFilter方法时,修改相应似乎为时已晚,以为数据已经发送给客户端,怎么办呢?

      解决这个问题的办法是创建一个像HttpServletResponse的缓冲区,当servlet或jsp调用response.getWiter或者response.getOutputStream并发送输出时,输出实际上没有被发送到客户端,而是放到了该缓冲区中,这样filter就可以在发送到客户端前检查货修改这个输出。大概过程如下

    具体代码如下:

    1、实现HttpServletResponseWrapper

    public class StringWrapper extends HttpServletResponseWrapper {
      private StringWriter stringWriter;//缓存区
    
      public StringWrapper(HttpServletResponse response) {
        super(response);
        stringWriter = new StringWriter();
      }
      /** 当servlet或jsp请求Writer时,给它们一个被封装过的writer,
       *  其会往缓冲区中写数据
       */
      public PrintWriter getWriter() {
        return(new PrintWriter(stringWriter));
      }
      /** 同样,当 调用 getOutputStream,
        * 返回一个模拟的output stream
        */
      public ServletOutputStream getOutputStream() {
        return(new StringOutputStream(stringWriter));
      }
      /** 返回buffer的字符串表示
       */
      public String toString() {
        return(stringWriter.toString());
      }

    2、实现ServletOutputStreanm

    public class StringOutputStream extends ServletOutputStream {
      private StringWriter stringWriter;//缓冲区引用
      
      public StringOutputStream(StringWriter stringWriter) {
        this.stringWriter = stringWriter;
      }
      /**重写OutputStream  write方法
       * 这个方法被ServletOutputStream调用而ServletOutputStream extends OutputStream
       */
      public void write(int c) {
        stringWriter.write(c);
      }
    }

      看一下ServletOutputStream类print方法

     public void print(String s)
        throws IOException
      {
        if (s == null) s = "null";
        int len = s.length();
        for (int i = 0; i < len; i++) {
          char c = s.charAt(i);
    
          if ((c & 0xFF00) != 0) {
            String errMsg = lStrings.getString("err.not_iso8859_1");
            Object[] errArgs = new Object[1];
            errArgs[0] = new Character(c);
            errMsg = MessageFormat.format(errMsg, errArgs);
            throw new CharConversionException(errMsg);
          }
          write(c);//在这里被调用
        }
      }
    View Code

    该类中其他所有输出String信息的方法都调用了该方法  

    疑问:当调用FilterChain 的doFilter方法时,怎么说就晚了呢?

      response是一个引用,当调用filterChain doFilter(或者是servlet jsp,没有其他过滤器的话)后,响应就通过这个引用写到端口上去了,所以说为时已晚

  • 相关阅读:
    149. Max Points on a Line(js)
    148. Sort List(js)
    147. Insertion Sort List(js)
    146. LRU Cache(js)
    145. Binary Tree Postorder Traversal(js)
    144. Binary Tree Preorder Traversal(js)
    143. Reorder List(js)
    142. Linked List Cycle II(js)
    141. Linked List Cycle(js)
    140. Word Break II(js)
  • 原文地址:https://www.cnblogs.com/tutar/p/3603085.html
Copyright © 2011-2022 走看看