解决Request中输入流只能读取一次的问题
程序员文章站
2022-03-10 11:45:31
...
解决Request中输入流只能读取一次的问题
1. 创建一个Request类对Request进行包装
package com.dbh123.dubbo.api.config;
import org.apache.commons.io.IOUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 包装HttpServletRequest
*/
public class MyServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
/**
* Construct a wrapper for the specified request.
*
* @param request The request to be wrapped
*/
public MyServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = IOUtils.toByteArray(super.getInputStream());
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new RequestBodyCachingInputStream(body);
}
private class RequestBodyCachingInputStream extends ServletInputStream {
private byte[] body;
private int lastIndexRetrieved = -1;
private ReadListener listener;
public RequestBodyCachingInputStream(byte[] body) {
this.body = body;
}
@Override
public int read() throws IOException {
if (isFinished()) {
return -1;
}
int i = body[lastIndexRetrieved + 1];
lastIndexRetrieved++;
if (isFinished() && listener != null) {
try {
listener.onAllDataRead();
} catch (IOException e) {
listener.onError(e);
throw e;
}
}
return i;
}
@Override
public boolean isFinished() {
return lastIndexRetrieved == body.length - 1;
}
@Override
public boolean isReady() {
// This implementation will never block
// We also never need to call the readListener from this method, as this method will never return false
return isFinished();
}
@Override
public void setReadListener(ReadListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener cann not be null");
}
if (this.listener != null) {
throw new IllegalArgumentException("listener has been set");
}
this.listener = listener;
if (!isFinished()) {
try {
listener.onAllDataRead();
} catch (IOException e) {
listener.onError(e);
}
} else {
try {
listener.onAllDataRead();
} catch (IOException e) {
listener.onError(e);
}
}
}
@Override
public int available() throws IOException {
return body.length - lastIndexRetrieved - 1;
}
@Override
public void close() throws IOException {
lastIndexRetrieved = body.length - 1;
body = null;
}
}
}
2. 创建一个过滤器对Request进行替换
package com.dbh123.dubbo.api.filter;
import com.dbh123.dubbo.api.config.MyServletRequestWrapper;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 替换Request对象
*/
@Component
public class RequestReplaceFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (!(request instanceof MyServletRequestWrapper)) {
request = new MyServletRequestWrapper(request);
}
filterChain.doFilter(request, response);
}
}
上一篇: python框架Django实战商城项目之工程搭建
下一篇: Fork/Join框架简介
推荐阅读
-
浅谈request.getinputstream只能读取一次的问题
-
springboot请求体中的流只能读取一次的问题
-
解决request.getInputStream()只能读取一次的方案
-
拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.
-
解决request.getInputStream()与request.getReader()只能调用一次的问题
-
解决 request.getInputStream()只能获取一次的问题
-
拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.
-
Request中的InputStream只能读取一次的问题
-
Servlet的Request.getInputStream()只能读取一次问题
-
解决request.getInputStream()只能读取一次的问题