一篇文章说清楚Filter(过滤器)、Interceptor(拦截器)和AOP(切面儿)

文章目录

    • 前言
    • 一、Filter(过滤器)
      • 1.说明
      • 2.实现
        • filterChain.doFilter()
      • 3.order优先级
      • 4.解决跨域
      • 5.拦截返回错误信息JSON
    • 二、Interceptor(拦截器)
      • 1.说明
      • 2.实现
        • preHandle
        • postHandle
        • afterCompletion
      • 3.执行顺序图
      • 4.排除特定路径拦截 or 加入指定路径拦截
      • 5.拦截返回错误信息JSON
    • 三、AOP(切面儿)
      • 1.说明
      • 2.实现
        • Pointcut切面节点定义
        • doBefore
        • doAfter
        • doAfterReturning
        • doAfterThrowing
        • doAround
      • 3.基于注解在特定方法上实现
      • 4.拦截返回错误信息JSON
    • 四、三者共同点及不同点
      • 1.共同点
      • 2.不同点
    • 五、三者横切节点分析

前言

        Filter、Interceptor、AOP都是用于实现应用横切关注点的技术手段,通过这些技术,可以将横切关注点的代码从核心业务逻辑中解耦,使得代码更加清晰和可维护,同时也提高了代码的复用性。但是三者的应用场景还是有些区别的,Filter主要用于处理HTTP请求和响应,在Servlet容器中工作,可以实现如日志记录、安全性过滤、跨域请求处理等;Interceptor主要用于在Spring MVC中拦截方法调用,允许在方法执行前后添加额外逻辑,用于实现权限拦截、日志记录、事务管理等;AOP用于处理复杂的横切关注点,在不修改核心业务逻辑的情况下增加或调整功能,用于日志记录、事务管理、性能监控等。

一、Filter(过滤器)

1.说明

        Filter主要用于Web应用开发中,基于Servlet规范工作,处理HTTP请求和响应,可以在请求到达Servlet之前进行预处理,也可以在响应返回给客户端之前进行后处理。Filter可以组成过滤链,按照配置的顺序依次处理请求,每个Filter可以在请求进入Servlet之前进行拦截,也可以在响应返回之前对响应进行处理。需要实现Filter接口,重写init()、doFilter()和destroy()方法,其中init()和destroy()分别是初始化和销毁方法,重点是doFilter()方法,实现对请求的处理和转发或对响应的处理。

2.实现

/*** 过滤器*/
@Component
public class WsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String url = request.getRequestURI(); // 相对方法名路径System.out.println("\n【过滤器】请求到达:" + url);// 如果没有filterChain.doFilter方法,请求的方法就直接被过滤了,执行不到下面的Controller方法中filterChain.doFilter(request, response);System.out.println("【过滤器】请求结束:" + url);}@Overridepublic void destroy() {Filter.super.destroy();}
}
filterChain.doFilter()

项目启用了过滤器,doFilter方法下如果没有filterChain.doFilter(request, response)方法,则程序请求的方法就直接被过滤了,执行不到下面的Controller方法中。

3.order优先级

配置多个Filter,根据不同的order来决定过滤执行的顺序,order越小优先级越高,越大优先级越低。

4.解决跨域

与前端项目交互时,尤其是前后端分离项目,经常会出现跨域问题,这个时候需要配置跨域参数,设置Access-Control允许各类请求通过,解决跨平台交互的跨域问题。如下:

	@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String url = request.getRequestURI(); // 相对方法名路径System.out.println("\n【过滤器】请求到达:" + url);// 跨域配置if (request.getHeader("Origin") != null) {response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));}response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");// 如果没有filterChain.doFilter方法,请求的方法就直接被过滤了,执行不到下面的Controller方法中filterChain.doFilter(request, response);System.out.println("【过滤器】请求结束:" + url);}

5.拦截返回错误信息JSON

