Spring boot 2.0 解决 RequestBody 和 ResponseBody 重复读取问题

本贴最后更新于 1857 天前,其中的信息可能已经时异事殊

为什么 RequestBody 只能读取一次?

方法一

1.创建一个自定义 HttpServletRequestWrapper

import org.springframework.util.StreamUtils; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; /** * @author yudong * @version 1.0 * @date 2020/3/20 3:04 下午 * @modified By */ public class BodyReaderRequestWrapper extends HttpServletRequestWrapper { private final byte [] body; /** * * @param request */ public BodyReaderRequestWrapper(HttpServletRequest request) throws IOException { super(request); body = StreamUtils.copyToByteArray(request.getInputStream()); } @Override public BufferedReader getReader() { return new BufferedReader(new InputStreamReader(this.getInputStream())); } @Override public ServletInputStream getInputStream(){ final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body); ServletInputStream servletIns = new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) {} @Override public int read() { return byteArrayIns.read(); } }; return servletIns; } }

2.创建一个 filter

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * @author yudong * @version 1.0 * @date 2020/3/20 3:07 下午 * @modified By */ @Component @Order @WebFilter(filterName="bodyReader", urlPatterns="/**") public class BodyReaderFilter implements Filter { private final static Logger logger = LoggerFactory.getLogger(BodyReaderFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { logger.info("filter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)servletRequest; BodyReaderRequestWrapper requestWrapper = new BodyReaderRequestWrapper(req); filterChain.doFilter(requestWrapper, servletResponse); } @Override public void destroy() { } }

3.测试

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.*; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import java.nio.charset.Charset; /** * 重复读取测试 * @author yudong * @version 1.0 * @date 2020/2/11 2:38 下午 * @modified By */ @ResponseBody @Controller public class TestController { @Autowired private Test test; @PostMapping("test") public String test(HttpServletRequest httpServletRequest, @RequestBody String ss)throws Exception{ ServletInputStream inputStream = httpServletRequest.getInputStream(); String s = StreamUtils.copyToString(inputStream, Charset.forName("UTF-8")); return s; } }

方法二

1.创建一个 filter

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.util.ContentCachingRequestWrapper; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * @author yudong * @version 1.0 * @date 2020/3/20 3:07 下午 * @modified By */ @Component @Order @WebFilter(filterName="bodyReader", urlPatterns="/**") public class BodyReaderFilter implements Filter { private final static Logger logger = LoggerFactory.getLogger(BodyReaderFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { logger.info("filter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)servletRequest; ContentCachingRequestWrapper contentCachingRequestWrapper = new ContentCachingRequestWrapper(req); filterChain.doFilter(contentCachingRequestWrapper, servletResponse); } @Override public void destroy() { } }

2.编写测试 controller

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.ContentCachingRequestWrapper; import javax.servlet.http.HttpServletRequest; /** * @author yudong * @version 1.0 * @date 2020/2/11 2:38 下午 * @modified By */ @ResponseBody @Controller public class TestController { @PostMapping("test") public String test(HttpServletRequest httpServletRequest, @RequestBody String ss)throws Exception{ ContentCachingRequestWrapper contentCachingRequestWrapper = (ContentCachingRequestWrapper)httpServletRequest; byte[] contentAsByteArray = contentCachingRequestWrapper.getContentAsByteArray(); String body = new String(contentAsByteArray); return body ; } }

ResponseBody 重复读取

ContentCachingResponseWrapper responseToCache = new ContentCachingResponseWrapper(httpServletResponse); //读取值 String responseBody = new String(responseToCache.getContentAsByteArray()); //重写写入到responseBody中 responseToCache.copyBodyToResponse();
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    948 引用 • 1460 回帖 • 1 关注
  • HTTP
    75 引用 • 128 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...