拦截器和过滤器区别_新手能看懂的(Interceptor)和(Filter)区别与使用!
一、拦截器与过滤器
我们先了解一下过滤器和拦截器。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的。在分析两者的区别之前,我们先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。
但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。
而两者的主要区别包括以下几个方面:
- Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
- Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
- Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
二、过滤器的配置
现在我们通过过滤器来实现记录请求执行时间的功能,其实现如下:
public
class
LogCostFilter
implements
Filter
{
@Override
public
void init(FilterConfig filterConfig)
throws
ServletException
{
}
@Override
public
void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain)
throws
IOException,
ServletException
{
long start =
System.currentTimeMillis();
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Execute cost="+(System.currentTimeMillis()-start));
}
@Override
public
void destroy()
{
}
}
这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类,这个是Servlet的规范,这个跟以前的Web项目没区别。
但是,有了过滤器类以后,以前的web项目可以在web.xml中进行配置,但是spring boot项目并没有web.xml这个文件,那怎么配置?在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:
@Configuration
public
class
FilterConfig
{
@Bean
public
FilterRegistrationBean registFilter()
{
FilterRegistrationBean registration =
new
FilterRegistrationBean();
registration.setFilter(new
LogCostFilter());
registration.addUrlPatterns("/*");
registration.setName("LogCostFilter");
registration.setOrder(1);
return registration;
}
}
这样配置就完成了,需要配置的选项主要包括实例化Filter类,然后指定url的匹配模式,设置过滤器名称和执行顺序,这个过程和在web.xml中配置其实没什么区别,只是形式不同而已。现在我们可以启动服务器访问任意URL:
大家可以看到上面的配置已经生效了。除了通过 FilterRegistrationBean 来配置以外,还有一种更直接的办法,直接通过注解就可以完成了:
@WebFilter(urlPatterns =
"/*", filterName =
"logFilter2")
public
class
LogCostFilter2
implements
Filter
{
@Override
public
void init(FilterConfig filterConfig)
throws
ServletException
{
}
@Override
public
void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain)
throws
IOException,
ServletException
{
long start =
System.currentTimeMillis();
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("LogFilter2 Execute cost="
+
(System.currentTimeMillis()
- start));
}
@Override
public
void destroy()
{
}
}
这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。
@SpringBootApplication
@MapperScan("com.pandy.blog.dao")
@ServletComponentScan("com.pandy.blog.filters")
public
class
Application
{
public
static
void main(String[] args)
throws
Exception
{
SpringApplication.run(Application.class, args);
}
}
现在,我们再来访问一下任意URL:
可以看到,我们配置的两个过滤器都生效了。细心的读者会发现,第二个Filter我们并没有指定执行的顺序,但是却在第一个Filter之前执行。这里需要解释一下,@WebFilter这个注解并没有指定执行顺序的属性,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列,并且@WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器。有兴趣的朋友可以自己实验一下。
三、拦截器的配置
上面我们已经介绍了过滤器的配置方法,接下来我们再来看看如何配置一个拦截器。我们使用拦截器来实现上面同样的功能,记录请求的执行时间。首先我们实现拦截器类:
public
class
LogCostInterceptor
implements
HandlerInterceptor
{
long start =
System.currentTimeMillis();
@Override
public
boolean preHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o)
throws
Exception
{
start =
System.currentTimeMillis();
return
true;
}
@Override
public
void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o,
ModelAndView modelAndView)
throws
Exception
{
System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
}
@Override
public
void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o,
Exception e)
throws
Exception
{
}
}
这里我们需要实现HandlerInterceptor这个接口,这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。除了实现上面的接口外,我们还需对其进行配置:
@Configuration
public
class
InterceptorConfig
extends
WebMvcConfigurerAdapter
{
@Override
public
void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(new
LogCostInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
这里我们继承了WebMVCConfigurerAdapter,看过前面的文章的朋友应该已经见过这个类了,在进行静态资源目录配置的时候我们用到过这个类。这里我们重写了addInterceptors这个方法,进行拦截器的配置,主要配置项就两个,一个是指定拦截器,第二个是指定拦截的URL。现在我们再启动系统访问任意一个URL:
可以看到,我们通过拦截器实现了同样的功能。不过这里还要说明一点的是,其实这个实现是有问题的,因为preHandle和postHandle是两个方法,所以我们这里不得不设置一个共享变量start来存储开始值,但是这样就会存在线程安全问题。当然,我们可以通过其他方法来解决,比如通过ThreadLocal就可以很好的解决这个问题,有兴趣的同学可以自己实现。不过通过这一点我们其实可以看到,虽然拦截器在很多场景下优于过滤器,但是在这种场景下,过滤器比拦截器实现起来更简单。
四、总结
本文主要对基于Spring boot对过滤器和拦截器的配置进行的讲解。无论是过滤器还是拦截器都属于AOP(面向切面编程)思想的具体实现。除了这两种实现我们还见过另一种更灵活的AOP实现技术,即Aspect,我们可以通过Aspect来完成更多更强大的功能。这个后续再给大家分享。
如果你对编程感兴趣或者想往编程方向发展,可以关注微信公众号【筑梦编程】,大家一起交流讨论!小编也会每天定时更新既有趣又有用的编程知识!
拦截器和过滤器区别_新手能看懂的(Interceptor)和(Filter)区别与使用!相关推荐
- 详解拦截器和过滤器的区别
拦截器和过滤器的区别 过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对acti ...
- 拦截器和过滤器有什么区别?
首先了解什么是过滤器什么是拦截器 ①过滤器(Filter) 过滤器通过直接实现Filter接口实现,也可以通过@WebFilter注解实现特定的URL拦截 在Filter接口中定义了三个方法: ini ...
- java 拦截器和过滤器的区别
介绍 在 Java Web 应用程序中,拦截器和过滤器是两种不同的机制,用于在请求/响应处理过程中进行拦截和过滤.两者都可以用来在请求到达目标资源之前对其进行预处理.修改或拦截. 但是,拦截器和过滤器 ...
- 区分Java拦截器和过滤器
今天带大家分析java拦截器和过滤器的区别,文中有非常详细的解释说明,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下 一.过滤器(filter) 过滤器处于客户端与Web资源(Serv ...
- struts2中拦截器和过滤器的比较
拦截器和过滤器的区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而 ...
- 【SpringMVC】拦截器和过滤器
拦截器: 拦截器是springmvc中的一种,需要实现HandlerInterceptor接口. 拦截器和过滤器类似,功能方向侧重点不同. 过滤器是用来过滤器请求参数,设置编码字符集等工作. 拦截器是 ...
- 关于SSM框架设置拦截器和过滤器
我们知道拦截器和过滤器都是在项目中起到拦截过滤请求的功能,所以可能在设置的时候会傻傻分不清.这里我们先来比较它们的区别. 过滤器Filter是JavaEE标准,在Servlet的规范中定义的,是Ser ...
- SpringBoot 拦截器和过滤器
拦截器和过滤器 时光飞逝,最近也是很忙,但是忙到最后发现在自己并没有太多的成长 工作 学习 生活 没想到成长是不经意间的,像是被 推着,让你身不由己 午休时间,写写博客,也是保留一些自己的时间和空间 ...
- 拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别
转自:https://www.cnblogs.com/shangc/p/5939708.html 拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别.其主要区别为以下几点: 1)拦截器是基于 ...
最新文章
- 如何建立图像数据矩阵和图像显示灰度之间的关系!_放射技术考试第四章第一节 数字图像的特征...
- 在DataTable中更新、删除数据
- An error occurred during the file system check
- 为什么深度学习几乎成了计算机视觉研究的标配?
- 郁金香汇编代码注入怎么写看雪_雷军1994年写的诗一样的代码,我把它运行起来了!...
- 房子成焦点,被挂马的×××网站仍在增加中
- CentOS单用户模式及进入后只读处理,开机修改为文字界面
- kubespray容器化部署kubernetes高可用集群
- linux lite 3.6 64bit,Linux Lite 3.6 正式发布:基于 Ubuntu 16.04.3 LTS 打造
- C++ 操作sqlite
- 数字逻辑电路学习笔记
- vivado第三方编辑器的使用
- 仿真软件Multisim 10下载地址与破解补丁
- yum安装freeswitch
- Window10 磁盘如何分区(压缩卷操作)
- Idea使用起来反应比较慢
- ebs知识点100题
- CCF大会腾源会专场即将召开,聚焦基础软件与开发语言未来发展
- html表格图片右对齐,更好的方式在HTML表格中右对齐文本
- Python通过MQTT协议上传物联网数据给ThingsBoard
热门文章
- 【ElasticSearch】Es 源码之 LicenseService 源码解读
- 【IDEA】IDEA git log 点击 没有代码变更
- 【Jenkins】Jenkins : jenkins-2.121.1 安装 与 使用
- Spring : Spring事物支持核心接口
- spark学习-Spark算子Transformations和Action使用大全(Transformations章(二))
- 指令include和动作include的区别
- ajax中url是什么意思_装修中的阳台封窗是什么意思?
- 爽到爆!阿里腾讯都在用的API管理神器,API文档、测试、Mock全搞定
- android studio中的适配器,如何在Android Studio中测试回收器视图适配器
- 实验2linux系统使用,操作系统实验答案-实验2Linux的基本操作及vi的使用(答案)