一、拦截器与过滤器

我们先了解一下过滤器和拦截器。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的。在分析两者的区别之前,我们先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。

但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。

而两者的主要区别包括以下几个方面:

  • Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
  • Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
  • Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。

二、过滤器的配置

现在我们通过过滤器来实现记录请求执行时间的功能,其实现如下:

  1. public class LogCostFilter implements Filter {
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  7. long start = System.currentTimeMillis();
  8. filterChain.doFilter(servletRequest,servletResponse);
  9. System.out.println("Execute cost="+(System.currentTimeMillis()-start));
  10. }
  11. @Override
  12. public void destroy() {
  13. }
  14. }

这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类,这个是Servlet的规范,这个跟以前的Web项目没区别。

但是,有了过滤器类以后,以前的web项目可以在web.xml中进行配置,但是spring boot项目并没有web.xml这个文件,那怎么配置?在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:

  1. @Configuration
  2. public class FilterConfig {
  3. @Bean
  4. public FilterRegistrationBean registFilter() {
  5. FilterRegistrationBean registration = new FilterRegistrationBean();
  6. registration.setFilter(new LogCostFilter());
  7. registration.addUrlPatterns("/*");
  8. registration.setName("LogCostFilter");
  9. registration.setOrder(1);
  10. return registration;
  11. }
  12. }

这样配置就完成了,需要配置的选项主要包括实例化Filter类,然后指定url的匹配模式,设置过滤器名称和执行顺序,这个过程和在web.xml中配置其实没什么区别,只是形式不同而已。现在我们可以启动服务器访问任意URL:

大家可以看到上面的配置已经生效了。除了通过 FilterRegistrationBean 来配置以外,还有一种更直接的办法,直接通过注解就可以完成了:

  1. @WebFilter(urlPatterns = "/*", filterName = "logFilter2")
  2. public class LogCostFilter2 implements Filter {
  3. @Override
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. }
  6. @Override
  7. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  8. long start = System.currentTimeMillis();
  9. filterChain.doFilter(servletRequest, servletResponse);
  10. System.out.println("LogFilter2 Execute cost=" + (System.currentTimeMillis() - start));
  11. }
  12. @Override
  13. public void destroy() {
  14. }
  15. }

这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。

  1. @SpringBootApplication
  2. @MapperScan("com.pandy.blog.dao")
  3. @ServletComponentScan("com.pandy.blog.filters")
  4. public class Application {
  5. public static void main(String[] args) throws Exception {
  6. SpringApplication.run(Application.class, args);
  7. }
  8. }

现在,我们再来访问一下任意URL:

可以看到,我们配置的两个过滤器都生效了。细心的读者会发现,第二个Filter我们并没有指定执行的顺序,但是却在第一个Filter之前执行。这里需要解释一下,@WebFilter这个注解并没有指定执行顺序的属性,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列,并且@WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器。有兴趣的朋友可以自己实验一下。

三、拦截器的配置

上面我们已经介绍了过滤器的配置方法,接下来我们再来看看如何配置一个拦截器。我们使用拦截器来实现上面同样的功能,记录请求的执行时间。首先我们实现拦截器类:

  1. public class LogCostInterceptor implements HandlerInterceptor {
  2. long start = System.currentTimeMillis();
  3. @Override
  4. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
  5. start = System.currentTimeMillis();
  6. return true;
  7. }
  8. @Override
  9. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  10. System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
  11. }
  12. @Override
  13. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  14. }
  15. }

这里我们需要实现HandlerInterceptor这个接口,这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。除了实现上面的接口外,我们还需对其进行配置:

  1. @Configuration
  2. public class InterceptorConfig extends WebMvcConfigurerAdapter {
  3. @Override
  4. public void addInterceptors(InterceptorRegistry registry) {
  5. registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**");
  6. super.addInterceptors(registry);
  7. }
  8. }

这里我们继承了WebMVCConfigurerAdapter,看过前面的文章的朋友应该已经见过这个类了,在进行静态资源目录配置的时候我们用到过这个类。这里我们重写了addInterceptors这个方法,进行拦截器的配置,主要配置项就两个,一个是指定拦截器,第二个是指定拦截的URL。现在我们再启动系统访问任意一个URL:

可以看到,我们通过拦截器实现了同样的功能。不过这里还要说明一点的是,其实这个实现是有问题的,因为preHandle和postHandle是两个方法,所以我们这里不得不设置一个共享变量start来存储开始值,但是这样就会存在线程安全问题。当然,我们可以通过其他方法来解决,比如通过ThreadLocal就可以很好的解决这个问题,有兴趣的同学可以自己实现。不过通过这一点我们其实可以看到,虽然拦截器在很多场景下优于过滤器,但是在这种场景下,过滤器比拦截器实现起来更简单。

四、总结

本文主要对基于Spring boot对过滤器和拦截器的配置进行的讲解。无论是过滤器还是拦截器都属于AOP(面向切面编程)思想的具体实现。除了这两种实现我们还见过另一种更灵活的AOP实现技术,即Aspect,我们可以通过Aspect来完成更多更强大的功能。这个后续再给大家分享。

如果你对编程感兴趣或者想往编程方向发展,可以关注微信公众号【筑梦编程】,大家一起交流讨论!小编也会每天定时更新既有趣又有用的编程知识!

拦截器和过滤器区别_新手能看懂的(Interceptor)和(Filter)区别与使用!相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. SpringBoot 拦截器和过滤器

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

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

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

最新文章

  1. 如何建立图像数据矩阵和图像显示灰度之间的关系!_放射技术考试第四章第一节 数字图像的特征...
  2. 在DataTable中更新、删除数据
  3. An error occurred during the file system check
  4. 为什么深度学习几乎成了计算机视觉研究的标配?
  5. 郁金香汇编代码注入怎么写看雪_雷军1994年写的诗一样的代码,我把它运行起来了!...
  6. 房子成焦点,被挂马的×××网站仍在增加中
  7. CentOS单用户模式及进入后只读处理,开机修改为文字界面
  8. kubespray容器化部署kubernetes高可用集群
  9. linux lite 3.6 64bit,Linux Lite 3.6 正式发布:基于 Ubuntu 16.04.3 LTS 打造
  10. C++ 操作sqlite
  11. 数字逻辑电路学习笔记
  12. vivado第三方编辑器的使用
  13. 仿真软件Multisim 10下载地址与破解补丁
  14. yum安装freeswitch
  15. Window10 磁盘如何分区(压缩卷操作)
  16. Idea使用起来反应比较慢
  17. ebs知识点100题
  18. CCF大会腾源会专场即将召开,聚焦基础软件与开发语言未来发展
  19. html表格图片右对齐,更好的方式在HTML表格中右对齐文本
  20. Python通过MQTT协议上传物联网数据给ThingsBoard

热门文章

  1. 【ElasticSearch】Es 源码之 LicenseService 源码解读
  2. 【IDEA】IDEA git log 点击 没有代码变更
  3. 【Jenkins】Jenkins : jenkins-2.121.1 安装 与 使用
  4. Spring : Spring事物支持核心接口
  5. spark学习-Spark算子Transformations和Action使用大全(Transformations章(二))
  6. 指令include和动作include的区别
  7. ajax中url是什么意思_装修中的阳台封窗是什么意思?
  8. 爽到爆!阿里腾讯都在用的API管理神器,API文档、测试、Mock全搞定
  9. android studio中的适配器,如何在Android Studio中测试回收器视图适配器
  10. 实验2linux系统使用,操作系统实验答案-实验2Linux的基本操作及vi的使用(答案)