为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

心有法竹 2021-11-17 17:25:48
我在拦截器中读取请求正文时遇到问题。双方getReader()并getInputStream()造成问题。我的拦截器:public class MyInterceptor extends HandlerInterceptorAdapter {@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)        throws Exception {    // TODO Auto-generated method stub}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)        throws Exception {    // TODO Auto-generated method stub}@Overridepublic 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)。这是一个已知的问题?有什么解决方法吗?
查看完整描述

1 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

最后我想通了,所以我会在这里留下一些简单但有用的建议给其他人。我使用了一个请求包装器,但为了使其正常工作,我添加了一个最高阶的过滤器,以便在开始执行拦截器之前将每个请求包装到包装器中。现在它运行良好;) 这是最重要的代码 - 过滤器将每个请求包装到多读包装器中(拦截器看起来与上面几乎相同,包装器不是我发明的,在堆栈中找到,我发现它最清晰易读):


@Component

@Order(Ordered.HIGHEST_PRECEDENCE)

public class GlobalWrapFilter implements Filter {


@Override

public void init(FilterConfig filterConfig) throws ServletException {

}


@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    MultiReadRequest wrapper = new MultiReadRequest((HttpServletRequest) request);

    chain.doFilter(wrapper, response);

}


@Override

public 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")));

    }

}

}


查看完整回答
反对 回复 2021-11-17
  • 1 回答
  • 0 关注
  • 295 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信