如果是void无返回值的方法,直接拦截是没有问题的,直接不执行filterChain.doFilter(request, response)方法即可。但是如果是有返回值的,需要在过滤器上构造JSON进行返回,如下:

	@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String url = request.getRequestURI(); // 相对方法名路径System.out.println("\n【过滤器】请求到达:" + url);returnJson(response, 401, "Filter拦截了");// 如果没有filterChain.doFilter方法,请求的方法就直接被过滤了,执行不到下面的Controller方法中// filterChain.doFilter(request, response);// System.out.println("【过滤器】请求结束:" + url);}private void returnJson(HttpServletResponse response, int code, String msg) throws IOException {// 设置响应的内容类型为JSONresponse.setContentType("application/json");response.setCharacterEncoding("UTF-8");// 创建JSON字符串Map<String, Object> map = new HashMap<>();map.put("code", code);map.put("msg", msg);String json = JSON.toJSONString(map);// 获取PrintWriter来写入响应PrintWriter out = response.getWriter();out.print(json);out.flush();}

二、Interceptor(拦截器)

1.说明

        Interceptor主要用于Spring MVC框架中拦截方法的调用,用于框架中方法调用的拦截和处理,拦截器与过滤器(Filter)类似,但更加灵活,通常用于框架级别的功能扩展和定制化。通常用于框架级别的功能扩展,如事务管理、日志记录、权限检查等,使得应用程序可以更加模块化、可维护和可扩展。

2.实现

/*** 拦截器*/
@Component
public class WsInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String url = request.getRequestURI(); // 相对方法名路径System.out.println("【拦截器】到达:"+ url);return true; // 放开,继续执行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 当前请求进行处理之后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用System.out.println("【拦截器】请求处理完成,DispatcherServlet准备进行视图返回渲染");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行System.out.println("【拦截器】请求结束,DispatcherServlet渲染了对应的视图");}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {@Beanpublic WsInterceptor getWsInterceptor() {return new WsInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(getWsInterceptor());}
}
preHandle

请求处理前preHandle,是在请求处理器(如Controller方法)执行前被调用的方法,允许开发者在实际请求处理前执行特定的预处理逻辑。必须【return true】时,才能执行到后续的controller方法中,如果【return false】则不往下继续执行。

postHandle

请求处理后postHandle,当前请求进行处理之后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用。

afterCompletion

视图渲染后afterCompletion,在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。

3.执行顺序图

在这里插入图片描述

4.排除特定路径拦截 or 加入指定路径拦截

如果什么都不处理,默认拦截所有的请求
registry.addPathPatterns(URL)为加入指定路径拦截,则其他路径都放行

	@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(getWsInterceptor()).addPathPatterns("/test/test02");}

registry.excludePathPatterns(URL)为排除特定路径拦截,其他路径都拦截

	@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(getWsInterceptor()).excludePathPatterns("/test/test02");}

5.拦截返回错误信息JSON

如果是void无返回值的方法,直接拦截是没有问题的,直接【return false】即可。但是如果是有返回值的,需要在拦截器上构造JSON进行返回,如下:

	@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String url = request.getRequestURI(); // 相对方法名路径System.out.println("【拦截器】到达:"+ url);returnJson(response, 402, "Interceptor拦截了");return false;// return true; // 放开,继续执行}private void returnJson(HttpServletResponse response, int code, String msg) throws IOException {// 设置响应的内容类型为JSONresponse.setContentType("application/json");response.setCharacterEncoding("UTF-8");// 创建JSON字符串Map<String, Object> map = new HashMap<>();map.put("code", code);map.put("msg", msg);String json = JSON.toJSONString(map);// 获取PrintWriter来写入响应PrintWriter out = response.getWriter();out.print(json);out.flush();}

三、AOP(切面儿)

1.说明

        AOP切面是一种编程范式,用于通过将横切关注点从核心业务逻辑中分离出来,使得这些关注点能够被模块化、重用,并且能够有效地降低代码的重复性。它定义了在何处(Pointcut)以及如何(Advice)应用横切关注点到目标对象的行为,增强系统的模块化程度,提高代码的可维护性和可扩展性。

2.实现

