过滤器通过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);//在这里被调用
}
}

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

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

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

最新文章

  1. JAVA基本类库介绍
  2. jade模板引擎的基本使用
  3. 用git difff 生成补丁
  4. jquery点击控制动画暂停开始
  5. JM编解码264
  6. Android 项目建立步骤
  7. out返回值的用法与用途
  8. UGUI Text控件
  9. SharePoint 2010 用Event Receiver将文件夹自动变成approved状态 (2)
  10. 使用phpQuery实现批量文件处理
  11. Unity人工智能学习—确定性AI算法之追踪算法二
  12. UITableView回调和table相关成员方法详解
  13. C#实现手机发送验证码
  14. 在Linux中使用线程
  15. 二.java下使用RabbitMQ实现hello world
  16. hadoop hdfs 高可用
  17. codeforces-1132 (div2)
  18. Python_程序实现发红包
  19. CF875F Royal Questions
  20. Linux——进程管理学习简单笔记

热门文章

  1. PL/SQL题型代码示例
  2. Redhat 7修改主机名
  3. PXE自动化部署
  4. 测试人员必备:linux文件清理不得不知道的技巧
  5. eclipse中安装Activiti插件
  6. CSS中cursor属性
  7. 递归型SPFA+二分答案 || 负环 || BZOJ 4773
  8. IC SPEC相关数据
  9. split 命令
  10. SQL server 获取异常