服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - JAVA教程 - Spring Boot项目实战之拦截器与过滤器

Spring Boot项目实战之拦截器与过滤器

2021-03-29 09:59liuxiaopeng JAVA教程

这篇文章主要介绍了Spring Boot项目实战之拦截器与过滤器,文中给大家详细介绍了springboot 拦截器和过滤器的基本概念,过滤器的配置,需要的朋友可以参考下

一、拦截器过滤器

在讲spring boot之前,我们先了解一下过滤器和拦截器。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的。在分析两者的区别之前,我们先理解一下aop的概念,aop不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。 但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以aop——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。而两者的主要区别包括以下几个方面:

1、filter是依赖于servlet容器,属于servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。

2、filter的执行由servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。

3、filter的生命周期由servlet容器管理,而拦截器则可以通过ioc容器来管理,因此可以通过注入等方式来获取其他bean的实例,因此使用会更方便。

二、过滤器的配置

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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来完成配置。其实现过程如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
@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:

Spring Boot项目实战之拦截器与过滤器

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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,指定扫描的包。

?
1
2
3
4
5
6
7
8
@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:

Spring Boot项目实战之拦截器与过滤器

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

三、拦截器的配置

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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,该方法通常用于清理资源等工作。除了实现上面的接口外,我们还需对其进行配置:

?
1
2
3
4
5
6
7
8
9
@configuration
public class interceptorconfig extends webmvcconfigureradapter {
 
 @override
 public void addinterceptors(interceptorregistry registry) {
  registry.addinterceptor(new logcostinterceptor()).addpathpatterns("/**");
  super.addinterceptors(registry);
 }
}

 

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

Spring Boot项目实战之拦截器与过滤器

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

四、总结

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

原文链接:http://www.cnblogs.com/paddix/p/8365558.html

延伸 · 阅读

精彩推荐
  • JAVA教程Spring的Ioc模拟实现详细介绍

    Spring的Ioc模拟实现详细介绍

    这篇文章主要介绍了Spring的Ioc模拟实现详细介绍,具有一定参考价值,需要的朋友可以了解下。...

    C_凯7242021-01-29
  • JAVA教程JDBC简介_动力节点Java学院整理

    JDBC简介_动力节点Java学院整理

    什么是JDBC?这篇文章就为大家详细介绍了Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,具有一定的参考价值,感兴趣的小伙伴们可以...

    wuyue2042020-12-04
  • JAVA教程详解Spring中的JavaConfig注解

    详解Spring中的JavaConfig注解

    在开发Java程序,尤其是Java EE应用的时候,总是免不了与各种配置文件打交道。java注解则帮我们使之更整洁,不会配置文件满天飞了。 下面这篇文章主要介...

    搬砖工1812020-08-04
  • JAVA教程SpringBoot2.0集成Swagger2访问404的解决操作

    SpringBoot2.0集成Swagger2访问404的解决操作

    这篇文章主要介绍了SpringBoot2.0集成Swagger2访问404的解决操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    xqnode6452020-09-29
  • JAVA教程多线程死锁的产生以及如何避免死锁方法(详解)

    多线程死锁的产生以及如何避免死锁方法(详解)

    下面小编就为大家带来一篇多线程死锁的产生以及如何避免死锁方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过...

    Java教程网4902020-09-08
  • JAVA教程java多线程下载实例详解

    java多线程下载实例详解

    这篇文章主要介绍了java多线程下载,结合实例形式详细分析了Java多线程文件传输的原理与多线程下载的相关实现技巧,需要的朋友可以参考下 ...

    sgx4250212342572020-03-13
  • JAVA教程通过JDK源码角度分析Long类详解

    通过JDK源码角度分析Long类详解

    这篇文章主要给大家介绍了关于通过JDK源码角度分析Long类的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用long类具有一定的参考学习...

    汪洋之舟---seaboat8282021-02-01
  • JAVA教程Java 泛型有哪些好处详解

    Java 泛型有哪些好处详解

    这篇文章主要介绍了 Java 泛型有哪些好处详解的相关资料,需要的朋友可以参考下...

    Java之家1972020-08-20