解决HttpServletRequest 中的 InputStream 只能读取一次问题
程序员文章站
2022-03-01 15:43:38
...
问题
公司使用 xml 方式流的方式发送请求,接收方使用 getInputStream() 获取数据,在过滤器中需要对请求的数据校验。过滤器校验完后无法重读 InputStream 中的数据。
原因
pos :标识当前流每次流读取的位置、 每读取一次pos 做一次位移、直至结束返回-1
因在读取一次后 pos值已经达到文件末尾、而 ServletInputStream 没有重写 rest() 方法、从而导致request.getInputStream 只能读取一次。
解决方法
public class AntiHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public AntiHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = StreamUtils.readBytes(request.getInputStream());
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}
}
使用
HttpServletRequest request = (HttpServletRequest)request0;
AntiHttpServletRequestWrapper antiHttpServletRequestWrapper = new AntiHttpServletRequestWrapper(request);
//获取请求中的参数
String param= StreamUtils.streamToString(antiHttpServletRequestWrapper.getInputStream());
工具类
public class StreamUtils {
/**
* @param inputStream inputStream
* @return 字符串转换之后的
*/
public static String streamToString(InputStream inputStream) {
try(BufferedReader br =new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
StringBuilder builder = new StringBuilder();
String output;
while((output = br.readLine())!=null){
builder.append(output);
}
return builder.toString();
} catch (IOException e) {
throw new RuntimeException("Http 服务调用失败",e);
}
}
public static byte[] readBytes(ServletInputStream inputStream) {
return streamToString(inputStream).getBytes(Charset.forName("UTF-8"));
}
}