springboot下使用拦截器和过滤器[通俗易懂]

springboot下使用拦截器和过滤器[通俗易懂]1.拦截器InterceptorSpringMVC的拦截器(Interceptor)和Filter不同,但是也可以实现对请求进行预处理,后处理。先介绍它的使用,只需要两步:1.1实现拦截器实现拦截器可以自定义实现HandlerInterceptor接口,也可以通过继承HandlerInterceptorAdapter类,后者是前者的实现类。如果preHandle方法ret…

大家好,又见面了,我是你们的朋友全栈君。

1. 拦截器Interceptor

Spring MVC的拦截器(Interceptor)和Filter不同,但是也可以实现对请求进行预处理,后处理。先介绍它的使用,只需要两步:
1.1 实现拦截器
实现拦截器可以通过继承HandlerInterceptorAdapter类。如果preHandle方法return true,则继续后续处理。

public class InterceptorDemo extends HandlerInterceptorAdapter { 
   


    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { 
   
        StringBuffer requestURL = httpServletRequest.getRequestURL();
        System.out.println("前置拦截器1 preHandle: 请求的uri为:"+requestURL.toString());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { 
   
        System.out.println("拦截器1 postHandle: ");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { 
   
        System.out.println("拦截器1 afterCompletion: ");
    }
}

1.2 注册拦截器
实现拦截器后还需要将拦截器注册到spring容器中,可以通过implements WebMvcConfigurer,覆盖其addInterceptors(InterceptorRegistry registry)方法。记得把Bean注册到Spring容器中,可以选择@Component 或者 @Configuration。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer{ 
   

	 /** * 注册自定义拦截器 */
    @Override
    public void addInterceptors(InterceptorRegistry registry) { 
   
        
       	registry.addInterceptor(new InterceptorDemo2()).addPathPatterns("/**");
        registry.addInterceptor(new InterceptorDemo()).addPathPatterns("/**");
    }
 }

注意这里注册了两个拦截器。这两个拦截器的执行顺序和配置顺序有关系,即先配置顺序就在前(感觉这样不太方便,但没有找到设置类似order的API)。

发起一个请求,在控制台可以看到拦截器生效:

前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle: 
拦截器2 postHandle: 
拦截器1 afterCompletion: 
拦截器2 afterCompletion:

1.3 拦截器的总结
1.3.1 工作原理
一个拦截器,只有preHandle方法返回true,postHandle、afterCompletion才有可能被执行;如果preHandle方法返回false,则该拦截器的postHandle、afterCompletion必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:

  • 所有的拦截器(Interceptor)和处理器(Handler)都注册在HandlerMapping中。
  • Spring MVC中所有的请求都是由DispatcherServlet分发的。
  • 当请求进入DispatcherServlet.doDispatch()时候,首先会得到处理该请求的Handler(即Controller中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。

1.3.2 拦截器工作流程

  • 正常流程:

      	1.Interceptor2.preHandle
      	2.Interceptor1.preHandle
      	3.Controller处理请求
      	4.Interceptor1.postHandle
      	5.Interceptor2.postHandle
      	6.渲染视图view
      	2.Interceptor1.afterCompletion
      	2.Interceptor2.afterCompletion
    
  • 中断流程
    如果在Interceptor1.preHandle中报错或返回false ,那么接下来的流程就会被中断,但注意被执行过的拦截器的afterCompletion仍然会执行。下图为Interceptor1.preHandle返回false的情况:

    前置拦截器2 preHandle: 用户名:null
    前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
    拦截器2 afterCompletion:
    

1.3.3 和Filter共存时的执行顺序
拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter。其顺序如下。

Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter

1.3.4 应用场景
拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

  • 登录验证,判断用户是否登录。
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
  • 处理cookie、本地化、国际化、主题等。
  • 性能监控,监控请求处理时长等。

2. 过滤器Filter

springboot下过滤器的使用有两种形式:
2.1 注解形式
创建一个Filter,并使用WebFilter注解进行修饰,表示该类是一个Filter,以便于启动类进行扫描的时候确认

@WebFilter(urlPatterns = "/*",filterName = "filter2")
public class FilterAnnotationTest implements Filter { 
   

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { 
   
        System.out.println("过滤器2开始初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
   
        System.out.println("过滤器2开始工作");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() { 
   
        System.out.println("过滤器2销毁");
    }
}

然后在启动类上添加注解@ServletComponentScan,该注解用于自动扫描指定包下(默认是与启动类同包下)的WebFilter/WebServlet/WebListener等特殊类。
2.2 代码注册方式
同样编写Filter,但是不添加WebFilter注解,通过@Bean注入spring

public class FilterDemo implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        System.out.println("过滤器开始工作。。"+httpServletRequest.getRequestURL());
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("过滤器开始销毁");
    }
}

然后利用filterRegistrationBean来进行注册。也可以在代码里设置Order

@Configuration
public class FilterDemo { 
   
    @Bean
    @Order(2)
    //spring boot会按照order值的大小,从小到大的顺序来依次过滤
    public FilterRegistrationBean configFilter(){ 
   
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new FilterDemo());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("sessionFilter");
        //filterRegistrationBean.setOrder(2);
        return filterRegistrationBean;
    }
    
}

2.3 过滤器filter和拦截器Interceptor的区别
spring的拦截器和servlet的过滤器有相似之处,都是AOP思想的体现,都可以实现权限检查,日志记录,不同的是

  1. 适用范围不同:Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器的使用范围就大得多
  2. 使用的资源不同:拦截器是属于spring的一个组件,因此可以使用spring的所有资源,对象,如service对象,数据源,事务控制等,而过滤器就不行
  3. 深度不同:Filter还在servlet前后起作用。而拦截器能够深入到方法前后,异常抛出前后,因此拦截器具有更大的弹性,所有在spring框架中应该优先使用拦截器。
    通过调试可以发现,拦截器的执行过程是在过滤器的doFilter中执行的,过滤器的初始化会在项目启动时执行。
过滤器开始工作。。http://localhost:8010/user/353434
前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle: 
拦截器2 postHandle: 
拦截器1 afterCompletion: 
拦截器2 afterCompletion: 
过滤器开始工作。。http://localhost:8010/favicon.ico

可以通过这个博客里的一张图来说明:
这里写图片描述

3. 监听器

监听器的简单使用如下:先编写监听器的实现:

@WebListener
public class WebListenerDemo implements ServletContextListener { 
   


    @Override
    public void contextInitialized(ServletContextEvent sce) { 
   
        System.out.println("监听器初始化。。。。。。。。。。。。");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) { 
   
        System.out.println("监听器销毁。。。。。。。。。。。");
    }
}

监听session创建的监听器(可以用来统计在线人数)

@WebListener
public class SessionListener implements HttpSessionListener { 
   

    @Override
    public void sessionCreated(HttpSessionEvent se) { 
   
        System.out.println("。。。创建session成功");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) { 
   
        System.out.println("。。。销毁session");
    }
}

然后在启动类上添加注解@ServletComponentScan即可,当然也可以注册到spring容器中省却@ServletComponentScan注解。

@Configuration
public class ListenerConfig { 
   
    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean() { 
   
        ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
        slrBean.setListener(new WebListenerDemo());
        return slrBean;
    }

    @Bean
    public ServletListenerRegistrationBean sessionListenerRegistrationBean() { 
   
        ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
        slrBean.setListener(new SessionListener());
        return slrBean;
    }
}


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/160977.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月17日 下午10:00
下一篇 2022年7月17日 下午10:16


相关推荐

  • 安装keil5时,注册机在解压后消失的解决以及使用注册机破解keil5时,无法破解

    安装keil5时,注册机在解压后消失的解决以及使用注册机破解keil5时,无法破解这里写自定义功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入全新的界面设计,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown将代码片显示选择的高亮样式进行展示;增加了图片拖拽功能,你可以

    2022年6月2日
    113
  • qeephp学习

    qeephp学习controller 中调用 find 操作数据库时报错 Deprecated mysql connect Themysqlexte usemysqliorP xampp htdocs qeemaster jingly library db

    2026年3月17日
    2
  • SpringBoot+MyBatisPlus+Thymeleaf+AdminLTE增删改查实战

    SpringBoot+MyBatisPlus+Thymeleaf+AdminLTE增删改查实战说明AdminLTE是网络上比较流行的一款Bootstrap模板,包含丰富的样式、组件和插件,非常适用于后端开发人员做后台管理系统。因为最近又做了个后台管理系统,这次就选的是AdminLTE做主题模板发现效果不错,这里我把最核心的SpringBoot如何集成AdminLTE实现增删改查的源码提供出来,需要的朋友可以参考而少走弯路。实现效果技术选型前端:Thymeleaf+Bootstrap+AdminLTE+插件后端:SpringBoot2.0+Mybatis-Plus数据库:

    2022年7月27日
    15
  • SQL行转列、列转行

    SQL行转列、列转行这个主题还是比较常见的,行转列主要适用于对数据作聚合统计,如统计某类目的商品在某个时间区间的销售情况。列转行问题同样也很常见。一、整理测试数据createtablewyc_test( idint(32)notnullauto_increment, namevarchar(80)defaultnull, datedatedefaultn…

    2022年4月4日
    58
  • Hive系列 (六):Hive数据类型转换

    Hive系列 (六):Hive数据类型转换hive 数据类型转换规则及转换原则 日期类型转换

    2025年8月13日
    7
  • 《大语言模型综述》精读笔记:从入门到实践,手把手教你玩转大模型!

    《大语言模型综述》精读笔记:从入门到实践,手把手教你玩转大模型!

    2026年3月16日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号