在spring-boot工程中添加spring mvc拦截器

1. 认识拦截器

Spring MVC的拦截器(Interceptor)不是Filter,同样可以实现请求的预处理、后处理。使用拦截器仅需要两个步骤:

  • 实现拦截器
  • 注册拦截器

1.1 实现拦截器

实现拦截器可以自定义实现HandlerInterceptor接口,也可以通过继承HandlerInterceptorAdapter类,后者是前者的实现类。下面是拦截器的一个实现的例子,目的是判断用户是否登录。如果preHandle方法return true,则继续后续处理。

public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
*预处理回调方法,实现处理器的预处理(如登录检查)。
*第三个参数为响应的处理器,即controller。
*返回true,表示继续流程,调用下一个拦截器或者处理器。
*返回false,表示流程中断,通过response产生响应。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("-------------------preHandle");
// 验证用户是否登陆
Object obj = request.getSession().getAttribute("username");
if (obj == null || !(obj instanceof String)) {
response.sendRedirect(request.getContextPath() + "/index.html");
return false;
}
return true;
}
/**
*当前请求进行处理之后,也就是Controller 方法调用之后执行,
*但是它会在DispatcherServlet 进行视图返回渲染之前被调用。
*此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("-------------------postHandle");
}
/**
*方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。
*这个方法的主要作用是用于进行资源清理工作的。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("-------------------afterCompletion");
}
}

1.2 注册拦截器

为了使自定义的拦截器生效,需要注册拦截器到spring容器中,具体的做法是继承WebMvcConfigurerAdapter类,覆盖其addInterceptors(InterceptorRegistry registry)方法。最后别忘了把Bean注册到Spring容器中,可以选择@Component 或者 @Configuration。

@Component
public class InterceptorConfiguration extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器
InterceptorRegistration ir = registry.addInterceptor(new LoginInterceptor());
// 配置拦截的路径
ir.addPathPatterns("/**");
// 配置不拦截的路径
ir.excludePathPatterns("/**.html");
// 还可以在这里注册其它的拦截器
//registry.addInterceptor(new OtherInterceptor()).addPathPatterns("/**");
}
}

1.3 拦截器的应用场景

拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

  1. 登录验证,判断用户是否登录。
  2. 权限验证,判断用户是否有权限访问资源。
  3. 日志记录,记录请求日志,以便统计请求访问量。
  4. 处理cookie、本地化、国际化、主题等。
  5. 性能监控,监控请求处理时长等。

2. 原理

2.1 工作原理

拦截器不是Filter,却实现了Filter的功能,其原理在于:

  • 所有的拦截器(Interceptor)和处理器(Handler)都注册在HandlerMapping中。
  • Spring MVC中所有的请求都是由DispatcherServlet分发的。
  • 当请求进入DispatcherServlet.doDispatch()时候,首先会得到处理该请求的Handler(即Controller中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。

2.2 拦截器工作流程

一个拦截器,只有preHandle方法返回true,postHandle、afterCompletion才有可能被执行;如果preHandle方法返回false,则该拦截器的postHandle、afterCompletion必然不会被执行。

假设我们有两个拦截器,例如叫Interceptor1和Interceptor2,当一个请求过来,正常的流程和中断的流程分别如下。

2.2.1正常流程
注意两个拦截器在执行preHandle方法和执行postHandle、afterCompletion方法时,顺序是颠倒的。

  1. Interceptor1.preHandle
  2. Interceptor2.preHandle
  3. Controller处理请求
  4. Interceptor2.postHandle
  5. Interceptor1.postHandle
  6. 渲染视图
  7. Interceptor2.afterCompletion
  8. Interceptor1.afterCompletion

2.2.2 中断流程

假设执行Interceptor2.preHandle中报错,那么流程被中断,之前被执行过的拦截器的afterCompletion仍然会执行。在本例中,即执行了Interceptor1.afterCompletion。

1. Interceptor1.preHandle
2. Interceptor2.preHandle
//中间流程被中断,不再执行
3. Interceptor1.afterCompletion

2.3 和Filter共存时的执行顺序

拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter。其顺序如下。

Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2019-06-19

SpringBoot添加自定义拦截器的实现代码

在Controller层时,往往会需要校验或验证某些操作,而在每个Controller写重复代码,工作量比较大,这里在Springboot项目中 ,通过继承WebMvcConfigurerAdapter,添加拦截器. 1.WebMvcConfigurerAdapter源码 /* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the

spring boot如何添加拦截器

构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Application.class, useDefaultFilters = true) public class ServletContextConfig extends WebMvcConfigurationSupport { 为了方便扫描位置,我们可以写一个接口或者入口类Application放置于最外

Spring boot如何基于拦截器实现访问权限限制

遇到一个需求是:要为用户设置不同的菜单.数据访问权限.对于一些特定类型的数据,有的用户可以看有的用户则不可以.一开始没有太多思路,后来一想是不是可以把"特定类型"这个参数通过@PathVariable注解加到路径上,这样就可以通过拦截器拦截后,校验此用户是否可以访问这个路径(类型)下的数据了. 话不多说,以下为具体实践 拦截器配置类 @Configuration public class UserInterceptorConfig { //为了保证IDbnetUserService提前

详解为Angular.js内置$http服务添加拦截器的方法

前言 在Angular框架中,创建团队为使用者进行了Ajax请求的封装,并通过$http服务暴露出相关的接口.Angular在其官方文档中指出, $http服务底层针对Web常见的安全攻击做出了相应的对策,也就是说使用$http服务封装的Ajax为使用者提供了更为安全的保障.作为一个框架,保证框架的可用性,适配性是很有必要的. Angular在设计,实现中也体现出来了这样的良好风格.我们通常在使用Ajax时,有时候希望我们能够在请求发起前或接收到请求后做一些相应的处理工作,比如:在请求发起前,在

Spring MVC中自定义拦截器的实例讲解

1. 引言 拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似于Servlet的Filter. 我们可以让普通的Bean实现HandlerIntercpetor接口或继承HandlerInterceptorAdapter类来实现自定义拦截器. 通过重写WebMvcConfigurerAdapter的addIntercetors方法来注册一个计算每一次请求的处理时间的拦截器. 2. 自定义拦截器的实现 2.1 定义拦截器 新建LogInterceptor类,并继承Ha

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

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

Spring Boot命令行运行器的实现方法

CommandLineRunner是一个带有run方法的简单spring引导接口.Spring Boot启动后将自动调用实现CommandLineRunner接口的所有bean的run方法. Command Line Runner在加载应用程序上下文之后以及Spring Application run方法完成之前执行,相当于你的应用的初始化过程,一般用来实现一些数据预先加载或预先处理. @SpringBootApplication <b>public</b> <b>cl

Spring Boot项目添加外部Jar包以及配置多数据源的完整步骤

前言 最近项目需要和Oracle数据库进行交互,然后我从Maven中央仓库下载数据库驱动jar包,但怎么都下不下来,我到Oracle官网上一看,我去,居然不让用Maven直接下(大学时候用过Oracle,很久远的事情了0rz),没办法我还是直接下载jar包放到我的项目里面吧.SpringBoot项目引入外部jar包是非常方便的,包含打引入外部jar等操作. 我的做法如下: 首先在src同级目录建一个lib文件夹,将第三方jar包放到这个文件内,比如我将ojdbc6.jar 这个jar包放到这个地

详解spring面向切面aop拦截器

spring中有很多概念和名词,其中有一些名字不同,但是从功能上来看总感觉是那么的相似,比如过滤器.拦截器.aop等. 过滤器filter.spring mvc拦截器Interceptor .面向切面编程aop,实际上都具有一定的拦截作用,都是拦截住某一个面,然后进行一定的处理. 在这里主要想着手的是aop,至于他们的比较,我想等三个都一一了解完了再说,因此这里便不做过多的比较. 在我目前的项目实践中,只在一个地方手动显示的使用了aop,那便是日志管理中对部分重要操作的记录. 据我目前所知,ao

spring自定义注解实现拦截器的实现方法

类似用户权限的需求,有些操作需要登录,有些操作不需要,可以使用过滤器filter,但在此使用过滤器比较死板,如果用的话,就必须在配置文件里加上所有方法,而且 不好使用通配符.这里可以采用一种比较简单灵活的方式,是采用spring 的 methodInterceptor拦截器完成的,并且是基于注解的.大概是用法是这样的: @LoginRequired @RequestMapping(value = "/comment") public void comment(HttpServletRe

详解java中spring里的三大拦截器

Filter 新建 TimeFilter @Component public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("time filter init"); } @Override public void doFilter(ServletRequest s