1. 程式人生 > >異常:getReader() has already been called for this request

異常:getReader() has already been called for this request

一個流不能讀兩次異常,這種異常一般出現在框架或者攔截器中讀取了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>