我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复【资料】,即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板。

HandlerInterceptor 详解

HandlerInterceptor 允许定制 handler 处理器执行链的工作流接口。我们可以自定义拦截器用于拦截 handlers 处理器(你可以理解为 controller 层的接口),从而可以添加一些共同的重复性的处理行为(例如接口鉴权,接口日志记录,性能监控等),而不用修改每一个 handler 的实现。

注意,此基于 SpringBoot 2.3.12.RELEASE 版本讲解。

HandlerInterceptor 接口只有三个默认空实现方法,在低版本中这三个方法不是默认方法,而是抽象方法。

public interface HandlerInterceptor {

	default boolean preHandle(HttpServletRequest request, HttpServletResponse response,                 Object handler) throws Exception {
return true;
} default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
} default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}

这三个方法的执行顺序图如下:

preHandle

preHandle 前置处理,拦截一个处理器(handler)的执行,preHandle 方法会在 HandlerMapping 确定一个适当的处理器对象之后,但在 HandlerAdapter 调用处理器之前被调用。可以简单理解为 controller 接口被调用之前执行。

Intercepter 是链式的,就是一个接着一个执行。如果此方法返回 true,则会执行下一个拦截器或者直接执行处理器。如果此方法返回 false 或者抛出异常则终止执行链,也不再调用处理器。

注意,此方法如果不返回 true,那么 postHandleafterCompletion 不会被执行。

那这个方法有什么用呢?其实可以做一些接口被调用前的预处理,例如用户权限校验。

package com.chenpi;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor; /**
* @Description 用户权限验证拦截
* @Author 陈皮
* @Date 2021/6/27
* @Version 1.0
*/
@Component
public class UserPermissionInterceptor implements HandlerInterceptor { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; // 获取用户权限校验注解
UserAuthenticate userAuthenticate =
handlerMethod.getMethod().getAnnotation(UserAuthenticate.class);
if (null == userAuthenticate) {
userAuthenticate = handlerMethod.getMethod().getDeclaringClass()
.getAnnotation(UserAuthenticate.class);
}
if (userAuthenticate != null && userAuthenticate.permission()) {
// 验证用户信息
UserContext userContext = userContextManager.getUserContext(request);
if (null == userContext) {
return false;
}
}
}
return true;
}
}

postHandle

postHandle 后置处理,会在 HandlerAdapter 调用处理器之后,但在 DispatcherServlet 渲染视图之前被调用。可以在此对 ModelAndView 做一些额外的处理。可以简单理解为 controller 接口被调用之后执行。

注意,此方法在执行链中的执行顺序是倒着执行的,即先声明的拦截器后执行。

afterCompletion

afterCompletion 完成之后,在请求处理完之后被执行,也就是渲染完视图之后。一般用于做一些资源的清理工作,配合 preHandle 计算接口执行时间等。

注意,和 postHandle 一样,此方法在执行链中的执行顺序也是倒着执行的,即先声明的拦截器后执行。

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable Exception ex) {
// 请求完后,清除当前线程的用户信息
UserContextHolder.removeUserContext();
}

注册拦截器

注意,我们自定义的拦截器要通过 WebMvcConfigurer 的实现类进行注册,才能生效。

package com.yzj.ehr.common.config;

import com.yzj.ehr.common.context.UserContextResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.yzj.ehr.common.interceptor.UserPermissionInterceptor; /**
* @Description 注册拦截器
* @Author 陈皮
* @Date 2021/6/27
* @Version 1.0
*/
@Component
public class WebAppConfigurer implements WebMvcConfigurer { private UserPermissionInterceptor userPermissionInterceptor; public WebAppConfigurer(final UserPermissionInterceptor userPermissionInterceptor) {
this.userPermissionInterceptor = userPermissionInterceptor;
} @Override
public void addInterceptors(InterceptorRegistry registry) {
// 匹配所有接口,排除/base/test接口
registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/**")
.excludePathPatterns("/base/test");
}
}

SpringBoot 拦截器妙用,让你一个人开发整个系统的鉴权模块!的更多相关文章

  1. Java结合SpringBoot拦截器实现简单的登录认证模块

    Java结合SpringBoot拦截器实现简单的登录认证模块 之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章 ...

  2. SpringBoot拦截器中Bean无法注入(转)

    问题 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于其他bean在service,controller层注入一点问题也没有,开始根本没意识到Be ...

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

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

  4. SpringBoot拦截器中无法注入bean的解决方法

    SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...

  5. Springboot拦截器未起作用

    之前遇到要使用springboot拦截器却始终未生效的状况,查了网上的博客,大抵都是@Component,@Configuration注解未加,或是使用@ComponentScan增加包扫描,但是尝试 ...

  6. SpringBoot拦截器中service或者redis注入为空的问题

    原文:https://my.oschina.net/u/1790105/blog/1490098 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于 ...

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

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

  8. Springboot 拦截器配置(登录拦截)

    Springboot 拦截器配置(登录拦截) 注意这里环境为springboot为2.1版本 1.编写拦截器实现类,实现接口   HandlerInterceptor, 重写里面需要的三个比较常用的方 ...

  9. SpringBoot图文教程7—SpringBoot拦截器的使用姿势这都有

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

随机推荐

  1. 关于有符号数和无符号数的转换 - C/C++

    转载自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题, ...

  2. “深度评测官”——记2020BUAA软工软件案例分析作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 个人博客作业-软件案例分析 我在这个课程的目标是 完成一次完整的软件开发经历并以博客的方式记录开发 ...

  3. 墙裂推荐一波mysql学习资源

    在日常工作与学习中,无论是开发.运维.测试,还是架构师,数据库是一门必不可少的"必修课", 也是必备的涨薪神器.在互联网公司中,开源数据库用得比较多的当属 MySQL 了. 但my ...

  4. Date类常用方法总结(构造|格式化输出|String转换|Long转换|计算间隔|比较)

    java.util.Date类 它重写了toString方法,new一个Date类直接输出是按照这样的格式 // "EEE MMM dd HH:mm:ss zzz yyyy"Fri ...

  5. [刷题] 226 Invert Binary Tree

    要求 翻转一棵二叉树 实现 翻转左右子树,交换左右子树的根节点 1 class Solution { 2 public: 3 TreeNode* invertTree(TreeNode* root) ...

  6. QT发布 - 动态编译,删减以来dll

    经常看到网上有些论调说 Qt 程序无比庞大,甚至拿 .NET 程序来比,说 Qt 程序打包以后跟 .NET 安装包差不多大.由此影响了很多人对 Qt 的选择.我觉得有必要对此做一些澄清-- 显然这个说 ...

  7. 【转载】Linux查看PCIe版本及速率【方法】PCIE的X4X8X16 查看 数量 怎么看

    Linux查看PCIe版本及速率   PCIE有四种不同的规格,通过下图来了解下PCIE的其中2种规格   查看主板上的PCI插槽 # dmidecode | grep --color "P ...

  8. fail to start File System Check

    fail to start File System Check 方法A: 输入root的密码 cd /etc 1 vim /etc/fstab 将所有分区最后的数字 1和2 全都改为0 reboot ...

  9. 5.6 date:显示与设置系统时间

    date命令 用于显示当前的系统时间或设置系统时间. date [选项] +[日期格式]   date命令的参数选项及说明 OPTION参数选项-d 时间字符串 显示指定字符串所描述的时间,而非当前时 ...

  10. 5.7 echo:显示一行文本

    echo命令 能将指定的文本显示在Linux命令行上.     -n    不要自动换行 -E    不解析转义字符(默认参数)   -e    若字符串中出现以下字符,则需要进行特别处理,而不会将它 ...