@Aspect
@Component
public class WsAop {// 定义切面儿的切入点,参数是定义在哪个包。哪个类、哪个方法切入,关于切入点如何定义(对应路径下的某类、某方法,*代表的是全部)@Pointcut("execution(* com.jon.demo.controller.*.*(..))")public void wsLog(){}@Before("wsLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 在切⼊点开始处切⼊内容System.out.println("【AOP】before 在切⼊点开始处切⼊内容");}@After("wsLog()")public void doAfter() {// 在切⼊点结尾处切⼊内容System.out.println("【AOP】doAfter 在切⼊点结尾处切⼊内容");}@AfterReturning(pointcut = "wsLog()", returning = "result")public void doAfterReturning(Object result) {// 在切⼊点return内容之后切⼊内容,可以对返回值做⼀些加⼯处理System.out.println("【AOP】doAfterReturning 在切⼊点return内容之后切⼊内容");}@AfterThrowing(pointcut = "wsLog()", throwing = "exception")public void doAfterThrowing(Exception exception) {// 处理当切⼊内容部分抛出异常之后的逻辑System.out.println("【AOP】doAfterThrowing 处理当切⼊内容部分抛出异常之后的逻辑");}// 环绕通知wsLog方法,切面方法需要有返回值,来代替被代理方法返回结果@Around("wsLog()")public Object doAround(ProceedingJoinPoint point) throws Throwable {// 方法要有返回,如果有多个参数ProceedingJoinPoint要放在第一个System.out.println("【AOP】doAround");return point.proceed();}
}
Pointcut切面节点定义

定义切面儿的切入点,参数是定义在哪个包。哪个类、哪个方法切入,关于切入点如何定义(对应路径下的某类、某方法,*代表的是全部)

doBefore

在切⼊点开始处切⼊内容

doAfter

在切⼊点结尾处切⼊内容

doAfterReturning

在切⼊点return内容之后切⼊内容,可以对返回值做⼀些加⼯处理。

doAfterThrowing

处理当切⼊内容部分抛出异常之后的逻辑

doAround

环绕通知wsLog方法,切面方法需要有返回值,来代替被代理方法返回结果。方法要有返回,如果有多个参数ProceedingJoinPoint要放在第一个。

3.基于注解在特定方法上实现

        不在Pointcut指定特意的类、方法作为切入点,直接自定义注解,并且指定注解的引用地址,这样在对应的方法中加上注解就会引入切面了,这样更加方便和灵活。具体的使用方式,在之前的文章自定义注解(一)——统一请求拦截中有定义!

4.拦截返回错误信息JSON

如果是void无返回值的方法,直接拦截是没有问题的,直接around方法不执行point.proceed()即可。但是如果是有返回值的,需要在around方法中构造JSON,并且在point.proceed()之前进行返回,如下:

	// 环绕通知wsLog方法,切面方法需要有返回值,来代替被代理方法返回结果@Around("wsLog()")public Object doAround(ProceedingJoinPoint point) throws Throwable {// 方法要有返回,如果有多个参数ProceedingJoinPoint要放在第一个System.out.println("【AOP】doAround");Map<String, Object> map = new HashMap<>();map.put("code", 403);map.put("msg", "AOP拦截了");return map;
//        return point.proceed();}

四、三者共同点及不同点

1.共同点

三者都是处理横切关注点,即那些不能分散在核心业务逻辑中处理的功能或需求,例如日志记录、性能监控、事务管理等。它们都支持在运行时动态地将横切关注点的代码织入到目标对象的执行流程中,而不需要修改目标对象的源代码。

2.不同点

Filter工作在Servlet容器中,可以对请求链进行处理,例如处理编码、安全性、日志等。对比于,Filter更多用于整个请求和响应的处理。

Interceptor主要工作Spring容器中,用于框架中方法调用的拦截和处理,通常用于面向对象的框架中,在方法调用前后可以添加额外逻辑。对比于Filter,Interceptor更加专注于方法调用前后的处理。

AOP用于处理复杂的横切关注点,允许在运行时动态地将横切逻辑织入到应用中,可以跨越多个类和模块,不仅限于单个方法或请求处理。可以在代码中定义关注点(如事务、日志、安全性),并在需要时将其应用到目标对象中。

五、三者横切节点分析

在这里插入图片描述
    三者横切的节点不一样,客户端端发起请求后,请求顺序为:请求入口 -> 过滤器filterChain.doFilter之前 -> 拦截器preHandle方法 -> 切面doAround方法 -> 切面before方法 -> Controller下的方法

    返回顺序为:Controller下的方法执行结束 -> 切面doAfterReturning方法 -> 切面doAfter方法 -> 拦截器postHandle方法 -> 拦截器afterCompletion方法 -> 过滤器filterChain.doFilter之后 -> 请求入口

