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

一、拦截器与过滤器

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

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

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

3、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来完成更多更强大的功能。这个后续再给大家分享。

(0)

相关推荐

  • SpringBoot拦截器实现登录拦截的方法示例

    源码 GitHub:https://github.com/291685399/springboot-learning/tree/master/springboot-interceptor01 SpringBoot拦截器可以做什么 可以对URL路径进行拦截,可以用于权限验证.解决乱码.操作日志记录.性能监控.异常处理等 SpringBoot拦截器实现登录拦截 pom.xml: <?xml version="1.0" encoding="UTF-8"?> &

  • 解决Spring boot2.0+配置拦截器拦截静态资源的问题

    第一次遇到这个问题的时候,简直是一脸蒙逼,写了一个拦截器以后,静态资源就不能访问了,到处查找才知道是版本问题 解决办法: 第一步:定义一个类实现 实现WebMvcConfigurer的类中拦截器中添加放行资源处添加静态资源文件路径: @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(sessionInterceptor).addPathPatterns("/&

  • Spring Boot项目中定制拦截器的方法详解

    这篇文章主要介绍了Spring Boot项目中定制拦截器的方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Servlet 过滤器属于Servlet API,和Spring关系不大.除了使用过滤器包装web请求,Spring MVC还提供HandlerInterceptor(拦截器)工具.根据文档,HandlerInterceptor的功能跟过滤器类似,但拦截器提供更精细的控制能力:在request被响应之前.request被响应之后.视

  • 详谈springboot过滤器和拦截器的实现及区别

    前言 springmvc中有两种很普遍的AOP实现: 1.过滤器(Filter) 2.拦截器(Interceptor) 本篇面对的是一些刚接触springboot的人群 所以主要讲解filter和interceptor的简单实现和它们之间到底有什么区别 (一些复杂的功能我会之后发出文章,请记得关注) Filter的简单实现 字面意思:过滤器就是过滤的作用,在web开发中过滤一些我们指定的url 那么它能帮我们过滤什么呢? 那功能可就多了: 比如过拦截掉我们不需要的接口请求 修改请求(reques

  • SpringBoot的拦截器中依赖注入为null的解决方法

    该项目是基于SpringBoot框架的Maven项目. 今天在拦截器中处理拦截逻辑时需要使用注解调用其他方法 并且要从配置文件中读取参数.所以我使用了以下注解: @Reference CoreRedisService redisService; @Value("${channel}") private String channel; @Value("${allowMethod}") private String allowMethod; 一个是获取接口的引用,两外两

  • Spring Boot配置拦截器及实现跨域访问的方法

    拦截器功能强大,能够深入方法前后,常应用于日志记录.权限检查和性能检测等,几乎是项目中不可或缺的一部分,本文就来实现Spring Boot自定义拦截器的配置. 理论指导 问:Spring Boot怎么配置拦截器? 答:配置一个拦截器需要两步完成. 自定义拦截器,实现HandlerInterceptor这个接口.这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是

  • SpringBoot快速设置拦截器并实现权限验证的方法

    一.概述 拦截器的使用场景越来越多,尤其是面向切片编程流行之后.那通常拦截器可以做什么呢? 之前我们在Agent介绍中,提到过统计函数的调用耗时.这个思路其实和AOP的环绕增强如出一辙. 那一般来说,场景如下: 函数增强:比如对一个函数进行参数检查,或者结果过滤等.甚至可以对函数就行权限认证. 性能监控:统计函数性能. 日志打点:比如在用户登录函数之前,打点统计PV等信息. 以及其他等等. 二.Spring的拦截器 无论是SpringMVC或者SpringBoot中,关于拦截器不得不提: org

  • 详解SpringBoot 解决拦截器注入Service为空问题

    一.自定义拦截器实现 HandlerInterceptor 接口 /** * * Created by zhh on 2018/04/20. */ public class MyInterceptor implements HandlerInterceptor { @Autowired private NetworkProxyInfoService networkProxyInfoService; @Override public void afterCompletion(HttpServlet

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

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

  • Spring boot项目中异常拦截设计和处理详解

    背景: 项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连通性问题,db等服务器出现的网络抖动或宕机 无论是分析设计.开发.测试.线上都需要能够准确定位问题并制定解决方案. 目的: 规范化异常的处理过程,避免异常被吞和到处都在捕获异常的情况 准确的反馈异常信息,为定位问题提供依据 通用性异常全局处理,降低业务开发关注度 对异常情况进行预警,以便能够及时响应

  • Spring Boot项目抵御XSS攻击实战过程

    目录 前言 一.什么是XSS攻击 二.如何抵御XSS攻击 三.实现抵御XSS攻击 总结 前言 作为Web网站来说,抵御XSS攻击是必须要做的事情,这是非常常见的黑客攻击手段之一. 一.什么是XSS攻击 XSS意思是跨站脚本攻击,英文全称Cross Site Scripting,为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS. XSS攻击的手段很简单,就是通过各种手段向我们的Web网站植入JS代码.比如说普通网站的用户注册.论坛

  • Spring Boot 项目设置网站图标的方法

    正常情况下,每个网站都会有一个对应的网站图标(Favicon),在浏览器访问网站时,对应的浏览器标签上会出现对应的图标.如下图百度的图标: 对此Spring Boot项目也提供了支持,但不同版本有所区别,在最新版本中的使用,网络上大多数文章已经失效,本篇文章带大家看一下Spring Boot 2.x版本中的使用情况. Spring Boot不同版本对Favicon的支持 在早些版本中Spring Boot对Favicon进行了默认支持,并且通过如下配置进行关闭操作: spring.mvc.fav

  • Spring Boot项目传参校验的最佳实践指南

    目录 场景还原 神注解加持 数据异常统一拦截 总结 场景还原 简单业务场景模拟: 假如你现在在做一个成绩录入系统,你愉快地用Spring Boot框架写了一个后台接口,用于接收前台浏览器传过来的 Student对象,并插入后台数据库. 我们将传入的 Student对象定义为: public class Student { private String name; // 姓名 private Integer score; // 考试分数(满分100分) private String mobile;

  • mybatis实战之拦截器解读

    目录 mybatis实战之拦截器 1.使用方法 2.需要注意的地方 拦截器的执行顺序 与常用插件的整合遇到的问题 可以提升的点 总结 mybatis实战之拦截器 在服务的开发过程中,往往存在这样的需求,针对业务,实现对数据库操作语句做统一的处理. 比如对某些敏感数据如用户姓名.手机号等坐脱敏处理保存和查询.对未实现权限的查询通过添加关联查询实现权限控制查询结果等等. 这时,mybatis框架提供了拦截器的方式,允许在映射语句执行过程中的某一点进行拦截调用,进行自己的业务处理. 1.使用方法 这里

  • ssm项目改造spring boot项目完整步骤

    目录 添加依赖 添加启动类 拷贝项目代码 配置数据库连接池 添加依赖 连接池的自动配置方式 配置 Druid 连接池 集成 MyBatis 添加依赖 配置 Mapper 对象 MyBatis配置属性 事务管理 添加依赖 注解方式 配置切换代理 测试验证 集成 Web 添加依赖 修改端口 目录结构 静态资源的一些处理 前端控制器映射路径配置 集成 Thymeleaf 添加依赖 相关配置 修改模板文件 统一异常处理 框架自带方式 控制器增强器方式 添加注册多个拦截器 系统日志 为什么要用日志 Spr

  • 详解如何在Spring Boot项目使用参数校验

    开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空,非null,整数值的范围,字符串的个数,日期,邮箱等等.最常见的就是我们直接写代码校验,这样以后比较繁琐,而且不够灵活. Bean Validation 1.0(JSR-303)是一个校验规范,在spring Boot项目由于自带了hibernate validator 5(http://hibernate.org/validator/)实现,所以我们可以非常方便的使用这个特性 . 核心的pom依赖:

  • Spring Boot项目利用Redis实现session管理实例

    在现代网络服务中,session(会话)不得不说是非常重要也是一定要实现的概念,因此在web后台开发中,对session的管理和维护是必须要实现的组件.这篇文章主要是介绍如何在Spring Boot项目中加入redis来实现对session的存储与管理. 1. 利用Spring Initializr来新建一个spring boot项目 2. 在pom.xml中添加redis和session的相关依赖.项目生成的时候虽然也会自动生成父依赖,但是1.5.3版本的spring boot的redis相关

随机推荐