背景,这边有一个需求,前端跟后端之间有一个网闸,网闸只接收Post请求,json格式的数据,而且不能转发cookie跟headers,这就只能把token放在路径上或者是请求体中,我这里是把token放在请求体中,我在后端request里使用它的inputstream,后发现spring在对参数进行解析的时候再获取时,取不到请求参数。这个原因就是inputstream是只能读一次。处理方法:通过request增加器,复制请求的方式,这是网上找到的方法,可以解决这个问题,再这里记录一下。
/**
* desc 请求参数增强器
* date 2022/9/6 9:34
* @author fmk
*/
public class RequestBodyWrapper extends HttpServletRequestWrapper {
/**
* 定义字节数组, 缓存请体信息
*/
private final byte[] requestBody;
public RequestBodyWrapper(HttpServletRequest request) throws IOException {
super(request);
// 复制请求体
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
/**
* desc 重写获取request请求的输入流方法, 从复制的字节数组中获取
* date 2022/9/6 9:40
* @author fmk
* @return {@link ServletInputStream}
*/
@Override
public ServletInputStream getInputStream(){
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public int read(){
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
/**
* desc 重写获取缓冲字符输入流的方法, 从复制的字节数组中获取
* date 2022/9/6 9:40
* @author fmk
* @return {@link BufferedReader}
*/
@Override
public BufferedReader getReader(){
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}
过滤器如下:
package com.example.appspringboot.cache;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
@Order(1)
public class RequestBodyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if(servletRequest instanceof HttpServletRequest){
filterChain.doFilter(new RequestBodyWrapper((HttpServletRequest) servletRequest), servletResponse);
}else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
操作这两步可以了。