可看执行结果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/40852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文学习——基于类型检测的动态自适应多目标优化算法

论文题目&#xff1a;Dynamic adaptive multi-objective optimization algorithm based on type detection 基于类型检测的动态自适应多目标优化算法&#xff08;Xingjuan Cai a,b, Linjie Wu a,∗, Tianhao Zhao a, Di Wu c, Wensheng Zhang d, Jinjun Chen e&#xff09;Inf…

yum命令提示 错误:rpmdb: BDB0113 Thread/process 4153/139708200269632

一、报错信息 [rootDawn yum.repos.d]# yum clean all 错误&#xff1a;rpmdb: BDB0113 Thread/process 4153/139708200269632 failed: BDB1507 Thread died in Berkeley DB library 错误&#xff1a;db5 错误(-30973) 来自 dbenv->failchk&#xff1a;BDB0087 DB_RUNRECOVE…

HTTP与HTTPS协议区别及应用场景

HTTP&#xff08;超文本传输​​协议&#xff09;和 HTTPS&#xff08;安全超文本传输​​协议&#xff09;都是用于通过网络传输数据的协议。虽然它们有一些相似之处&#xff0c;但在安全性和数据保护方面也存在显著差异。 在这篇博文中&#xff0c;我们将探讨 HTTP 和 HTTPS…

pytorch中的contiguous()

官方文档&#xff1a;https://pytorch.org/docs/stable/generated/torch.Tensor.contiguous.html 其描述contiguous为&#xff1a; Returns a contiguous in memory tensor containing the same data as self tensor. If self tensor is already in the specified memory forma…

自然语言处理与Transformer模型:革新语言理解的新时代

引言 自然语言处理&#xff08;NLP&#xff09;是人工智能和计算机科学的一个重要分支&#xff0c;旨在使计算机能够理解、生成和处理人类语言。随着互联网和数字化信息的爆炸性增长&#xff0c;NLP在许多领域中的应用变得越来越重要&#xff0c;包括&#xff1a; 搜索引擎&am…

Python实现PowerPoint演示文稿到图片的批量转换

PowerPoint演示文稿作为展示创意、分享知识和表达观点的重要工具&#xff0c;被广泛应用于教育、商务汇报及个人项目展示等领域。 然而&#xff0c;面对不同的分享场景与接收者需求&#xff0c;有时需要我们将PPT内容以图片形式保存与传播。这样能够避免软件兼容性的限制&…

OpenEuler 22.03 LTS SP3 CVE-2024-6387 OpenSSH 漏洞修复指南

一、漏洞概括 漏洞名称OpenSSH Server远程代码执行漏洞漏洞编号CVE-2024-6387公开时间2024-7-1CVSS 3.1分数8.1威胁类型代码执行漏洞等级暂无技术细节状态已公开在野利用状态不明确PoC状态x86已公开EXP状态未公开 OpenSSH是SSH&#xff08;Secure Shell&#xff09;协议的开源…

腾讯课堂即将停止服务?来试试这款开源的知识付费系统

项目介绍 本系统基于ThinkPhp5.0layuiVue开发,功能包含在线直播、付费视频、付费音频、付费阅读、会员系统、分销系统、拼团活动、直播带货、直播打赏、商城系统等。能够快速积累客户、会员数据分析、智能转化客户、有效提高销售、吸引流量、网络营销、品牌推广的一款应用&…

【Git 学习笔记】gitk 命令与 git log 其他参数的使用

1.7 用 gitk 查看提交历史 # make sure you have gitk installed $ which gitk /usr/bin/gitk # Sync the commit ID $ git checkout master && git reset --hard 13dcad # bring up the gitk interface, --all to see everything $ gitk --all &实测结果&#xf…

速速来get新妙招!苹果手机护眼模式在哪里开启

