zoukankan      html  css  js  c++  java
  • 整合 Springboot 拦截器和过滤器的使用

    Springboot

    1:拦截器(Interceptor)

    java中的拦截器是动态拦截action调用的对象。依赖于web框架,在springmvc中依赖于SpringMVC框架,在实现上基于Java的反射机制,属于AOP的一种应用,作用类似于过滤器,但是拦截器只能对Controller请求进行拦截,对其他的直接访问静态资源的请求无法拦截处理。

    拦截器可以拦截前端请求,定义拦截器需要实现 HandlerInterceptor 接口,然后根据需求重写preHandle,postHandle,afterCompletion三个方法。

    /**
     * 拦截器
     *
     * @program: myspringboot
     * @author: syt
     * @create: 2020-03-05 21:11
     */
    @Component
    @Slf4j
    public class MyInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("前置拦截器****");
            //返回true表示通过请求,返回false表示请求被拦截
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("后置拦截器****");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("拦截器执行完成****");
        }
    }
    复制代码

    想要让自己的拦截器生效需要进行webmvc配置,自定义一个配置类实现WebMvcConfigurer接口,然后重写addInterceptors方法添加需要拦截的路径,JDK1.8以前都是继承于WebMvcConfigurerAdapter然后重新其中的方法,但是JDK1.8支持接口默认方法,官方就定义了可以不用继承WebMvcConfigurerAdapter直接实现WebMvcConfigurer即可。

    **
     * 配置拦截器和过滤器
     *
     * @program: myspringboot
     * @author: syt
     * @create: 2020-03-05 21:16
     */
    @Configuration
    public class MyConfig implements WebMvcConfigurer {
        @Autowired
        private MyInterceptor myInterceptor;
        /**
         * 添加拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //addPa-thPatterns 用于添加拦截规则
            //excludePathPatterns 用于排除拦截
            /*要执行的拦截器*/
            registry.addInterceptor(myInterceptor).
                    addPathPatterns("/**").
                    excludePathPatterns("/**/login", "/**/esProductinfo/**");
        }
    
        /**
         * 解决跨域问题
         * 源(origin)就是协议、域名和端口号。
         * URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口全部相同,
         * 则表示他们同源。否则,只要协议、域名、端口有任何一个不同,就是跨域
         *
         * @param registry
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/*")
                    .allowedOrigins("*")
                    .allowCredentials(true)
                    .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
                    .maxAge(3600);
        }
    
    
    }
    复制代码

    自定义自己的配置类也可以继承WebMvcConfigurationSupport类。这个类有许多默认的配置,但是如果继承了WebMvcConfigurationSupport这个类,SpringBoot的mvc自动装配就好失效,默认配置都需要自己定义,如静态文件地址 /**,需要重新addResourceHandlers方法添加静态文件地址

    /**
     * 配置拦截器和过滤器
     *
     * @program: myspringboot
     * @author: syt
     * @create: 2020-03-05 21:16
     */
    @Configuration
    public class MyConfig extends WebMvcConfigurationSupport {
        @Autowired
        private MyInterceptor myInterceptor;
    
          /**
         * 静态资源
         *
         * @param registry
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
            registry.addResourceHandler("/static/**").addResourceLocations("classpath:/META-INF/resources/static/");
        }
    
        /**
         * 添加拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //addPa-thPatterns 用于添加拦截规则
            //excludePathPatterns 用于排除拦截
            /*要执行的拦截器*/
            registry.addInterceptor(myInterceptor).
                    addPathPatterns("/**").
                    excludePathPatterns("/**/login", "/**/esProductinfo/**");
        }
    
        /**
         * 解决跨域问题
         * 源(origin)就是协议、域名和端口号。
         * URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口全部相同,
         * 则表示他们同源。否则,只要协议、域名、端口有任何一个不同,就是跨域
         *
         * @param registry
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/*")
                    .allowedOrigins("*")
                    .allowCredentials(true)
                    .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
                    .maxAge(3600);
        }
    }
    复制代码

    2:过滤器(filter)

    方式一

    对目标资源的请求和响应进行过滤截取。在请求到达servlet之前,进行逻辑判断,判断是否放行到servlet;也可以在一个响应response到达客户端之前进行过滤,判断是否允许返回客户端。

    定义过滤器需要实现Filter接口

    @Slf4j
    public class MyFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("MyFilter的init方法");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info("MyFilter的doFilter方法");
            //这里可以加一个判断,在过滤器请求不通过时可以返回自己的信息
            if (false) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            } else {
                servletResponse.setContentType("text/html;charset=UTF-8;");
                PrintWriter out = servletResponse.getWriter();
                out.write("过滤器不通过");
                log.info("过滤器不通过");
                out.flush();
                out.close();
                return;
            }
        }
    
        @Override
        public void destroy() {
            log.info("MyFilter的destroy方法");
        }
    }
    复制代码

    想要让过滤器生效需要进行配置

    @Configuration
    public class MyConfig{
      
        /**
         * 添加filter
         *
         * @return
         */
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new MyFilter());
            //该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
            registration.addInitParameter("targetFilterLifecycle", "true");
            registration.setEnabled(true);
            //filter的执行顺序,数字小先执行
            registration.setOrder(1);
            //需要拦截的url路径
            registration.addUrlPatterns("/demand/*", "/notice/*", "/query/*");
            return registration;
        }
    }
    复制代码

    方式二

    可以直接用@WebFilter注解加@Component注解直接就可以创建过滤器了

    @Slf4j
    @Component
    @WebFilter(filterName = "myFilter",urlPatterns = "/*")
    public class MyFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("MyFilter的init方法");
        }
    
        /**
         * 这里是过滤请求的方法
         */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info("MyFilter的doFilter方法");
            if (false) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            } else {
                servletResponse.setContentType("text/html;charset=UTF-8;");
                PrintWriter out = servletResponse.getWriter();
                out.write("过滤器不通过");
                log.info("过滤器不通过");
                out.flush();
                out.close();
                return;
            }
        }
    
        @Override
        public void destroy() {
            log.info("MyFilter的destroy方法");
        }
    }
    复制代码

    感觉拦截器和过滤器很像,都是可以拦截请求做相应的处理。接下来说下他俩的具体区别。

    ①:拦截器是基于java的反射机制,而过滤器基于函数回调。 ②:过滤器依赖于servlet容器,拦截器不依赖于servlet容器。 ③:拦截器只能对action请求起作用,而过滤器几乎对所有的请求都起作用。 ④:拦截器可以访问action上下文,值栈里的对象,而过滤器不能。 ⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。 ⑥:拦截器可以获取IOC容器中的各个bean,而过滤器就不行,(在拦截器里注入一个service,可以调用业务逻辑)。 ⑦:过滤器是在请求进入容器后,但进入servlert前进行预处理的。响应请求也是,在servlet处理结束后,返回给客户端前触发。而拦截器提供了三个方法支持(1)preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现); 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。 afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。

    码云地址:gitee.com/sytsuccess/…

    参考链接:blog.csdn.net/u013806366/…


    作者:着迷。
    链接:https://juejin.im/post/5e639f33f265da570829f63c
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    operamasks—omMessageBox的使用
    operamasks-omGrid的使用
    SQL Server转sqlite数据库
    operamasks—omMessageTip的使用
    operamasks—omBorderLayout布局
    选择器(E:hover/E:active/E:focus的使用)
    CSS3(各UI元素状态伪类选择器受浏览器的支持情况)
    选择器的使用(nth-of-type和nth-last-of-type选择器)
    选择器的使用(nth-child和nth-last-child选择器)
    选择器的使用(first-child和last-child选择器)
  • 原文地址:https://www.cnblogs.com/aishangJava/p/12444631.html
Copyright © 2011-2022 走看看