一、拦截器与过滤器

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

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

  • Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。

  • Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。

二、过滤器的配置

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

public class LogCostFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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));}@Overridepublic void destroy() {}
}

这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类,这个是Servlet的规范,这个跟以前的Web项目没区别。但是,有了过滤器类以后,以前的web项目可以在web.xml中进行配置,但是spring boot项目并没有web.xml这个文件,那怎么配置?在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:

@Configuration
public class FilterConfig {@Beanpublic 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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));}@Overridepublic 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配置的过滤器。

三、springboot拦截器的配置

上面我们已经介绍了过滤器的配置方法,接下来我们再来看看如何配置一个拦截器。其实spring boot拦截器的配置方式和springMVC差不多,只有一些小的改变需要注意下就ok了。下面主要介绍两种常用的拦截器:

  1. 基于URL实现的拦截器:
public class LoginInterceptor extends HandlerInterceptorAdapter{/*** 在请求处理之前进行调用(Controller方法调用之前)* 基于URL实现的拦截器* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String path = request.getServletPath();if (path.matches(Const.NO_INTERCEPTOR_PATH)) {//不需要的拦截直接过return true;} else {// 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等System.out.println("====================================");return true;}}
}

关键代码:path.matches(Const.NO_INTERCEPTOR_PATH 就是基于正则匹配的url。

/*** @author    BianP* @explain 常量类*/
public class Const {public static final String SUCCESS = "SUCCESS";public static final String ERROR = "ERROR";public static final String FIALL = "FIALL";/**********************对象和个体****************************/public static final String SESSION_USER = "loginedAgent"; // 用户对象public static final String SESSION_LOGINID = "sessionLoginID"; // 登录IDpublic static final String SESSION_USERID = "sessionUserID"; // 当前用户对象ID编号public static final String SESSION_USERNAME = "sessionUserName"; // 当前用户对象ID编号public static final Integer PAGE = 10; // 默认分页数public static final String SESSION_URL = "sessionUrl"; // 被记录的urlpublic static final String SESSION_SECURITY_CODE = "sessionVerifyCode"; // 登录页验证码// 时间 缓存时间public static final int TIMEOUT = 1800;// 秒public static final String ON_LOGIN = "/logout.htm";public static final String LOGIN_OUT = "/toLogout";// 不验证URL anon:不验证/authc:受控制的public static final String NO_INTERCEPTOR_PATH =".*/((.css)|(.js)|(images)|(login)|(anon)).*";
}
  1. 基于注解的拦截器
    ①创建注解:
/*** 在需要登录验证的Controller的方法上使用此注解*/
@Target({ElementType.METHOD})// 可用在方法名上
@Retention(RetentionPolicy.RUNTIME)// 运行时有效
public @interface LoginRequired {}

②创建拦截器:

public class AuthorityInterceptor extends HandlerInterceptorAdapter{@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 如果不是映射到方法直接通过if (!(handler instanceof HandlerMethod)) {return true;}// ①:START 方法注解级拦截器HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();// 判断接口是否需要登录LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);// 有 @LoginRequired 注解,需要认证if (methodAnnotation != null) {// 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等System.out.println("====================================");return true;}return true;}
}
  1. 把拦截器添加到配置中,相当于SpringMVC时的配置文件干的事儿:
/*** 和springmvc的webmvc拦截配置一样* @author BIANP*/
@Configuration
public class WebConfigurer implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录registry.addInterceptor(LoginInterceptor()).addPathPatterns("/**");registry.addInterceptor(AuthorityInterceptor()).addPathPatterns("/**");}@Beanpublic LoginInterceptor LoginInterceptor() {return new LoginInterceptor();}@Beanpublic AuthorityInterceptor AuthorityInterceptor() {return new AuthorityInterceptor();}
}
  1. 注意:
  • 一定要加@Configuration 这个注解,在启动的时候在会被加载。

  • 有一些教程是用的“WebMvcConfigurerAdapter”,不过在spring5.0版本后这个类被丢弃了WebMvcConfigurerAdapter ,虽然还可以用,但是看起来不好。

  • 也有一些教程使用的WebMvcConfigurationSupport,我使用后发现,classpath:/META/resources/,classpath:/resources/,classpath:/static/,classpath:/public/)不生效。具体可以原因,大家可以看下源码因为:WebMvcAutoConfiguration上有个条件注解: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    所以还是建议使用WebMvcConfigurer。

