@ExceptionHandler如何从HttpServletRequest

时间:2017-12-02 05:54:39

标签: spring spring-boot

我的休息控制器

@RestController
public class MyController {

    @RequestMapping(value = "/getrawjson",  method =  RequestMethod.POST)
    public @ResponseBody
    String search(@RequestBody Map<String, Object> json, HttpServletRequest httpServletRequest) throws PushNotiException,Exception {
        return "OK";
    }
}

我的异常处理无效的原始json帖子。我试图使用request.getInputStream()但我得到了错误

  

IllegalStateException:已为此请求调用getInputStream()

@ControllerAdvice
public class MethodArgumentNotValidExceptionHandler {

        @ExceptionHandler({org.springframework.http.converter.HttpMessageNotReadableException.class})
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ResponseBody
        public TrueIDResponse resolveException(HttpServletRequest request,Exception ex) throws IOException {

        }
}

我想在此异常上保留日志输入原始json数据。

任何人都可以帮助我吗?感谢。

更新

作为@Sean Carrol的建议。我尝试按照建议使用HttpServletRequestWrapper,但它仍然不起作用。

@ControllerAdvice
public class MethodArgumentNotValidExceptionHandler {



    @ExceptionHandler({org.springframework.http.converter.HttpMessageNotReadableException.class})
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ResponseBody
        public TrueIDResponse resolveException(HttpServletRequest request,Exception ex) throws IOException {
            MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request);
            InputStream inputStream = multiReadRequest.getInputStream();
            String theString = IOUtils.toString(inputStream, "UTF-8");

        }
}

我在InputStream输入了这个错误inputStream = multiReadRequest.getInputStream();线。

  

java.io.IOException:Stream closed

1 个答案:

答案 0 :(得分:-1)

我可以解决这个问题,只需添加一个过滤器,拦截当前的HttpServletRequest并将其包装在自定义的HttpServletRequestWrapper(MultipleReadHttpRequest)

@Component
public class CachingRequestBodyFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
        MultipleReadHttpRequest wrappedRequest = new MultipleReadHttpRequest(currentRequest);
        chain.doFilter(wrappedRequest, servletResponse);
    }
}

servlet 3.0的MultipleReadHttpRequest类

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
    private ByteArrayOutputStream cachedBytes;

    public MultiReadHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (cachedBytes == null)
            cacheInputStream();

        return new CachedServletInputStream();
    }

    @Override
    public BufferedReader getReader() throws IOException{
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    private void cacheInputStream() throws IOException {
    /* Cache the inputstream in order to read it multiple times. For
     * convenience, I use apache.commons IOUtils
     */
        cachedBytes = new ByteArrayOutputStream();
        IOUtils.copy(super.getInputStream(), cachedBytes);
    }

    /* An inputstream which reads the cached request body */
    public class CachedServletInputStream extends ServletInputStream {
        private ByteArrayInputStream input;

        public CachedServletInputStream() {
      /* create a new input stream from the cached request body */
            input = new ByteArrayInputStream(cachedBytes.toByteArray());
        }

        @Override
        public int read() throws IOException {
            return input.read();
        }

        @Override
        public boolean isFinished() {
            return input.available() == 0;
        }

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

        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");
        }
    }
}