首页 > 其他分享 >遭遇getReader() has already been called for this request错误

遭遇getReader() has already been called for this request错误

时间:2023-02-24 13:58:02浏览次数:40  
标签:body already return request Override getReader public

该错误的原因是HttpServletRequest的getInputStream()和getReader()只能调用一次,【getReader()底层调用了getInputStream()】。@RequestBody也是流的形式读取,流读取一次就没了。

这种场景一般出现在拦截器中读取了流,并且接口使用了@RequestBody注解的,就会导致重复读取流,抛出这个异常。

解决方法:
因为过滤器是优先于拦截器执行的,所以我们可以写一个过滤器,在过滤器里面把流的数据copy一份出来,放入自定义的Wrapper对象,然后把这个wrapper对象当做request往下传递(wrapper和request可以强转),这样在拦截器中拿到的就是我们copy出来的流,就可以反复读取了,如
过滤器:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

    request = new AuthRequestWrapper(request);
    filterChain.doFilter(request,response);
}

AuthRequestWrapper:

@Slf4j
public class AuthRequestWrapper extends HttpServletRequestWrapper {

    private String body;

    public AuthRequestWrapper(HttpServletRequest request) {
        super(request);
        try(BufferedReader reader = request.getReader()){
            body= reader.lines().collect(Collectors.joining());
        }catch (Exception e){
            log.error("!!-- read request from requestbody error",e);
        }
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletIns = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() {
                return byteArrayIns.read();
            }
        };
        return  servletIns;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

后续拦截器使用:

if (request instanceof AuthRequestWrapper){
    return ((AuthRequestWrapper)request).getBody();
}

标签:body,already,return,request,Override,getReader,public
From: https://www.cnblogs.com/yyfyy/p/17151175.html

相关文章