SpringBoot之HandlerInterceptorAdapter

 

在SpringBoot中我们可以使用HandlerInterceptorAdapter这个适配器来实现自己的拦截器。这样就可以拦截所有的请求并做相应的处理。

应用场景

  • 日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
  • 权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
  • 性能监控:典型的是慢日志。

在HandlerInterceptorAdapter中主要提供了以下的方法:
preHandle:在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true,则继续调用下一个拦截器。如果返回false,则中断执行,也就是说我们想调用的方法 不会被执行,但是你可以修改response为你想要的响应。
postHandle:在方法执行后调用。
afterCompletion:在整个请求处理完毕后进行回调,也就是说视图渲染完毕或者调用方已经拿到响应。

在HandlerInterceptorAdapter中主要提供了以下的方法:

  • preHandle:在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true,则继续调用下一个拦截器。如果返回false,则中断执行,也就是说我们想调用的方法 不会被执行,但是你可以修改response为你想要的响应。
  • postHandle:在方法执行后调用。
  • afterCompletion:在整个请求处理完毕后进行回调,也就是说视图渲染完毕或者调用方已经拿到响应。

HandlerInterceptor

拦截器适配器HandlerInterceptorAdapter

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

   /**
* This implementation always returns {@code true}.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { return true;
} /**
* This implementation is empty.
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
} /**
* This implementation is empty.
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
} /**
* This implementation is empty.
*/
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
} }

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器(种适配器设计模式的实现),允许我们只实现需要的回调方法。
这样在我们业务中比如要记录系统日志,日志肯定是在afterCompletion之后记录的,否则中途失败了,也记录了,那就扯淡了。一定是程序正常跑完后,我们记录下那些对数据库做个增删改的操作日志进数据库。所以我们只需要继承HandlerInterceptorAdapter,并重写afterCompletion一个方法即可,因为preHandle默认是true。

运行流程总结如下:

  1. 拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。
  2. 会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。
  3. 然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。
  4. 在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)

下面用一个demo来演示执行流程

定义一个类继承HandlerInterceptorAdapter,并重写方法

快捷键ctrl+o打开可以重写的方法面板选择

package com.example.demo.config;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LogInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("================================== preHandle1 ===========================================");
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.err.println("================================== postHandle1 ===========================================");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.err.println("================================== afterCompletion1 ===========================================");
} }

WebMvcConfigurerAdapter 抽象类是对WebMvcConfigurer接口的简单抽象(增加了一些默认实现),但在在SpringBoot2.0及Spring5.0中WebMvcConfigurerAdapter已被废弃 。官方推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport

实现WebMvcConfigurer配置拦截器

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
public class WebConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
}
}

在控制器中写一个方法并访问

@ApiOperation(value = "test mybatis", notes = "")
@RequestMapping(value = "getuser", method = RequestMethod.GET)
public User getUser() {
return userService.getUser();
}

会在控制台输出

此时在加入一个拦截器,会按照配置的顺序执行,配置如下

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
public class WebConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
registry.addInterceptor(new LogInterceptor2());
}
}

控制的输出反映了配置多个拦截器的执行流程:

如果controller出现异常,则不会继续执行postHandle,只会倒序执行afterCompletion方法

转载地址:https://www.cnblogs.com/weianlai/p/11358768.html

最新文章

  1. Typecast 免费了!献给设计师们的礼物
  2. Android布局中涉及的一些属性
  3. JRebel_修改class后无法正确调试问题解决【2014-03-12】
  4. Hdu1108(最小公倍数)
  5. HDU 4739 求正方形个数
  6. 调试设置移动端Web开发环境搭建实践
  7. adb不是内部或外部命令
  8. [js高手之路]深入浅出webpack教程系列7-( babel-loader,css-loader,style-loader)的用法
  9. HDU3507 Print Article (斜率优化DP基础复习)
  10. JavaScript 优雅简单的拼接字符串
  11. PHP的性能优化方法总结
  12. Http读书笔记1-5章
  13. 浅谈JavaScript的函数的call以及apply
  14. docker 网络配置
  15. matplotlib坐标轴的一些操作
  16. 如何使用bootstrap框架
  17. 使用TensorFlow实现分类
  18. [django]cbv方式
  19. 海康抓拍机SDK开发
  20. 1207. [HNOI2004]打鼹鼠【线性DP】

热门文章

  1. AtCoder Beginner Contest 182 F
  2. Bzoj通过5题纪念
  3. 手把手从0到1:搭建Kubernetes集群
  4. Linux usb 6. HC/UDC 测试
  5. 将 ASP.Net Core WebApi 应用打包至 Docker 镜像
  6. 菜鸟Markdown笔记,看这个就够了
  7. dart系列之:dart类中的构造函数
  8. 8大原则带你秒懂Happens-Before原则
  9. 站长管理服务器必读:Ftp、Ftps与Sftp三兄弟的不同与区别以及部署全指引
  10. [luogu7476]苦涩