異常:getReader() has already been called for this request
阿新 • • 發佈:2019-01-06
一個流不能讀兩次異常,這種異常一般出現在框架或者攔截器中讀取了request中的流的資料,我們在業務程式碼中再次讀取(如@requestBody),由於流中的資料已經沒了,所以第二次讀取的時候就會丟擲異常。
解決方案:定義一個過濾器將流中的資料讀取到一個數組中,並重寫getInputStream()和getRead()方法,後續獲取流中的資料的時候,直接去陣列中讀取,程式碼實現如下:
class DealStreamFilter extends AbstractWebFilter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
logger.info("進入DealStreamFilter。。。。。。" );
ServletRequest requestWrapper = null;
if (servletRequest instanceof HttpServletRequest) {
requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) servletRequest);
}
if (null == requestWrapper) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
static class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super (request);
body = toByteArray(request.getInputStream());
}
private byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 4];
int n = 0;
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
}
return out.toByteArray();
}
@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();
}
};
}
}
}
將過濾器配置到配置檔案:
<bean id="dealStreamFilter" class="com.pingan.apollo.filter.DealStreamFilter">
<property name="patterns" >
<list>
<value>/loan/device/report.do</value>
</list>
</property>
<property name="order" >
<value>-999999</value>
</property>
</bean>