HttpServletResponse内容读取操作

/ Servlet / 没有评论 / 66浏览

我们知道HttpServletResponse api中并没有对body内容读取,我们需要采用设计模式之wrapper模式

背景

在项目中,遇到需要在Filter中对HttpServletResponse中的内容进行读取,然后坐一些操作。但是原生的HttpServletResponse api是没有获取body方法的,只能reset,write等。

这时,我们需要采用wrapper模式对HttpServletResponse进行争强。

ContentCachingResponseWrapper

我们可以利用Spring Mvc中的一个工具类ContentCachingResponseWrapper,来完成对body的操作。

/**
 * {@link javax.servlet.http.HttpServletResponse} wrapper that caches all content written to
 * the {@linkplain #getOutputStream() output stream} and {@linkplain #getWriter() writer},
 * and allows this content to be retrieved via a {@link #getContentAsByteArray() byte array}.
 *
 * <p>Used e.g. by {@link org.springframework.web.filter.ShallowEtagHeaderFilter}.
 *
 * @author Juergen Hoeller
 * @since 4.1.3
 * @see ContentCachingRequestWrapper
 */
public class ContentCachingResponseWrapper extends HttpServletResponseWrapper {
}

它将getOutputStreamgetWriter方法写的内容都缓存起来,然后通过getContentAsByteArray方法获取缓存的字节数组。

使用

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletResponse resp = (HttpServletResponse) servletResponse;
    // 这里包装resp,缓存body,供分析body内容
    ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(resp);
    // 后续之ing
    filterChain.doFilter(req, respWrapper);
    // 做一些事情
    doSomthing(respWrapper);
    // 将内容复制到原始响应
    respWrapper.copyBodyToResponse();
}

要注意的是:在doFilter最后一定要调用copyBodyToResponse方法,它会将缓存的字节数组输出到原始响应中去,不然浏览器会接收不到任务内容。

小结