在日常生活中&#xff0c;我们经常长时间使用手机&#xff0c;无论是工作还是娱乐&#xff0c;屏幕的蓝光都会对眼睛造成一定的伤害。为了减轻眼睛疲劳&#xff0c;苹果手机推出了护眼模式&#xff0c;也叫“夜览”模式&#xff0c;通过调整屏幕色温&#xff0c;让显示效果更温…

MySQL 8.0 架构 之 中继日志(Relay log)

文章目录 MySQL 8.0 架构 之 中继日志&#xff08;Relay log&#xff09;中继日志&#xff08;Relay log&#xff09;概述相关参数参考 【声明】文章仅供学习交流&#xff0c;观点代表个人&#xff0c;与任何公司无关。 来源|WaltSQL和数据库技术(ID:SQLplusDB) MySQL 8.0 OCP …

PyTorch - 神经网络基础

神经网络的主要原理包括一组基本元素&#xff0c;即人工神经元或感知器。它包括几个基本输入&#xff0c;例如 x1、x2… xn &#xff0c;如果总和大于激活电位&#xff0c;则会产生二进制输出。 样本神经元的示意图如下所述。 产生的输出可以被认为是具有激活电位或偏差的加权…

四、(3)补充beautifulsoup、re正则表达式、标签解析

四、&#xff08;3&#xff09;补充beautifulsoup、re正则表达式、标签解析 beautifulsoupre正则表达式正则提取标签解析 beautifulsoup 补充关于解析的知识 还需要看爬虫课件 如何定位文本或者标签&#xff0c;是整个爬虫中非常重要的能力 无论find_all&#xff08;&#xff…

Spring启动时,将SpringContext设置到Util中(SpringContextUtil)

场景 在Spring应用开发中&#xff0c;为简化代码或者在静态方法中获取Spring应用的上下文&#xff0c;需要把SpringContext设置到类属性上。经过对源码的分析和实践&#xff0c;使用Spring的事件监听器监听ApplicationPreparedEvent事件是最佳的方式。 通过ApplicationPrepar…

matrixone集群搭建、启停、高可用扩缩容和连接数据库

1. 部署 Kubernetes 集群 由于 MatrixOne 的分布式部署依赖于 Kubernetes 集群&#xff0c;因此我们需要一个 Kubernetes 集群。本篇文章将指导你通过使用 Kuboard-Spray 的方式搭建一个 Kubernetes 集群。 准备集群环境 对于集群环境&#xff0c;需要做如下准备&#xff1a…

mysql在windows下的安装

一&#xff0c;软件安装 只修改开头的系统盘 二&#xff0c;环境变量配置 找到MySQL安装目录对应的bin目录复制路径粘贴过来 三&#xff0c;cmd

SSL/CA 证书及其相关证书文件解析

在当今数字化的时代&#xff0c;网络安全变得至关重要。SSL&#xff08;Secure Socket Layer&#xff09;证书和CA&#xff08;Certificate Authority&#xff09;证书作为保护网络通信安全的重要工具&#xff0c;发挥着关键作用。 一、SSL证书 SSL证书是数字证书的一种&…

SSM少儿读者交流系-计算机毕业设计源码20005

摘要 随着信息技术的发展和互联网的普及&#xff0c;少儿读者之间的交流方式发生了革命性的变化。通过使用Java编程语言&#xff0c;可以实现系统的高度灵活性和可扩展性。而SSM框架的采用&#xff0c;可以提供良好的开发结构和代码管理&#xff0c;使系统更加稳定和易于维护。…

同方威视受邀盛装亮相2024长三角快递物流展(杭州)助力行业物畅其流

同方威视技术股份有限公司携安全检测产品和综合解决方案&#xff0c;盛装亮相2024长三角快递物流展&#xff08;杭州&#xff09; 展位号&#xff1a;3C馆A07-1 时间&#xff1a;2024年7月8-10日 地址&#xff1a;杭州国际博览中心&#xff08;浙江省杭州市萧山区奔竞大道35…

【CSAPP】-linklab实验

目录 实验目的与要求 实验原理与内容 实验步骤 实验设备与软件环境 实验过程与结果&#xff08;可贴图&#xff09; 实验总结 实验目的与要求 1.了解链接的基本概念和链接过程所要完成的任务。 2.理解ELF目标代码和目标代码文件的基本概念和基本构成 3.了解ELF可重定位目…