自定义过滤器:
1、首先需要实现 Filter 重写 doFilter 方法
2、doFilter 内部逻辑
2.1、通过 servletRequest 转成 HttpServletRequestWrapper 包装
2.2、通过spring 提供的 StreamUtils 把流信息转成字符串
2.3、过滤链进行继续传递
注意:
filterChain.doFilter 继续传递的request 是自定义的 HttpServletRequestWrapper
因为servletRequest中的流只能读取一次,流中的信息读取是通过offset 位移来读取 经过一次读取后 offset 没有提供接口进行重置(流本身是可以通过reset进行重置的, 但是CoyoteInputStream 这个流是没有提供接口的),所以不能重置无法重复读取
补充: inputStream 提供 三个相关接口 markSupported 是否支持标记默认为false 不支持标记 mark 标记位置 reset 重置到标记位置 进行重复读取
因此 需要自定义 HttpServletRequestWrapper 把数据信息存储 成 byte[] 数组中 ,方便以后重复读取
代码示例:
@Component
@WebFilter(urlPatterns = "/*",filterName = "customFileter")
public class CustomFileter implements Filter {
Logger logger = LoggerFactory.getLogger(CustomFileter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//获取 输入流
CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper((HttpServletRequest) servletRequest);
//流转成字符串
String body = StreamUtils.copyToString(requestWrapper.getInputStream(), Charset.forName(servletRequest.getCharacterEncoding()));
//输出看一下 流中的信息
logger.info(body);
//继续执行过滤链
filterChain.doFilter(requestWrapper,servletResponse);
}
}
自定义 HttpServletRequestWrapper
1、首先需要继承 HttpServletRequestWrapper 在构造函数中把request流存储到 byte[] 数组中,此时 旧的request的流信息已经不能重复读取了
2、重写 getInputStream 方法 把 byte[] 数组转成 新的流 返回 新的 ServletInputStream
3、重写 返回 ServletInputStream 对象中的 read() 方法 需要在 新的流中读取
class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* 定义 byte数组
*/
private final byte[] requestBody;
public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
//把流数据 转到数组保存
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* getInputStream 从byte数组中获取数据转成流
* @return ServletInputStream
*/
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBody);
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 inputStream.read();
}
};
}
}
网友评论