美文网首页Java WebSpring-BootSpring Boot
spring boot 添加自定义监听器、过滤器、拦截器

spring boot 添加自定义监听器、过滤器、拦截器

作者: VincentPeng | 来源:发表于2018-01-26 20:13 被阅读250次

    场景1:需要项目启动的时候把数据加载到缓存中去 使用:监听器

    1.自定义listenner类 添加@WebListener 实现ServletContextListener


    一个注解 一个实现

    2.重写contextInitialized方法

        @Override
        public void contextInitialized(ServletContextEvent sce) {
    
      //当服务启动时候的业务逻辑
    
        }
    

    3.在启动类添加注解扫描
    @EnableScheduling
    @ServletComponentScan


    指定扫描类

    场景2:在Rest接口中,在拦截器位置判断请求体的参数是否签名符合规范,符合放行在handler中进行业务逻辑的处理,不符合直接不进行响应 使用:过滤器+拦截器

    这类功能有一些点还是需要注意的

    • 过滤器请求被处理前调用一次,拦截器可以调用多次
    • 过滤器无法直接响应请求
    • 过滤器和拦截器中httpServletRequest中getInputStream()只可读取一次,无法重复读取

    想要在拦截器中读取输入流之后,handler依旧可以再次读取输入流需要在过滤器中读取inputStream,之后缓存起来,然后包装httpServletRequest;重写其中getInputStream()方法去拿缓存数据,就可以满足在拦截器处理getInputStream之后,handler依旧可以从httpServletRequest中拿到数据

    1.过滤器处理

    //过滤顺序
    @Order(1)
    //过滤器配置
    @WebFilter(filterName = "xxxRequestFilter", urlPatterns = "/path/*")
    public class xxxRequestFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
            if (!(request instanceof ApiRequestWrapper)) {
    //XXXRequestWrapper是HttpServletRequest包装类
                XXXRequestWrapper xxxRequestWrapper = new XXXRequestWrapper((HttpServletRequest) request);
                chain.doFilter(xxxRequestWrapper, response);
                return;
            }
            chain.doFilter(request,response);
        }
        @Override
        public void destroy() {
    
        }
    }
    

    2.XXXRequestWrapper包装HttpServletRequest 缓存数据

    public class XXXRequestWrapper extends HttpServletRequestWrapper {
        
        private byte[] rawData;
        private HttpServletRequest request;
        private ResettableServletInputStream servletStream;
    
        public XXXRequestWrapper(HttpServletRequest request) {
            super(request);
            this.request = request;
            this.servletStream = new ResettableServletInputStream();
    
        }
    
    
        public void resetInputStream() {
            servletStream.stream = new ByteArrayInputStream(rawData);
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
            if (rawData == null) {
                rawData = readBytes(request).getBytes(Charset.forName("UTF-8"));
                servletStream.stream = new ByteArrayInputStream(rawData);
            }
            return servletStream;
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            if (rawData == null) {
                rawData = readBytes(request).getBytes(Charset.forName("UTF-8"));
                servletStream.stream = new ByteArrayInputStream(rawData);
            }
            return new BufferedReader(new InputStreamReader(servletStream));
        }
    
    
        private class ResettableServletInputStream extends ServletInputStream {
    
            private InputStream stream;
    
            @Override
            public int read() throws IOException {
                return stream.read();
            }
    
            @Override
            public boolean isFinished() {
                return false;
            }
    
            @Override
            public boolean isReady() {
                return false;
            }
    
            @Override
            public void setReadListener(ReadListener listener) {
    
            }
        }
        private String readBytes(HttpServletRequest request){
            StringBuilder sb = new StringBuilder();
            InputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = request.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("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();
        }
    
        public String getBodyString() {
            try {
                return new String(rawData, "UTF-8");
            } catch (UnsupportedEncodingException ex) {
                return new String(rawData);
            }
        }
     
    }
    

    3.拦截器Interceptor

    @Component
    public class XXXRequestInterceptor implements HandlerInterceptor {
        protected Logger log = LoggerFactory.getLogger(getClass());
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
    
             if (httpServletRequest instanceof XXXRequestWrapper) {
                 XXXRequestWrapper xxxRequestWrapper = (XXXRequestWrapper) httpServletRequest;
              //使用getInputStream 不影响后续的处理器获取请求体中的数据
                 xxxRequestWrapper.getInputStream();
                  log.info("校验成功 ");
                 }catch (Exception e) {
                     log.error("请求校验失败 ");
                     return false;
                 }
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
        }
    }
    
    

    4.其他配置

    拦截器不需要单独添加注解,在类上添加@Component即可
    过滤器需要在启动类上配置

    @ServletComponentScan(basePackageClasses={xxx.xxxRequestFilter.class})
    

    相关文章

      网友评论

        本文标题:spring boot 添加自定义监听器、过滤器、拦截器

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