首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Spring 常用的三种拦截器详解

编程知识
2024年07月27日 15:57

前言

在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 AOP、 Interceptor 、 Filter,但其实很多人并不知道什么时候用AOP,什么时候用Interceptor,什么时候用Filter,也不知道其拦截顺序,内部原理。今天我们详细介绍一下这三种拦截器。

拦截器顺序

我们现在有一个controller接口,叫做test,现在我们在项目有定义了三个拦截器,其顺序如下

Filter(before) > Interceptor(before) > AOP(before) > test方法 > AOP(after) > Interceptor(after) > Filter(after)

具体流程如下两幅图片。

所以有时候我们使用不了AOP/Interceptor, 只能使用Filter。

  • 比如我们现在是一个Get请求,但是别人却发送了一个Post请求,这时候只有Filter才能拦截,只能使用Filter.
  • 又比如我们在Interceptor获取了请求参数以后,因为是一个流,后面controller就会获取不到,我们一般会采用包装类来实现重复读取。但假如我们直接使用AOP就完全可以避免这个问题了。

类似的例子比较多,所以我们应该知其然,也要知其所以然。下面我们介绍一下三种拦截器的具体用法。

Filter拦截器

filter是servlet层面的提供拦截器,和spring无关。只是说现在spring/springboot一统江湖,很多项目在spring的基础上面使用filter。那我们如果在spring项目中使用filter拦截器呢

@Slf4j
public class FirstFilter implements Filter {
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

		log.info("FirstFilter before doFilter");
		filterChain.doFilter(servletRequest, servletResponse);
	}
}

@Slf4j
public class SecondFilter implements Filter {
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

		log.info("SecondFilter before doFilter");
		filterChain.doFilter(servletRequest, servletResponse);
	}
}

@Slf4j
@Configuration
public class FilterConfig {

	@Bean
	public FilterRegistrationBean firstFilter() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setFilter(new FirstFilter());
		registration.addUrlPatterns("/*");
		registration.setName("FirstFilter");
		// 数字越小,优先级越高
		registration.setOrder(1);
		return registration;
	}

	@Bean
	public FilterRegistrationBean secondFilter() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setFilter(new SecondFilter());
		registration.addUrlPatterns("/*");
		registration.setName("SecondFilter");
		// 数字越大,优先级越低
		registration.setOrder(2);
		return registration;
	}

}

输出结果

FirstFilter before doFilter

SecondFilter before doFilter

Interceptor拦截器

Interceptor是springmvc给我们提供的拦截器,只有在sotingmvc中才可以使用

@Slf4j
@Component
public class FirstInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		log.info("FirstInterceptor preHandle");
		return true;
	}
}

@Slf4j
@Component
public class SecondInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		log.info("SecondInterceptor preHandle");
		return true;
	}

}

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

	@Autowired
	private FirstInterceptor firstInterceptor;

	@Autowired
	private SecondInterceptor secondInterceptor;

	// 配置拦截规则
	public void addInterceptors(InterceptorRegistry registry) {

		// 按照注册的顺序,依次执行
		registry.addInterceptor(firstInterceptor)
				.addPathPatterns("/**")
				.excludePathPatterns("/task/**");

		registry.addInterceptor(secondInterceptor)
				.addPathPatterns("/**")
				.excludePathPatterns("/spring/**");
	}
}

输出结果

FirstInterceptor preHandle

SecondInterceptor preHandle

AOP拦截器

AOP是我们非常常用的拦截器,织入点,有before,after,around等,我们今天以around为例

@Aspect
@Component
public class LoggerAOP {

	@Pointcut("execution (public * com.xxx.controller..*(..))")
	public void pointcutLogger() {}

	@Around("pointcutLogger()")
	public Object methodAround(ProceedingJoinPoint joinPoint) throws Throwable {
		try {
			logger.info("request className = {}, method = {}, ip = {}, param = {}", className, methodName, ip, param);

			resp = joinPoint.proceed();

			long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS);
			logger.info("response className = {}, method = {}, resp = {}, cost = {}ms", className, methodName, buildResp(resp), duration);
		}

