在以multipart/form-data进行数据传输的时候,通过以下方式处理数据的时候
@RequestMapping(value = "/Devices/1000019$0/Events", method = RequestMethod.POST)
public void getStream(HttpServletRequest servletRequest) throws IOException {
dealDhData(servletRequest);
}
利用servletRequest.getReader()读取数据的时候,出现了“getInputStream() has already been called for this request”或者用servletRequest.getInputStream()读取数据发觉为null。报这个错,说明在进入Controller这个过程前数据已经被读取了一次。为了解决这个问题,需要在拦截器中进行处理。
在pom.xml中引入以下依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
以下为具体代码:
package net.dlet.dhdemo.configure;
import net.dlet.dhdemo.utils.dhutils.MyRequestWrapper;
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;
/**
* @Description:
* @PackageName: net.dlet.dhdemo.configure
* @Name: RequestReplaceFilter
* @Author: cure
* @CreateDate: 2020/09/06 4:58
* @ModifyUser:
* @ModifyDate:
* @ModifyDesc: 修改内容
* @DayNameFull: 星期日
* @ProjectName: dhdemo
* @Version: 1.0
**/
@Component
public class RequestReplaceFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if (!(request instanceof MyRequestWrapper)) {
request = new MyRequestWrapper(request);
}
filterChain.doFilter(request, response);
}
}
package net.dlet.dhdemo.utils.dhutils;
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;
/**
* @Description: 解决request.getInputStream()只能读取一次的问题
* @PackageName: net.dlet.dhdemo.utils.dhutils
* @Name: MyRequestWrapper
* @Author: cure
* @CreateDate: 2020/09/06 4:44
* @ModifyUser:
* @ModifyDate:
* @ModifyDesc: 修改内容
* @DayNameFull: 星期日
* @ProjectName: dhdemo
* @Version: 1.0
**/
public class MyRequestWrapper extends HttpServletRequestWrapper {
private volatile byte[] body;
public MyRequestWrapper(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() {
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;
}
}
}
主要参考解决request.getInputStream()只能读取一次的问题这篇文章
2020-09-07 采用这种方式处理可能更好