坑记(HttpInputMessage)

一、背景知识

public interface HttpInputMessage
extends HttpMessage
Represents an HTTP input message, consisting of headers and a readable body.

Typically implemented by an HTTP request on the server-side, or a response on the client-side.

Since:
3.0
Author:
Arjen Poutsma

在实现接口的加密处理过程中, 我们一般选择使用SpringMVCResponseBodyRequestBody,实现接口报文的监听和处理操作。在监听时,需分别实现相关的Advice类,以帮助完成自己的逻辑实现。交互流程图可以参考:
坑记(HttpInputMessage)_第1张图片

HttpInputMessage正是我们需要获取header和请求body的关键。今天我们谈谈使用过程中可能遇到的问题。

二、情况说明

1. 问题描述

我们在实现RequestBodyAdvice时,通常会重写以下方法:

 public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
      //读取请求body
      byte[] body = new byte[inputMessage.getBody().available()];
      inputMessage.getBody().read(body);
}

如我们使用以上方式,读取请求报文数据时,可能产生“读不完整”的现象。因为InputStream .available()方法描述如下:

public abstract class InputStream implements Closeable {
/**
     * Returns an estimate of the number of bytes that can be read (or
     * skipped over) from this input stream without blocking by the next
     * invocation of a method for this input stream. The next invocation
     * might be the same thread or another thread.  A single read or skip of this
     * many bytes will not block, but may read or skip fewer bytes.
     *
     * 

Note that while some implementations of {@code InputStream} will return * the total number of bytes in the stream, many will not. It is * never correct to use the return value of this method to allocate * a buffer intended to hold all data in this stream. * *

A subclass' implementation of this method may choose to throw an * {@link IOException} if this input stream has been closed by * invoking the {@link #close()} method. * *

The {@code available} method for class {@code InputStream} always * returns {@code 0}. * *

This method should be overridden by subclasses. * * @return an estimate of the number of bytes that can be read (or skipped * over) from this input stream without blocking or {@code 0} when * it reaches the end of the input stream. * @exception IOException if an I/O error occurs. */ public int available() throws IOException { return 0; } }

其中,有一句描述:

many bytes will not block, but may read or skip fewer bytes.

这就厉害了,不阻塞,但是可能丢包…所以如果使用上述方法,读取请求body时,数据并不完整,会导致后续逻辑出现异常。

2. 解决过程

上述方法有问题,可使用这个办法:

String reqBody = StreamUtils.copyToString(inputMessage.getBody(), Charset.defaultCharset());

亲测有效哦~

结束语

多看、多学、多试,总会找到解决的办法和途径。

你可能感兴趣的:(日记本,小技巧,spring,RequestBody,后端,JAVA)