what is `ContentCachingRequestWrapper` does?

发布时间:2024年01月24日

ContentCachingRequestWrapper 是 Spring Framework 中提供的一种包装类,它扩展了 HttpServletRequestWrapper 类,用于缓存请求体的内容。

通常在处理 HTTP 请求时,原生的 HttpServletRequest 对象中的输入流 (getInputStream()) 只能被读取一次,如果需要多次访问请求体内容(比如在进行过滤、校验或转发请求时),就会遇到问题。
ContentCachingRequestWrapper 解决了这个问题,通过在第一次读取请求体时将数据复制到一个缓冲区中,后续对请求体的读取操作会从这个缓冲区而不是原始输入流中获取数据。这样就允许开发者多次读取请求体而不会抛出异常,并且保持了请求体数据的一致性。

使用 ContentCachingRequestWrapper 时,通常是在应用的前置处理器、拦截器或者过滤器中创建并替换原来的 HttpServletRequest 实例,以便在后面的处理流程中安全地重复访问请求体内容。

在这里插入图片描述
使用样例:用在过滤器中

import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestBodyCachingFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        // 创建 ContentCachingRequestWrapper 对象来缓存请求体
        HttpServletRequest wrapper = new ContentCachingRequestWrapper(request);

        // 继续执行过滤链,并传递包装后的请求对象
        filterChain.doFilter(wrapper, response);

        // 在过滤链执行完毕后,可以访问缓存的请求体内容
        byte[] cachedBody = ((ContentCachingRequestWrapper) wrapper).getContentAsByteArray();

        // 在此处进行对请求体内容的处理或验证
        String requestBody = new String(cachedBody, request.getCharacterEncoding());

        // 示例:打印请求体内容
        System.out.println("The request body is: " + requestBody);
    }
}

使用样例:用在过滤器中

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestBodyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 创建 ContentCachingRequestWrapper 对象来缓存请求体
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);

        // 你可以在这里读取并处理请求体内容,例如进行预处理或验证
        byte[] cachedBody = wrappedRequest.getContentAsByteArray();
        String requestBody = new String(cachedBody, request.getCharacterEncoding());

        // 示例:打印请求体内容
        System.out.println("The request body is: " + requestBody);

        // 将包装后的请求对象传递给后续的处理流程
        request = wrappedRequest;

        // 如果需要继续执行请求处理,则返回 true
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可以在此处访问已经缓存的请求体数据
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求处理完成后,仍可以访问缓存的请求体数据
    }
}
文章来源:https://blog.csdn.net/weixin_37646636/article/details/135832869
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。