post请求体内容无法重复获取

post请求体内容无法重复获取

为什么会无法重复读取呢?

以tomcat为例,在进行请求体读取时实际底层调用的是org.apache.catalina.connector.Request的getInputStream()方法,而该方法返回的是CoyoteInputStream输入流

java 复制代码
public ServletInputStream getInputStream() throws IOException {

    if (usingReader) {
        throw new IllegalStateException(sm.getString("coyoteRequest.getInputStream.ise"));
    }

    usingInputStream = true;
    if (inputStream == null) {
        inputStream = new CoyoteInputStream(inputBuffer);
    }
    return inputStream;

}

在使用CoyoteInputStream进行读取时

java 复制代码
public int read(byte[] b, int off, int len) throws IOException {
  // 如果流关闭,则抛出异常
    if (closed) {
        throw new IOException(sm.getString("inputBuffer.streamClosed"));
    }
// 如果已经读完了,则返回-1
    if (checkByteBufferEof()) {
        return -1;
    }
    int n = Math.min(len, bb.remaining());
    bb.get(b, off, n);
    return n;
}

而流读取完毕都会进行close,这个流close之后,close状态就置为了true,所以导致流无法进行二次读取

那么如何解决呢?将tomcat的Request类进行重新实现吗?代价太大了,sun公司当初在设计的时候就已经提供了解决方法,对于请求和响应,sun公司提供了包装类,可以HttpServletRequestWrapper类包装原始的request对象,实现了HttpServletRequest接口的所有方法,内部调用了所包装的request对象的对应方法;相应的也有HttpServletResponseWrapper类来包装原始的response对象继承HttpServletRequestWrapper来进行方法重写,可以使用HttpServletResponseWrapper和HttpServletRequestWrapper来进行定制响应和请求

java 复制代码
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
		// 存储请求体
    private byte[] body;

    private HttpServletRequest orgRequest;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        this.orgRequest = request;
        body = HttpHelper.getBody(request);
    }

    public HttpServletRequest getOrgRequest() {
        return this.orgRequest;
    }

  // 重写读取,从存储的字节数组中读
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

  // 重写读取,从存储的字节数组中读
    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

zhhll.icu/2020/javawe...

本文由mdnice多平台发布

相关推荐
付朝鲜7 分钟前
用自写的jQuery库+Ajax实现了省市联动
java·前端·javascript·ajax·jquery
小赵面校招9 分钟前
Spring Boot整合MyBatis全攻略:原理剖析与最佳实践
java·spring boot·mybatis
曼岛_13 分钟前
[Java实战]Spring Boot 3 整合 Ehcache 3(十九)
java·spring boot·spring
意倾城14 分钟前
Spring Boot 配置文件敏感信息加密:Jasypt 实战
java·spring boot·后端
曼岛_14 分钟前
[Java实战]Spring Boot 3 整合 Apache Shiro(二十一)
java·spring boot·apache
火皇40515 分钟前
Spring Boot 使用 OSHI 实现系统运行状态监控接口
java·spring boot·后端
带刺的坐椅17 分钟前
Java Solon v3.3.0 发布(国产优秀应用开发基座)
java·spring·solon
不再幻想,脚踏实地18 分钟前
Spring Boot配置文件
java·数据库·spring boot
pedestrian_h26 分钟前
Spring AI 开发本地deepseek对话快速上手笔记
java·spring boot·笔记·llm·ollama·deepseek
诚丞成26 分钟前
BFS算法篇——从晨曦到星辰,BFS算法在多源最短路径问题中的诗意航行(上)
java·算法·宽度优先