其实springMVC很多东西,都可以搬到springboot中来使用,只需要把配置文件的模式,改成 对应@Configuration 类就好了。

文章转自
文章转自

SpringBoot拦截器与过滤器相关推荐

  1. springboot拦截器与过滤器详解

    前言 不管是传统的ssm项目,还是springboot项目,拦截器和过滤器在项目开发中都离不开,比如说对于ssm框架类的项目来说,许多登录逻辑的前置校验,黑白名单的检查,以及部分请求的数据分析等依然需 ...

  2. springBoot 拦截器与过滤器

    简介 过滤器 依赖于servlet容器.在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次.使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数 ...

  3. SpringBoot 拦截器 过滤器

    1.过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的.请求结束返回也是,是在servlet处理完后,返回给前端之前. 2.拦截器可以获取IOC容器中的各 ...

  4. SpringBoot 拦截器和过滤器

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

  5. 【SpringBoot】SpringBoot拦截器实战和 Servlet3.0自定义Filter、Listener

    =================6.SpringBoot拦截器实战和 Servlet3.0自定义Filter.Listener ============ 1.深入SpringBoot2.x过滤器Fi ...

  6. spring boot 1.5.4 整合redis、拦截器、过滤器、监听器、静态资源配置(十六)

    上一篇:spring boot 1.5.4 整合webService(十五) 1      Spring Boot整合redis和缓存 Spring Boot中除了对常用的关系型数据库提供了优秀的自动 ...

  7. springboot拦截器 跳过_springboot创建拦截器过程图解

    springboot创建拦截器过程图解 这篇文章主要介绍了springboot创建拦截器过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一. ...

  8. Spring Boot实战:拦截器与过滤器

    一.拦截器与过滤器 在讲Spring boot之前,我们先了解一下过滤器和拦截器.这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的.在分析两者的区别之前,我们先理解一下AOP的概念,A ...

  9. springboot + 拦截器 + 注解 实现自定义权限验证

    springboot + 拦截器 + 注解 实现自定义权限验证 最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定 ...

最新文章

  1. AI一分钟|阿里云解释故障原因:触发了一个未知代码Bug;清华蝉联ISC18超算竞赛总冠军...
  2. Python中的collections模块的相关练习
  3. oracle插入时判断重复,Oracle在插入表之前检查重复值
  4. 区块链学堂(3):Solidity
  5. 这 30 个常用的 Maven 命令你必须熟悉
  6. java核心技术-NIO
  7. Html中解决点击 a 标签刷新的问题,实现点击时不刷新
  8. VMware16下载与安装
  9. Java制作验证码的完整代码
  10. 百度网盘青春版未推出前,使用这个网盘高速下载工具
  11. js实现删除页面元素
  12. Unity表情聊天(NGUI图文混排)
  13. 读优美博文了解低风险套利策略
  14. SNN综述(1):深度脉冲神经网络
  15. 浅谈网络安全应急预案
  16. mapboxgl - 用webgl展示海量数据,是否可行?
  17. Generating Images from Captions with Attention
  18. OpenGL 与显卡
  19. MongoDB集群和安全
  20. php生成sn码,PHP 生成SN码

热门文章

  1. java读取pfx或P12格式的个人交换库公私钥
  2. 对于机器学习中,数据增强
  3. python-day01
  4. 【插件开发】—— 1 Eclipse插件开发导盲
  5. 在Tomcat中部署seam工程
  6. 标题要在3~5字之间-三年总结
  7. Python学习笔记: Python 标准库概览二
  8. 使用 xCAT 简化 AIX 集群的部署和管理
  9. Win7如何设置多个IP地址
  10. 深入理解内存(3):内存交换技术,虚拟内存