		catch (Throwable e) {
			logger.error("logger request className = {}, method = {} fail message = {} ",
					className, methodName, e.getMessage(), e);
			throw e;
		}
		return resp;
	}
}

最后

我们介绍了一下spring中,常用的三种拦截器,以及他们在springboot中如何使用。

最后给大家出一个小作业,如果把上面三个拦截器放到一个项目中,他会输出什么顺序呢?

[INFO  2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [FirstFilter.doFilter:17] [FirstFilter before doFilter]
[INFO  2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [SecondFilter.doFilter:17] [SecondFilter before doFilter]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [FirstInterceptor.preHandle:18] [FirstInterceptor preHandle]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [SecondInterceptor.preHandle:18] [SecondInterceptor preHandle]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [LoggerAOP.methodAround:52] [request className = TestController, method = testController, ip = 0:0:0:0:0:0:0:1, param = [null]]

[INFO  2024-07-27 16:01:52.149] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [TestController.testController:57] [main process]

[INFO  2024-07-27 16:01:52.149] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [LoggerAOP.methodAround:62] [response className = TestController, method = testController, resp = "ok", cost = 0ms]

From:https://www.cnblogs.com/wenbochang/p/18327158
本文地址: http://shuzixingkong.net/article/484
0评论
提交 加载更多评论
其他文章 ComfyUI插件:ComfyUI Impact 节点(一)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器、细节强化器、预览桥、通配符、Hook、图片发送器、图片接收器等等。通过这些节点的组合运用,我们可以实现的工作有很多,例如自动人脸检测和优化修复、区域增强、
ComfyUI插件:ComfyUI Impact 节点(一) ComfyUI插件:ComfyUI Impact 节点(一) ComfyUI插件:ComfyUI Impact 节点(一)
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞 超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞 超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
C# 通过反射(Reflection)调用不同名泛型方法
概述 由于工作需要,需要通过数据类型和方法名控制方法走向 用到的数据类型有8种(string,Int16,Int32,Int64,Boolean,Byte,Single,Double) 读取的方法(参数一致,但是数据不同的泛型方法,返回值也是泛型)暂时只有11种,但肯定的是,后续一定会增加 原本计划
《Programming from the Ground Up》阅读笔记:p88-p94
《Programming from the Ground Up》学习第5天,p88-p94总结,总计7页。 一、技术总结 1.touppercase.s #PURPOSE: This program converts an input file #to an output file with all
《Programming from the Ground Up》阅读笔记:p88-p94
带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线
本文主要讲解通过github的actions来对我们项目进行ci/cd System.out.println("原文地址:https://www.cnblogs.com/ancold/p/18327097"); 一、actions简介 GitHub Actions 是一种持续集成
带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线 带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线 带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线
【AppStore】IOS应用上架Appstore的一些小坑
前言 上一篇文章写到如何上架IOS应用到Appstore,其中漏掉了些许期间遇到的小坑,现在补上 审核不通过原因 5.1.1 Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage 5.1.1(ii) Permission Ap
【AppStore】IOS应用上架Appstore的一些小坑 【AppStore】IOS应用上架Appstore的一些小坑 【AppStore】IOS应用上架Appstore的一些小坑
useRoute 函数的详细介绍与使用示例
title: useRoute 函数的详细介绍与使用示例 date: 2024/7/27 updated: 2024/7/27 author: cmdragon excerpt: 摘要:本文介绍了Nuxt.js中useRoute函数的详细用途与示例,展示了如何在组合式API中使用useRoute获取
useRoute 函数的详细介绍与使用示例 useRoute 函数的详细介绍与使用示例
Golang 高性能 Websocket 库 gws 使用与设计(一)
GitHub 🌟 1.2k,高性能的 websocket 库,代码双语注释,适合有开发经验的同学进阶学习。
Golang 高性能 Websocket 库 gws 使用与设计(一) Golang 高性能 Websocket 库 gws 使用与设计(一) Golang 高性能 Websocket 库 gws 使用与设计(一)