Request Body数据读取
程序员文章站
2022-07-12 11:55:13
...
拦截器要读取request body数据的话需要注意一个问题,一旦拦截器把数据流从request读取出来后,后区的接口层就拿不到数据了,因为流是一次性的,那么要解决这个问题,我们就需要在拦截器取出流拿到数据后重新将数据放回流,这样后面的接口层就能正常获取到数据了
下面放出代码实现:
@Component
@Order(10000)
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/")
public class HttpServletRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig){
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
String path = "";
if (servletRequest instanceof HttpServletRequest && servletRequest.getInputStream() != null) {
path = ((HttpServletRequest) servletRequest).getRequestURI();
if(path.equals( "/health" )){
filterChain.doFilter(servletRequest, servletResponse);
return;
}
//获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
}
//在chain.doFiler方法中传递新的request对象
if (null == requestWrapper) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
if(servletResponse.getOutputStream() != null){
RequestWrapper.transmittableThreadLocal.remove();
}
}
@Override
public void destroy() {
}
}
/**
* <p>Title:HttpServletRequest 包装器</p>
* <p>Description:
* 解决: request.getInputStream()只能读取一次的问题
* 目标: 流可重复读
* </p>
* @author QIQI
* @params
* @return
* @throws
* @date 2020/11/16 14:24
*/
public class RequestWrapper extends HttpServletRequestWrapper {
public static final ThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
/**
* 请求体
*/
private String mBody;
public RequestWrapper(HttpServletRequest request) {
super(request);
// 将body数据存储起来
mBody = getBody(request);
transmittableThreadLocal.set(mBody);
}
/**
* 获取请求体
*
* @param request 请求
* @return 请求体
*/
private String getBody(HttpServletRequest request) {
return getBodyString(request);
}
/**
* 获取请求体
*
* @return 请求体
*/
public String getBody() {
return mBody;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 创建字节数组输入流
final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes( StandardCharsets.UTF_8));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
/**
* 获取请求Body
*
* @param request
* @return
*/
private String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
推荐阅读
-
Pytorch 实现数据集自定义读取
-
详解ASP.NET Core实现强类型Configuration读取配置数据
-
tensorflow使用range_input_producer多线程读取数据实例
-
Yii框架中用response保存cookie,用request读取cookie的原理解析
-
TFRecord格式存储数据与队列读取实例
-
Python使用Pickle模块进行数据保存和读取的讲解
-
C#从数据库读取数据到DataSet并保存到xml文件的方法
-
php excel reader读取excel内容存入数据库实现代码
-
C# Ado.net实现读取SQLServer数据库存储过程列表及参数信息示例
-
jsp读取数据库实现分页技术简析