猿问

无法正确读取拦截器中的请求正文 - Spring BOOT 2.0.4

我在拦截器中读取请求正文时遇到问题。双方getReader()并getInputStream()造成问题。我的拦截器:


public class MyInterceptor extends HandlerInterceptorAdapter {

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)

        throws Exception {

    // TODO Auto-generated method stub


}

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)

        throws Exception {

    // TODO Auto-generated method stub

}

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


    String requestBody = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));


//or

// String requestBody = new BufferedReader(new InputStreamReader(httpRequest.getInputStream()))

//                .lines().collect(Collectors.joining("\n"));

//some logic...

    return true;

}

两种方法都失败了,因为 spring 可能在内部某处使用了这样的资源。第一个原因java.lang.IllegalStateException: getReader() 已经被这个请求调用,并且缺少其他必需的请求体:org.springframework.http.ResponseEntity ...


我已经尝试了一些没有效果的包装器解决方法。我认为这是因为我不能像过滤器那样传递包装器(我不想使用过滤器,因为我有常见的异常管理器(@ControllerAdvice)。


这是一个已知的问题?有什么解决方法吗?


心有法竹
浏览 296回答 1
1回答

慕哥6287543

最后我想通了,所以我会在这里留下一些简单但有用的建议给其他人。我使用了一个请求包装器,但为了使其正常工作,我添加了一个最高阶的过滤器,以便在开始执行拦截器之前将每个请求包装到包装器中。现在它运行良好;) 这是最重要的代码 - 过滤器将每个请求包装到多读包装器中(拦截器看起来与上面几乎相同,包装器不是我发明的,在堆栈中找到,我发现它最清晰易读):@Component@Order(Ordered.HIGHEST_PRECEDENCE)public class GlobalWrapFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {    MultiReadRequest wrapper = new MultiReadRequest((HttpServletRequest) request);    chain.doFilter(wrapper, response);}@Overridepublic void destroy() {}class MultiReadRequest extends HttpServletRequestWrapper {    private String requestBody;    public MultiReadRequest(HttpServletRequest request) {        super(request);        try {            requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public ServletInputStream getInputStream() throws IOException {        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());        return new ServletInputStream() {            @Override            public boolean isFinished() {                return byteArrayInputStream.available() == 0;            }            @Override            public boolean isReady() {                return true;            }            @Override            public void setReadListener(ReadListener readListener) {            }            @Override            public int read() throws IOException {                return byteArrayInputStream.read();            }        };    }    @Override    public BufferedReader getReader() throws IOException {        return new BufferedReader(new InputStreamReader(this.getInputStream(), Charset.forName("UTF-8")));    }}}
随时随地看视频慕课网APP

相关分类

Java
我要回答