Spring ResponseEntityExceptionHandler和原始POST有效负载验证错误

时间:2016-09-01 13:14:19

标签: spring validation spring-boot

我在基于 Spring Boot 的RESTFul应用程序中使用ResponseEntityExceptionHandler,以便在一个地方捕获错误并输出一致的错误有效负载。

一切都按预期工作。扩展ResponseEntityExceptionHandler的类可以覆盖handleMethodArgumentNotValid,以便在发送未通过验证的消息的客户端上“做出反应”。 目前,通过使用@Valid注释注释请求正文来触发验证。

一切都按预期工作。如果客户端POST了一个未验证的JSON文档,则handleMethodArgumentNotValid中的代码将正确执行。

现在,出于监控目的,我想记录无效的JSON。显然,原始InputStream已关闭。

我通过升级MappingJackson2HttpMessageConverter解决了类似的问题recently,但在链接的情况下,我需要“挂钩”到验证过程并抛出包含无效JSON文档的自定义异常。 / p>

任何指针?

1 个答案:

答案 0 :(得分:0)

您可以尝试使用 HttpServletRequest 包装原始 HttpServletRequest 过滤器,并在容器读取之后在内部存储 InputStreams 的数据。 这是代码:

public class RequestCachingRequestWrapperFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        filterChain.doFilter(new RequestCachingRequestWrapper(request), response);
    }

    public class RequestCachingRequestWrapper extends HttpServletRequestWrapper {

        private final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        private final ServletInputStream inputStream;
        private BufferedReader reader;

        private RequestCachingRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            this.inputStream = new RequestCachingInputStream(request.getInputStream());
        }

        public ByteArrayOutputStream getCache() {
            return this.bos;
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            return inputStream;
        }

        @Override
        public String getCharacterEncoding() {
            return super.getCharacterEncoding() != null ? super.getCharacterEncoding() : WebUtils.DEFAULT_CHARACTER_ENCODING;
        }

        @Override
        public BufferedReader getReader() throws IOException {
            if (this.reader == null) {
                this.reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding()));
            }
            return this.reader;
        }

        private class RequestCachingInputStream extends ServletInputStream {

            private final ServletInputStream is;

            private RequestCachingInputStream(ServletInputStream is) {
                this.is = is;
            }

            @Override
            public int read() throws IOException {
                int ch = is.read();
                if (ch != -1) {
                    bos.write(ch);
                }
                return ch;
            }

        }

    }
}

它是在不久前发布在这里的,但是我找不到原始的奖励来赞美。