Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 错误响应实体中的Spring Boot添加请求正文_Java_Spring_Spring Boot_Kotlin - Fatal编程技术网

Java 错误响应实体中的Spring Boot添加请求正文

Java 错误响应实体中的Spring Boot添加请求正文,java,spring,spring-boot,kotlin,Java,Spring,Spring Boot,Kotlin,我有自己的Exceptionhandler,它正在扩展ResponseEntityExceptionHandler 我能够捕获错误,但在创建错误响应时,请求正文是空的 override fun handleHttpMessageNotReadable(e:HttpMessageNotReadableException, headers:HttpHeaders , status:HttpStatus , webRequest: WebRequest):ResponseEntity<Any&g

我有自己的Exceptionhandler,它正在扩展ResponseEntityExceptionHandler

我能够捕获错误,但在创建错误响应时,请求正文是空的

override fun handleHttpMessageNotReadable(e:HttpMessageNotReadableException, headers:HttpHeaders , status:HttpStatus , webRequest: WebRequest):ResponseEntity<Any>{
        val rsp = ErrResponse(
                Data(
                        HttpStatus.BAD_REQUEST.name,
                        e.message!!
                ),**REQUEST-BODY-NEEDED**[customFilter.payload])
        return super.handleExceptionInternal(e, rsp,headers, HttpStatus.BAD_REQUEST, webRequest)
    }
因此,我使用customRequestfilter获取主体,并在那里捕获主体,但是customRequestfilter的顺序依赖性很低,它将仅在请求之后执行。那么,有没有办法在错误响应上捕获请求主体呢

CustomRequestFilter

@Component
public class CustomRequestFilter extends OncePerRequestFilter{

 public String payload;
    public Map<String, Object> reqLog =null;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);

        int status = HttpStatus.BAD_REQUEST.value();

        filterChain.doFilter(wrappedRequest, response);
        if (status == response.getStatus()) {
            reqLog = getTrace(wrappedRequest, status);
            payload = getBody(wrappedRequest, reqLog);/** ITS CAPTURING THE BODY HERE SUCCESSFULLY**/
            logTrace(wrappedRequest, reqLog); 
        }

    }

哇,真是棘手!无论如何

创建自定义HttpInputMessage,它将委托给原始HttpInputMessage

class CachedHttpInputMessage implements HttpInputMessage {
    private final HttpInputMessage httpInputMessage;
    private ByteArrayOutputStream outputStream;

    CachedHttpInputMessage(final HttpInputMessage httpInputMessage) {
        this.httpInputMessage = httpInputMessage;
    }

    @Override
    public InputStream getBody() throws IOException {
        if (outputStream == null) {
            outputStream = new ByteArrayOutputStream();

            final InputStream body = httpInputMessage.getBody();
            final byte[] buffer = new byte[1024];

            while (true) {
                final int length;
                if (!((length = body.read(buffer)) > -1)) {
                    break;
                }

                outputStream.write(buffer, 0, length);
            }

            outputStream.flush();
        }

        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    @Override
    public HttpHeaders getHeaders() {
        return httpInputMessage.getHeaders();
    }
}
构建定制的HttpMessageConverter,根据当前使用的Jackson、Gson等扩展正确的HttpMessageConverter,并将其注册为first

class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {
    @Override
    public Object read(
            final Type type,
            final Class<?> contextClass,
            final HttpInputMessage inputMessage) throws IOException {
        return super.read(type, contextClass, new CachedHttpInputMessage(inputMessage));
    }

    @Override
    protected Object readInternal(
            final Class<?> clazz,
            final HttpInputMessage inputMessage) throws IOException {
        return super.readInternal(clazz, new CachedHttpInputMessage(inputMessage));
    }
}
扔掉自定义过滤器,在ExceptionHandler中使用

final HttpInputMessage inputMessage = e.getHttpInputMessage();
final InputStream body = inputMessage.getBody();
完成了!
请记住稍微清理一下代码并处理所有可能的异常。

这是Kotlin,不是Java。我将编辑标记。您将在哪里引发HttpMessageNotReadable异常?它是在Spring框架内部抛出的吗?刚刚检查过,它是从HttpMessageConverterYep抛出的,它是由springLppEdd抛出的,这是用Java编写的代码的一部分。只是java和kotlin之间的混合,因为第二部分也是其他项目的库,它们是java basedI,当我尝试读取主体java.io.IOException:Stream closed at java.io.PushbackInputStream.PushbackInputStream.java:74 atjava.io.PushbackInputStream.readPushbackInputStream.java:135@sankar您是否在维护ContentCachingRequestWrapper?我在执行e.getHttpInputMessage时已经对其进行了注释。@sankar我认为您仍需要在筛选器中使用它,并将其传递给筛选器链。否则输入流将被关闭。好的,现在我也得到了同样的错误。现在我将wrappedRequest传递给filterchain,这有点奇怪,应该在框架filterchain.doFilterRappedRequest,response中处理;
final HttpInputMessage inputMessage = e.getHttpInputMessage();
final InputStream body = inputMessage.getBody();