• 过滤器修改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,没有其他过滤器的话)后,响应就通过这个引用写到端口上去了,所以说为时已晚

  • 相关阅读:
    问题账户需求分析
    需求分析初学理解
    GitHub初步探索-1-使用本地代码管理工具,简化上传的过程
    软件工程概论-个人总结
    第二次冲刺-个人工作总结05
    第二次冲刺-个人工作总结04
    第二次冲刺-个人工作总结03
    第二次冲刺-个人工作总结02
    第二次冲刺-个人工作总结01
    第一次冲刺-个人工作总结10
  • 原文地址:https://www.cnblogs.com/tutar/p/3603085.html
Copyright © 2020-2023  润新知