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

所属分类: 软件编程 / java 阅读数: 20
收藏 0 赞 0 分享

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

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

更多精彩内容其他人还在看

SpringBoot环境搭建及第一个程序运行(小白教程)

这篇文章主要介绍了SpringBoot环境搭建及第一个程序运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

过滤器 和 拦截器的 6个区别(别再傻傻分不清了)

这篇文章主要介绍了过滤器 和 拦截器的 6个区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

SpringBoot整合SpringTask实现定时任务的流程

这篇文章主要介绍了SpringBoot整合SpringTask实现定时任务的流程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

vscode快速引入第三方jar包发QQ邮件

这篇文章主要介绍了vscode快速引入第三方jar包发QQ邮件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Java Enum和String及int的相互转化示例

这篇文章主要介绍了Java Enum和String及int的相互转化示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring boot如何快速的配置多个Redis数据源

这篇文章主要介绍了Spring boot如何快速的配置多个Redis数据源,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

JAVA 对接腾讯云直播的实现

这篇文章主要介绍了JAVA 对接腾讯云直播的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

JavaSE static final及abstract修饰符实例解析

这篇文章主要介绍了JavaSE static final及abstract修饰符实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

SpringBoot定时任务参数运行代码实例解析

这篇文章主要介绍了SpringBoot定时任务运行代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Spring Boot调用 Shell 脚本实现看门狗功能

这篇文章主要介绍了Spring Boot调用 Shell 脚本实现看门狗功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多