利用Filter和HttpServletResponseWrapper如何拦截response数据
利用Filter和HttpServletResponseWrapper如何拦截response数据
新手小白一枚,记录一下学习filter过程中的知识。
都知道HttpServletResponseWrapper是一个用来创建虚拟response的类,通过这个类可以截获response的内容,是我们可以对其进行一些处理,但是具体是怎么从response获得数据,下面是我自己的一点理解。如有错误,欢迎指正。
首先,要想对request、response进行过滤或拦截,需要使用实现Filter这个接口的类,然后在自身的doFilter方法中中进行一些过滤之类的处理,然后再调用一个filterchain.doFilter方法把request和response传递下去。
那么,如果我们想要拦截response返回的数据,就不能直接把原始的response传入doFilter方法,因为这样数据就会直接socket,所以我们需要利用HttpServletResponseWrapper来创建一个虚拟的response来确保获得输出的数据。
public class CacheFilter implements Filter{}
class CachedHttpServletResponse extends HttpServletResponseWrapper{}
通过上面代码的形式我们可以编写自己的Filter和Wrapper,然后在Wrapper类里面覆写我们需要的方法,大致如下所示
public PrintWriter getWriter() throws IOException {
if (open) {
throw new IllegalStateException("Cannot re-open writer!");
}
open = true;
return new PrintWriter(output, false, StandardCharsets.UTF_8);
}
// 获取OutputStream:
public ServletOutputStream getOutputStream() throws IOException {
if (open) {
throw new IllegalStateException("Cannot re-open output stream!");
}
open = true;
return new ServletOutputStream() {
public boolean isReady() {
return true;
}
public void setWriteListener(WriteListener listener) {
}
// 实际写入ByteArrayOutputStream:
public void write(int b) throws IOException {
output.write(b);
}
};
}
public byte[] getContent() {
return output.toByteArray();
}
在我们想要截获response的数据时,可以在Filter的doFilter方法中写下这样的代码
CachedHttpServletResponse wrapper = new CachedHttpServletResponse(resp);
chain.doFilter(request, wrapper);
这样filterchain就会把wrapper这个虚拟的response传递给下一个目标,而这个目标就是处理request的一个servlet实例,假如是一个get请求,那么doGet方法传入参数就是request和wrapper,此方法从后端(比如数据库)获取数据后就会调用response的writer写入数据,但这里传入的是wrapper,所以就会调用我们覆写的writer或outputstream,把数据写到我们的output,通过这样我们就获得了数据,可以对其进行处理。处理完之后再将其交给原始的response调用writer写入,返回给前端。
另外,如果filter实现了缓存,那么我们就可以将从后方获取的数据缓存起来,等到再次遇到同样的请求时,就不必再去后方获取数据,而是直接将缓存写入response,节省开销,提高效率。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)