Springboot项目快速实现 * 功能
作者:凡夫贩夫 时间:2022-10-05 12:34:50
前言
上一篇文章分享了Springboot项目快速实现过滤器功能,本篇文章接着来盘一盘 * ,仔细研究后会发现,其实 * 和过滤器的功能非常类似,可以理解为面向切面编程的一种具体实现。下面就其功能特性、工作原理、涉及到的核心类以及具体的实现方式几个方面进行梳理,以便在实际业务开发过程中,可以根据实际需要选择合适的实现访求。
环境配置
jdk版本:1.8
开发工具:Intellij iDEA 2020.1
springboot:2.3.9.RELEASE
HandleInterceptor介绍
* ,在java中只是一种概念,并没有一个具体的实现或标准,通常所说的java web的 * 实际是指HandleInterceptor接口,这是Spring MVC提供的一套拦截机制,可以在controller处理请求之后和响应处理结果之后,对请求信息和响应结果进行拦截;但不能修改具体的请求信息和响应结果;Spring MVC的 * 的概念和servlet的Filter非常类似,但是在执行顺序上是有所不同的,下面会重点介绍;从本质上来说,SpringMVC的 * 机制,是AOP(面向切面编程)的一种具体实现,可以很方面用户对实际业务中公共的一些业务进行横向抽取,但是和servlet的Filter一样,有一定的局限性,如能对请求信息和响应结果进行拦截,但不能修改具体的请求信息和响应结果;能拦截controller层的方法,但是不能拦截service层的方法;
工作原理
如果把过滤器和 * 放在一起来分析其工作原理,就需要再次明确一件事:Filter接口的全限定类名是javax.servlet.Filter,HandleInterceptor接口的全限定类名是org.springframework.web.servlet.HandlerInterceptor,从这里就可以看得出来,Filter是servlet里就有的接口,HandleInterceptor是Spring中新增的接口,两个是来源完全不同的东西,但功能却很类似,那么放在一起又会发生什么奇妙的事呢?
1、过滤器1、过滤器2、拦截1、拦截2对象,会在Spring容器启动的过程中,完成bean的注册;
2、当客户端向服务端发起http请求时,在请求到达具体的controller方法之前,会先经过过滤器、 * 的处理,其中过滤器的执行时机要早于 * ;和过滤器一样,如果当前请求匹配到了多个 * ,会形成一个 * 链,按照默认或指定的优先级,依次经过各个 * 对象的处理之后,才会到达具体的controller方法;
3、到达具体的controller方法后,开始业务处理;得到业务处理结果后,响应结果也会经过请求进来时的所有过滤器、 * 的处理,不同的是顺序与请求进来时完全相反,即先进后出;
实现方式
1、实现org.springframework.web.servlet.HandlerInterceptor接口;
2、继承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter类;
核心类
HandlerInterceptor
HandlerInterceptor是SpringMVC提供的实现 * 功能的一个标准接口,接口内有三个方法:
1、preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) ,方法在请求处理之前会被调用。该方法在 Interceptor 类中最先执行,用来进行一些前置初始化操作或是对当前请求做预处理,也可以进行一些判断来决定请求是否要继续进行下去。该方法的返回值是 Boolean 类型;当它返回 false 时,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;当它返回为 true 时,会继续调用下一个 Interceptor 的 preHandle 方法,如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法;
2、postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成之后,也就是 Controller 方法调用之后执行,但是它会在 DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作;
3、afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会执行;该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行,主要用来进行资源清理或释放。
HandlerInterceptorAdapter
HandlerInterceptorAdapter是一个抽象类,该抽象类实现了AsyncHandlerInterceptor接口,而AsyncHandlerInterceptor接口又继承于HandlerInterceptor,因此可以认为HandlerInterceptorAdapter是实现了HandlerInterceptor接口,但是HandlerInterceptorAdapter是抽象类,实际上并没有具体实现,所以在实现 * 功能功能的两种方式本质上是一种;
代码实现
定义两个 * :MyInterceptor1和MyInterceptor2,通过一次完成的请求,来分析一下HandlerInterceptor接口的preHandle()、postHandle()、afterCompletion()是如何工作的?
1、定义和注册两个 * :MyInterceptor1和MyInterceptor2,设置 * 的拦截路径为/person/get*,myInterceptor2的优先级高于myInterceptor1;
2、发起http请求(URL:/person/get);
3、/person/get请求在执行PersonController#getPerson()之前,会先执行到MyInterceptor1和MyInterceptor2的preHandler()方法;
4、如果MyInterceptor1和MyInterceptor2的preHandler()方法返回都为true,则会执行到PersonController#getPerson();
5、PersonController#getPerson()执行完成后,还没有返回视图渲染对象之前MyInterceptor1和MyInterceptor2的postHandle()方法触发执行;
6、再然后就是整个请求处理完之后,MyInterceptor1和MyInterceptor2的afterCompletion()方法触发执行;
PersonController.java
@Controller
@RequestMapping("/person")
@Slf4j
public class PersonController {
@Autowired
private IPersonService personService;
@GetMapping("/get")
@ResponseBody
public Person getPerson(Integer id) {
Person person = this.personService.get(id);
log.info("//查询person详情执行完成");
return person;
}
}
定义WebConfig类实现WebMvcConfigurer接口,实现addInterceptors(),完成 * 的注册以及设置好拦截路径和优先级顺序;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor2())
.addPathPatterns("/person/get*")
.order(1);
registry.addInterceptor(new MyInterceptor1())
.addPathPatterns("/person/get*")//设置拦截请求路径;*是通配符;
.order(2)//设置 * 对象的优先级,如果有多个 * 对象,设置数字越小,优先级越高;
.excludePathPatterns("/test");//设置排除拦截的请求路径;
}
}
定义MyInterceptor1类实现HandlerInterceptor接口
@Slf4j
public class MyInterceptor1 implements HandlerInterceptor {
//preHandle方法在请求处理之前被调用;当返回true,则表示可以继续后续请求处理;当返回false,则表示请求结束;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("//myInterceptor1的preHandle方法开始执行");
log.info("//请求路径:{}",request.getRequestURI());
HandlerMethod handlerMethod = (HandlerMethod) handler;
log.info("//拦截类:{},方法:{}",handlerMethod.getBean().getClass().getName(),handlerMethod.getMethod().getName());
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String parameterName = parameterNames.nextElement();
String parameterValue = request.getParameter(parameterName);
log.info("//请求参数>{}:{}",parameterName,parameterValue);
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("//myInterceptor1的postHandle方法开始执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("//myInterceptor1的afterCompletion方法开始执行");
}
}
定义MyInterceptor2,继承HandlerInterceptorAdapter抽象类,重写HandlerInterceptorAdapter类的方法;
@Slf4j
public class MyInterceptor2 extends HandlerInterceptorAdapter {
//preHandle方法在请求处理之前被调用;当返回true,则表示可以继续后续请求处理;当返回false,则表示请求结束;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("//myInterceptor1的preHandle方法开始执行");
log.info("//请求路径:{}",request.getRequestURI());
HandlerMethod handlerMethod = (HandlerMethod) handler;
log.info("//拦截类:{},方法:{}",handlerMethod.getBean().getClass().getName(),handlerMethod.getMethod().getName());
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String parameterName = parameterNames.nextElement();
String parameterValue = request.getParameter(parameterName);
log.info("//请求参数>{}:{}",parameterName,parameterValue);
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("//myInterceptor1的postHandle方法开始执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("//myInterceptor1的afterCompletion方法开始执行");
}
结果验证
Filter与HandleInterceptor的执行顺序:在请求处理阶段,先经过Filter然后再经过HandleInterceptor,在响应处理阶段,先经过HandleInterceptor,再经过Filter,即先进后出;
来源:https://blog.csdn.net/fox9916/article/details/129691345
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
C#使用foreach语句遍历堆栈(Stack)的方法
Java发送邮箱验证码、session校验功能
浅谈C#中的值类型和引用类型
![](https://img.aspxhome.com/file/2023/4/98284_0s.jpg)
如何将Mybatis连接到ClickHouse
Java实现淘宝秒杀聚划算抢购自动提醒源码
Groovy编程入门攻略
C#中WinForm控件的拖动和缩放的实现代码
java9迁移注意问题总结
springboot如何静态加载@configurationProperties
JAVA导出EXCEL表格的实例教学
Android使用Intent传递组件大数据
idea中Maven镜像源详细配置步骤记录(对所有项目)
![](https://img.aspxhome.com/file/2023/8/88198_0s.png)
Springboot项目出现java.lang.ArrayStoreException的异常分析
Android 之BottomsheetDialogFragment仿抖音评论底部弹出对话框效果(实例代码)
![](https://img.aspxhome.com/file/2023/9/86009_0s.gif)
详解Android运行时权限及APP适配方法
![](https://img.aspxhome.com/file/2023/1/103881_0s.png)
Java SpringBoot拦截器详解
![](https://img.aspxhome.com/file/2023/7/77067_0s.gif)
Spring MVC 前端控制器 (DispatcherServlet)处理流程解析
![](https://img.aspxhome.com/file/2023/7/128857_0s.png)
Kotlin协程的线程调度示例详解
解决try-catch捕获异常信息后Spring事务失效的问题
JavaFX之TableView的使用详解
![](https://img.aspxhome.com/file/2023/4/125584_0s.png)