首页 > 其他分享 >Spring 常用的三种拦截器详解

Spring 常用的三种拦截器详解

时间:2024-07-27 17:08:27浏览次数:6  
标签:拦截器 Spring Filter doFilter 详解 registration public before

前言

在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 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]

标签:拦截器,Spring,Filter,doFilter,详解,registration,public,before
From: https://www.cnblogs.com/wenbochang/p/18327158

相关文章

  • leetcode105. 从前序与中序遍历序列构造二叉树,步骤详解附代码
    leetcode105.从前序与中序遍历序列构造二叉树给定两个整数数组preorder和inorder,其中preorder是二叉树的先序遍历,inorder是同一棵树的中序遍历,请构造二叉树并返回其根节点。示例1:输入:preorder=[3,9,20,15,7],inorder=[9,3,15,20,7]输出:[3,9,20,nul......
  • 决策树算法详解:原理、实现与应用案例
    目录一:简介二:决策树算法原理决策树的基本概念信息增益和熵基尼指数卡方检验三:决策树的构建过程数据预处理决策树生成算法剪枝技术决策树的优缺点四:决策树算法的实现使用Python实现决策树使用R语言实现决策树实现过程中需要注意的问题五:决策树算法的优化与改进......
  • 计算机毕业设计SpringBoot+vue的洗衣店客户管理信息系统
    随着人们生活水平的提高,人们的衣物越来越多,而时间精力却越来越少,于是洗衣店的需求正在急剧增加,洗衣店有着很大的发展潜力,但根据对洗衣店的现状和需求调查研究表明,目前国内的洗衣店的发展仍然落后于市场的需求。减轻家务劳动的压力,寻求专业便捷的洗衣服务已经成为大多数人的选择......
  • SpringBoot中使用监听器
    1.定义一个事件/***定义事件*@authorhrui*@date2024/7/2512:46*/publicclassCustomEventextendsApplicationEvent{privateStringmessage;publicCustomEvent(Objectsource,Stringmessage){super(source);this.message......
  • 在WPF中使用WebView2详解
    MicrosoftEdgeWebView2MicrosoftEdgeWebView2 控件允许在本机应用中嵌入web技术(HTML、CSS以及JavaScript)。 WebView2 控件使用 MicrosoftEdge 作为绘制引擎,以在本机应用中显示web内容。使用 WebView2 可以在本机应用的不同部分嵌入Web代码,或在单个 We......
  • Servlet 超详细快速入门(详解 看这一篇就够了)
    1.Servlet介绍1.1 什么是Servlet  Servlet是ServerApplet的简称,是用Java编写的是运行在Web服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet,可以收集来自网页表单的用户输入,呈现来自......
  • 计算机毕业设计ssm/springoot商场停车场服务系统
    通过对商场用户停车服务管理的调查研究,要求系统具有以下功能: 1.全面展示停车场的服务功能及环境。  2.存储用户信息。 3.车位信息用户进行入场停车功能。4.入场停车用户进行出场缴费功能,管理员进行审核。5.停车记录用户进行支付功能,管理员进行审核。  6.提供管......
  • 计算机毕业设计ssm/springoot网上购物商城系统kgyax源码lw包调试
    框架:ssm/springoot都有jdk版本:1.8及以上ide工具:IDEA或者eclipse数据库:mysql 编程语言:java前端:layui+bootstrap+jsp详细技术:HTML+CSS+JS+jsp+springmvc+mybatis+MYSQL+MAVEN+tomcat开发工具IntelliJIDEA:一先进的IDE,用于java开发,提供了丰富的工具和功能。开......
  • Spring中使用到的设计模式及其源码分析
    前言众所周知,Spring框架是一个强大而灵活的开发框架。这不,上次的面试刚问到这些,没防住!!!因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式,自己做个面试复盘,同时希望能帮助到其他小伙伴儿们。工厂模式相信大家面试题都背过,Spring通过工厂模式来创建和管理Bean......
  • Navicat premium最新【16/17 版本】安装下载教程,图文步骤详解(超简单,一步到位,免费下载
    文章目录软件介绍软件下载安装步骤激活步骤软件介绍Navicat是一款快速、可靠且功能全面的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设计。以下是对Navicat的详细介绍:一、产品概述开发目的:Navicat旨在通过其直观和设计完善的用户界面,帮助数据库管......