优雅处理HTTP请求:过滤器、拦截器、ControllerAdvice和自定义AOP

news2024/12/23 9:09:28

我们在开发Spring Boot应用程序时,经常会遇到需要对HTTP请求进行一些处理的情况,例如鉴权、数据校验、请求日志记录等等。在处理HTTP请求时,我们可以使用四种不同的技术来实现这些功能:过滤器、拦截器、ControllerAdvice和自定义AOP。

在本文中,我们将分别介绍这四种技术的概念、用法和区别,并举例说明如何在Spring Boot应用程序中使用它们来实现对HTTP请求的统一处理。

基本概念及拦截执行顺序

  1. 过滤器(Filter):过滤器是Java Web中的一种技术,它在请求到达Servlet之前或之后进行处理。因此,过滤器是最先执行的拦截器。在过滤器中可以进行一些通用的业务处理,例如鉴权、数据校验、请求日志记录等等。Spring Boot应用程序中注册的过滤器按照注册的顺序依次执行。
  2. 拦截器(Interceptor):拦截器是Spring MVC框架提供的一种技术,它在请求到达Controller之前或之后进行处理。因此,拦截器在过滤器之后执行,但在请求到达Controller之前。在拦截器中可以进行请求的修改或者一些通用的业务逻辑处理。Spring Boot应用程序中注册的拦截器按照注册的顺序依次执行。
  3. ControllerAdvice:ControllerAdvice是Spring MVC提供的一个注解,用于定义一个全局的异常处理器、数据绑定器和模型处理器。它可以被用于处理所有的Controller中抛出的异常和响应,对于多个Controller中重复的异常处理可以进行统一管理。ControllerAdvice在请求到达Controller之后执行,可以对Controller返回的数据进行统一处理,例如添加通用的响应头、设置统一的返回值格式等等。
  4. 自定义AOP(Aspect-Oriented Programming):自定义AOP是一种编程范式,它可以用于在方法调用前、后或抛出异常时添加一些横切逻辑。在Spring Boot应用程序中,自定义AOP切面可以用于对HTTP请求进行统一处理,例如获取和解析请求头信息、请求日志记录、鉴权等等。自定义AOP切面的执行顺序在拦截器之后,在请求到达Controller之前执行。

总的来说,四种拦截方式的执行顺序是过滤器->拦截器->ControllerAdvice->自定义AOP。

但是需要注意的是,这并不是绝对的顺序,具体的执行顺序还会受到过滤器链、拦截器链、AOP切入位置等因素的影响,例如

  • 如果在过滤器或拦截器中调用了chain.doFilter(request, response)或handlerInterceptor.preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)方法,则会依次调用过滤器链和拦截器链的下一个过滤器或拦截器。
  • 自定义AOP的执行顺序在ControllerAdvice之后,是因为一般情况下我们会将切入点选在Controller的方法上

四种拦截方法的使用case

过滤器

在Spring Boot项目中,可以使用过滤器(Filter)来统一处理HTTP请求,并获取和解析请求头中的内容。过滤器可以在请求到达Servlet之前或之后进行一些处理操作。

以下例子展示如何在Spring Boot项目中实现一个过滤器来获取和解析请求头中的内容:

  1. 创建一个过滤器类,实现Filter接口。在该过滤器类中,可以重写doFilter方法,在该方法中获取并解析请求头信息。
 

Java

复制代码

public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; // 获取请求头信息 String headerInfo = httpRequest.getHeader("Header-Info"); // 解析请求头信息 // ... chain.doFilter(request, response); // 继续执行请求处理 } // 可以重写init和destroy方法进行初始化和销毁操作 }

  1. 在Spring Boot应用程序中注册该过滤器类。可以通过创建一个配置类并继承WebMvcConfigurerAdapter类,然后重写addFilters方法来注册过滤器。
 

Java

复制代码

