美文网首页
spring boot 自定义过滤器

spring boot 自定义过滤器

作者: 只想做个俗人_贪财_好色 | 来源:发表于2022-07-23 21:35 被阅读0次

    自定义过滤器:

    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();
                }
            };
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:spring boot 自定义过滤器

          本文链接:https://www.haomeiwen.com/subject/renbirtx.html