文章目录

  • 1. 拦截器Interceptor
  • 2. 过滤器Filter
  • 3. 监听器

1. 拦截器Interceptor

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

public class InterceptorDemo extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {StringBuffer requestURL = httpServletRequest.getRequestURL();System.out.println("前置拦截器1 preHandle: 请求的uri为:"+requestURL.toString());return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println("拦截器1 postHandle: ");}@Overridepublic 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{/*** 注册自定义拦截器*/@Overridepublic 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.preHandle2.Interceptor1.preHandle3.Controller处理请求4.Interceptor1.postHandle5.Interceptor2.postHandle6.渲染视图view2.Interceptor1.afterCompletion2.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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器2开始初始化");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("过滤器2开始工作");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("过滤器2销毁");}
}

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

public class FilterDemo implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;System.out.println("过滤器开始工作。。"+httpServletRequest.getRequestURL());filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic 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 {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("监听器初始化。。。。。。。。。。。。");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("监听器销毁。。。。。。。。。。。");}
}

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

@WebListener
public class SessionListener implements HttpSessionListener {@Overridepublic void sessionCreated(HttpSessionEvent se) {System.out.println("。。。创建session成功");}@Overridepublic void sessionDestroyed(HttpSessionEvent se) {System.out.println("。。。销毁session");}
}

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

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

springboot下使用拦截器和过滤器相关推荐

  1. SpringBoot 拦截器和过滤器

    拦截器和过滤器 时光飞逝,最近也是很忙,但是忙到最后发现在自己并没有太多的成长 工作 学习 生活 没想到成长是不经意间的,像是被 推着,让你身不由己 午休时间,写写博客,也是保留一些自己的时间和空间 ...

  2. 区分Java拦截器和过滤器

    今天带大家分析java拦截器和过滤器的区别,文中有非常详细的解释说明,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下 一.过滤器(filter) 过滤器处于客户端与Web资源(Serv ...

  3. 关于SSM框架设置拦截器和过滤器

    我们知道拦截器和过滤器都是在项目中起到拦截过滤请求的功能,所以可能在设置的时候会傻傻分不清.这里我们先来比较它们的区别. 过滤器Filter是JavaEE标准,在Servlet的规范中定义的,是Ser ...

  4. 详解拦截器和过滤器的区别

    拦截器和过滤器的区别 过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对acti ...

  5. java 拦截器和过滤器的区别

    介绍 在 Java Web 应用程序中,拦截器和过滤器是两种不同的机制,用于在请求/响应处理过程中进行拦截和过滤.两者都可以用来在请求到达目标资源之前对其进行预处理.修改或拦截. 但是,拦截器和过滤器 ...

  6. 拦截器和过滤器有什么区别?

    首先了解什么是过滤器什么是拦截器 ①过滤器(Filter) 过滤器通过直接实现Filter接口实现,也可以通过@WebFilter注解实现特定的URL拦截 在Filter接口中定义了三个方法: ini ...

  7. 拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别

    转自:https://www.cnblogs.com/shangc/p/5939708.html 拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别.其主要区别为以下几点: 1)拦截器是基于 ...

  8. struts2中拦截器和过滤器的比较

    拦截器和过滤器的区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而 ...

  9. 【SpringMVC】拦截器和过滤器

    拦截器: 拦截器是springmvc中的一种,需要实现HandlerInterceptor接口. 拦截器和过滤器类似,功能方向侧重点不同. 过滤器是用来过滤器请求参数,设置编码字符集等工作. 拦截器是 ...

  10. 【SpringMVC】自定义拦截器和过滤器

    一.闲话 五一假期明天结束了,咬咬牙把SpringMVC结束掉 二.基本要点 1.过滤器 除了之前我们提到的spring提供的过滤器之外,我们还可以自定义过滤器,使用步骤如下 编写java类实现Fil ...

最新文章

  1. 基于模型(Model-based)进行特征选择(feature selection)并可视化特征重要性(feature importance)
  2. 编程能力差!90%输在这点上!谷歌AI专家:其实都是瞎努力!
  3. mysql数据库定点任务_MySQL数据库Event定时执行任务详解
  4. fprintf/fscanf函数分析
  5. 2019年1月数据库流行度排行: PostgreSQL蝉联2018年度冠军
  6. Android onClick()单机监听2种方式
  7. Flink 集群搭建
  8. Facebook提高工作效率的秘密 ,值得收藏
  9. mysql用alter创建外键_MySQL入门(alter语法 与 外键)
  10. 最小二乘法以及正交最小二乘(OLS)的推导与简单比较
  11. 给机器人罗宾写一封英语回信_人教版5年级英语unit1知识
  12. 左连接 oracle条件查询,sql 左连接查询条件and与where
  13. Spring的装配方式
  14. Words Accumlation - Day 4
  15. 程序 数列求和 c语言,[编程入门]有规律的数列求和-题解(C语言代码)
  16. Windows下PostgreSQL 8.1版安装图解
  17. 【UE】BUILD ERROR: Missing precompiled manifest for ‘****‘.
  18. 动态规划-类数塔问题(在一个n* m的方格中,m为奇数,放置有n*m个数)
  19. linux oracle 查看版本
  20. 线性表的顺寻存储结构

热门文章

  1. html超链接块状,超链接伪类
  2. 软件工程实践: 敏捷开发流程图(scrum)
  3. 【代码之路】我和代码的这两年,一路风雨,终见彩虹
  4. 搭建 Harbor v2.2.0 docker私库
  5. Json数据转化为DataTable的两种方法(vb.net)
  6. 【Java】URL下载网络资源(CloudMusic)
  7. Win7 Hotfix KB2685811 (64-bit)疑难杂症状之解药
  8. TCP和UDP的区别
  9. 神推荐:西瓜导航你值得拥有
  10. Coremail邮件安全:2022重保最新钓鱼案件典型攻击手法复盘