public class MyFilterConfig extends WebMvcConfigurerAdapter { @Bean public FilterRegistrationBean<MyFilter> myFilter() { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/*"); // 指定过滤的URL return registrationBean; } }

这样,当请求到达时,就会先进入过滤器的doFilter方法进行处理,并获取和解析请求头信息。过滤器可以处理任何类型的请求,而不仅仅是Web请求,因此需要在过滤器中进行类型判断。

拦截器

在Spring Boot项目中,可以使用拦截器(Interceptor)来对HTTP请求进行统一转换和处理请求头信息。拦截器可以在请求处理前和处理后进行一些处理操作。

以下例子展示如何在Spring Boot项目中实现一个拦截器来获取和解析请求头中的信息:

创建一个拦截器类,实现HandlerInterceptor接口。在该拦截器类中,可以重写preHandle方法,在该方法中获取并解析请求头信息。

 

Java

复制代码

public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 获取请求头信息 String headerInfo = request.getHeader("Header-Info"); // 解析请求头信息 // ... return true; // 返回true继续执行请求处理,返回false则不执行请求处理 } // 可以重写 afterCompletion 和 postHandle 方法进行请求处理后的操作 }

在Spring Boot应用程序中注册该拦截器类。可以通过创建一个配置类并继承WebMvcConfigurerAdapter类,然后重写addInterceptors方法来注册拦截器。

 

Java

复制代码

@Configuration public class MyInterceptorConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); } }

这样,当请求到达时,就会先进入拦截器的preHandle方法进行处理,并获取和解析请求头信息。注意,拦截器只能处理@Controller注解或@RequestMapping注解的处理器方法,并且只对Web请求有效,对于非Web请求(如静态资源)不会进行拦截。

除preHandle(目标方法执行前执行), HandlerInterceptor还有两外两个方法:

  • postHandle 目标方法执行后执行
  • afterCompletion 请求完成时执行

ControllerAdvice

  • @ControllerAdvice是Spring MVC提供的一个注解,用于定义一个全局的异常处理器、数据绑定器和模型处理器。它可以被用于处理所有的Controller中抛出的异常和响应,对于多个Controller中重复的异常处理可以进行统一管理。
  • @ControllerAdvice注解对于应用程序中所有的@Controller注解的类中的方法进行全局处理,可以捕获Controller中的异常并返回相应的响应信息,也可以在Controller中返回数据之前对数据进行统一处理。
  • @ControllerAdvice注解所标注的类中,可以定义多个方法,每个方法可以处理不同的异常或返回不同类型的数据。在方法上可以使用@ExceptionHandler、@InitBinder或@ModelAttribute注解来指定要处理的异常类型、数据绑定规则和模型处理规则。

下面是一个@ControllerAdvice注解的示例:

 

Java

复制代码

@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) @ResponseBody public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } }

上面的代码定义了一个全局异常处理器,用于处理所有Controller中抛出的Exception异常,如果出现异常则返回一个HTTP 500错误响应,并将异常信息作为响应体返回。

另外,@ControllerAdvice注解中还可以添加basePackages属性或value属性来指定需要处理的Controller所在的包路径或类。例如:

 

Java

复制代码

@ControllerAdvice(basePackages = "com.example.controller") public class GlobalExceptionHandler { // ... }

这样就只会处理com.example.controller包下的Controller中抛出的异常。

总之,@ControllerAdvice是一个很有用的注解,可以让我们在应用程序中统一处理异常和响应,避免重复的代码,提高代码的可维护性和可读性。

自定义AOP

在Spring Boot项目中,可以使用自定义AOP的方式来统一处理HTTP请求,并获取和解析请求头中的内容。通过自定义AOP切面,可以在请求处理前和处理后添加相应的切面逻辑。

以下例子展示如何在Spring Boot项目中实现自定义AOP切面来获取和解析请求头中的内容:

创建一个注解,用于标注需要进行切面处理的方法。在该注解中添加一个String类型的属性,用于指定需要获取的请求头信息。

 

Java

复制代码

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value(); }

创建一个切面类,实现Aspect接口,并在该类中定义一个切点方法和一个通知方法。在切点方法中,使用@Pointcut注解来指定需要进行切面处理的方法;在通知方法中,通过JoinPoint参数获取请求对象,并从请求对象中获取并解析请求头信息。

 

Java

复制代码

@Aspect @Component public class MyAspect { @Pointcut("@annotation(com.example.demo.MyAnnotation)") public void myPointcut() {} @Around("myPointcut()") public Object myAdvice(ProceedingJoinPoint joinPoint) throws Throwable { // 获取请求对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 获取注解中指定的请求头信息 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); MyAnnotation annotation = methodSignature.getMethod().getAnnotation(MyAnnotation.class); String headerInfo = request.getHeader(annotation.value()); // 解析请求头信息 // ... // 继续执行请求处理 Object result = joinPoint.proceed(); // 处理请求处理结果 // ... return result; } }

在需要进行切面处理的方法上添加自定义注解,并指定需要获取的请求头信息。

 

Java

复制代码

@RestController public class MyController { @MyAnnotation("Header-Info") @GetMapping("/hello") public String hello() { return "Hello World!"; } }

这样,在请求到达需要进行切面处理的方法时,就会先进入自定义AOP切面的通知方法进行处理,并获取和解析请求头信息。注意,自定义AOP切面可以处理任何类型的方法,而不仅仅是@Controller注解或@RequestMapping注解的处理器方法,它也可以处理非Web请求(如异步方法或定时任务等)。

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

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

相关文章

谷歌seo多久才能见效?谷歌seo见效的参考时间线和效果预估

影响谷歌SEO的效果因素 谷歌SEO的效果因多种因素而异&#xff0c;包括竞争程度、关键词选择、网站优化程度、内容质量和网站的历史等。一般来说&#xff0c;SEO是一个长期的过程&#xff0c;而不是一夜之间见效的事情。e6zzseo&#xff08;e6zzseo的博客_CSDN博客-seo领域博主…

嵌入式音视频疑惑汇总

小小的脑袋里,大大的疑问,该文是博主在工作中遇见问题后,面向chatGPT学习的记录笔记 1.bypass hdr 是什么? “Bypass HDR” 是指绕过高动态范围(HDR)功能的一种设置。HDR 是指一种显示技术,它可以提供更高的色彩深度和亮度范围,从而产生更加真实、明亮和有层次感的图像…

Ludo:海外飞行棋游戏玩法,文末附源码

Ludo起源于印度的古老游戏Pachisi&#xff0c;玩法类似国内的飞行棋&#xff0c;是一种适合2至4人玩的战略类棋盘游戏。 其游戏规则也很简单&#xff1a;对局中&#xff0c;每人有2颗或4颗棋子&#xff0c;通过投骰子的方式决定前进的步数&#xff0c;在前进过程中赶上对手即可…

手把手带你分析 (net.devh.boot.grpc 包下面的)服务端 Grpc 自动装配、服务注册的源码(Java版)

前言 昨天写过一篇关于如何使用 Grpc 的博客&#xff0c;出于好奇想知道 GrpcService、GrpcClient、GrpcGlobalServerInterceptor、GrpcGlobalClientInterceptor这些注解是如何生效的&#xff0c;以及服务注册的流程是怎样的&#xff0c;就简单过了一遍源码&#xff0c;帮助大家…

新人必看!手把手教你如何使用浏览器表格插件(下)

摘要&#xff1a;本文由葡萄城技术团队于博客园原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 | 问题背景 作为一名优秀的打工人&#xff0c;Excel是大家上班中必不可少的办…

理解Linux TunTap设备

入门 TUN/TAP是操作系统内核中的虚拟网络设备&#xff0c;可以完成用户空间与内核空间的数据的交互。网络协议栈中的数据通过该设备可以进入到用户空间中&#xff0c;而用户空间中的程序通过该设备空间进入到内核空间的网络协议栈。 TUN模拟的是三层设备&#xff0c;操作三层…

chatgpt赋能python:Python主程序:提升编程效率与合作性的最佳选择

Python 主程序&#xff1a;提升编程效率与合作性的最佳选择 前言 Python 作为一门简单、易于学习并具备强大功能的编程语言&#xff0c;已经成为了最受欢迎的编程语言之一。Python 主程序不仅能够编写复杂的算法和进行数据处理&#xff0c;而且还可以实现广泛的应用&#xff…

基于SpringBoot+Uniapp的球队周边微信小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着微信小程序的兴起…

【jeecg-boot】jeecg-boot的一些功能扩展:

文章目录 一、Template里面将数组对象里面的值遍历>对象的key二、利用ES6的解构赋值互换数组数据&#xff1a;三、a-select实现可输入可下拉:四、a-table实现动态表头&#xff1a;五、jeecg-boot列自定义&#xff1a;六、jeecg-boot合计行&#xff1a; 一、Template里面将数…

Android 逆向工程,反编译心得

前言 apk的反编译是我们在Android开发中绕不开的一个坎&#xff0c;对于反编译这门技术&#xff0c;我们应该抱着学习的态度&#xff0c;学的越多&#xff0c;也越能防备别人反编译我们&#xff0c;这就是所谓的知己知彼吧&#xff0c;哈哈 需要准备的工具 Apktool&#xff…

centos下Harbor的安装(超详细+避坑)

前提 这篇文章讲的是在我的本地虚拟机上安装Harbor的一些过程和中途所遇到的一些问题和排除问题的情况说明&#xff1b;安装好的harbor的访问信息如下&#xff1a;http://192.168.45.146:8033/harbor&#xff08;admin/Harbor12345&#xff09;环境 本次所使用的环境和软件的各…

国外APP外包开发及上线流程

现在很多APP都做成全球通用版&#xff0c;尤其是一些小游戏类的APP&#xff0c;玩法全球基本都类似&#xff0c;在多个国家上线多个销售渠道。今天和大家分享一下Google Play上线流程及注意事项&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件…

ChatGPT:AI时代的创造力激活

《你好&#xff0c;ChatGPT》是一本深入探索人工智能&#xff08;AI&#xff09;领域的畅销书籍&#xff0c;它以ChatGPT为切入点&#xff0c;系统地介绍了AI和AIGC的基础概念、技术原理、应用领域和未来展望。这本书通俗易懂&#xff0c;由浅入深&#xff0c;层层递进&#xf…

WMS仓储管理系统解决方案能帮助电子企业解决哪些问题

WMS仓储管理系统解决方案是一种针对仓库管理的软件系统&#xff0c;它能够有效地解决电子企业在仓储管理方面的问题。在电子行业&#xff0c;由于产品的生命周期较短&#xff0c;且需求变化快速&#xff0c;WMS仓库管理系统的应用对于电子企业的管理有着重要的意义。本文将探讨…

DATAV通过配置nginx代理实现https访问

DATAV通过配置nginx代理实现https访问 首先要确保你的 datav 和 datav_proxy 的界面能用http正常访问 在nginx中添加datav配置 server {listen 8181 ssl;server_name localhost;ssl_certificate server.crt;ssl_certificate_key server.key;ssl_session_cache …

“来此加密“:轻松在线申请多域名和泛域名SSL证书

启用SSL证书是网站安全的关键。它加密数据传输&#xff0c;防止黑客窃听和篡改。SSL证书提升网站可信度&#xff0c;增加用户信任。搜索引擎更青睐启用SSL证书的网站&#xff0c;提高可见性和流量。此外&#xff0c;SSL证书还防止钓鱼和恶意软件威胁&#xff0c;保护用户安全。…

A-21S吸金树脂在金矿尾水、镀金废水中回收金的应用

吸金树脂Tulsimer A-21S 一、技术介绍 传统上使用活性碳吸附金子&#xff0c;珍贵的金会被活性碳吸附于表面&#xff0c;再藉由洗涤或直接焚烧以回收金。使用离子交换树脂回收贵金属比活性碳还具有多方面的优势&#xff0c; 因为藉由特殊制造过程中&#xff0c; 我们可以在其结…

python---动态类型

动态类型&#xff1a;是指在程序运行过程中&#xff0c;变量的类型可能会发生改变。 a的类型随着程序运行过程中会发生改变。 后面写不写类型是无所谓的&#xff01; 相比之下静态类型的语言是更好的&#xff01; 代码注释 可以使用’‘’ ‘’‘ / #来对代码进行注释

03_堆+MAT工具

堆栈方法区的关系&#xff1a; HotSpot是使用指针的方式来访问对象&#xff1a; Java堆中会存放访问类元数据的地址 reference存储的就是对象的地址 三种JVM&#xff1a; Sun公司的HotSpotBEA公司的JRockitIBM公司的J9 VM 一、堆体系概述 Java7之前 Heap 堆&#xff1a;一个…

LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间

LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间 桌面执行节点可以控制模拟时间&#xff0c;因此开发人员可以使用模拟I/O在开发计算机上执行期间更改关键点的激励。要成功使用此功能&#xff0c;需要测量FPGA VI完成所需的时间&#xff0c;或者需要以直观地知道…