SpringBoot拦截器、过滤器、自定义注解、监听器、全局异常-使用详解

一、拦截器

用springboot实现一个简单的拦截器

在Spring Boot中实现一个简单的拦截器涉及几个步骤。首先,你需要创建一个拦截器类,然后将其注册到Spring MVC的拦截器注册表中。下面是一个基本的例子来指导你如何操作:

1. 创建拦截器类

这个类需要实现HandlerInterceptor接口。这个接口包含三个方法:preHandle(), postHandle(),afterCompletion()

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 在控制器执行前调用System.out.println("preHandle: 请求前调用");// 返回true继续流程,返回false中断流程return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {// 在控制器执行后,视图渲染前调用System.out.println("postHandle: 请求后调用");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 在流程全部完成后调用System.out.println("afterCompletion: 请求完成后调用");}
}

2. 注册拦截器

创建一个配置类,继承WebMvcConfigurer,并重写addInterceptors()方法来注册拦截器。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册拦截器到Spring MVC机制,然后你可以决定拦截哪些URL路径registry.addInterceptor(myInterceptor).addPathPatterns("/**");}
}

在这个例子中,MyInterceptor会拦截所有的URL路径。你可以通过调整addPathPatternsexcludePathPatterns方法来自定义拦截和排除的路径。

3. 测试拦截器

一旦你设置好拦截器和配置,你可以启动Spring Boot应用并进行测试。通过访问不同的URL,你可以在控制台看到拦截器的输出,从而验证它是否按预期工作。

这就是在Spring Boot中实现一个简单拦截器的基本步骤。你可以根据自己的需求调整拦截器的逻辑和配置。

二、拦截器

再做一个过滤器

在Spring Boot中创建一个过滤器(Filter)也是一个相对简单的过程。过滤器在Servlet层面上运行,它们可以对进入和离开应用程序的请求/响应进行预处理和后处理。以下是创建和注册一个基本过滤器的步骤:

1. 创建过滤器类

首先,创建一个实现了javax.servlet.Filter接口的类。在这个类中,你可以重写doFilter方法来实现你的过滤逻辑。

import javax.servlet.*;
import java.io.IOException;public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器System.out.println("MyFilter initialized");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 在请求处理之前进行调用(Controller方法调用之前)System.out.println("MyFilter doFilter pre-processing");// 继续执行其他过滤器和请求本身chain.doFilter(request, response);// 在请求处理之后进行调用(Controller方法调用之后)System.out.println("MyFilter doFilter post-processing");}@Overridepublic void destroy() {// 过滤器销毁System.out.println("MyFilter destroyed");}
}

2. 注册过滤器

创建一个配置类,使用@Bean注解来注册过滤器。Spring Boot会自动探测并应用这个过滤器。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class WebConfig {@Beanpublic FilterRegistrationBean<MyFilter> loggingFilter() {FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new MyFilter());registrationBean.addUrlPatterns("/api/*"); // 指定过滤器的URL模式return registrationBean; }
}

在这个配置中,MyFilter过滤器将会应用于所有以/api/开头的URL。你可以根据需要调整这个路径模式。

3. 测试过滤器

部署并运行你的Spring Boot应用。当你访问配置的URL路径时,应该能在控制台看到由过滤器打印的消息,这表明过滤器正在按预期工作。

通过这些步骤,你就能成功地在你的Spring Boot应用中添加一个简单的过滤器。这可以用于诸如日志记录、请求验证、CORS设置等多种用途。

三、自定义注解

自定义一个注解,为该注解加一个参数name=kaifamiao,然后在拦截器里获取这个name

要在Spring Boot中实现这个功能,你需要创建一个自定义注解,并在拦截器中读取这个注解的参数值。这个过程大致可以分为三个步骤:

1. 创建自定义注解

首先,创建一个自定义注解。在这个例子中,我们将创建一个名为@MyAnnotation的注解,它有一个名为name的参数。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD) // 该注解适用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时保留注解信息
public @interface MyAnnotation {String name() default "kaifamiao"; // 带有默认值的name参数
}

2. 在拦截器中读取注解

接下来,修改拦截器以读取该注解的name参数。这可以通过检查被拦截方法上的注解来实现。

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);if (annotation != null) {String name = annotation.name();System.out.println("Annotation name: " + name);// 这里可以根据name做一些逻辑处理}}return true;}// 其他方法可以保持不变...
}

3. 在Controller方法上使用注解

最后,在你的Controller中的某个方法上使用这个注解。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MyController {@GetMapping("/test")@MyAnnotation(name = "kaifamiao")public String testMethod() {return "Test Method";}
}

/test端点被访问时,拦截器将会检测到testMethod上的@MyAnnotation注解,并打印出注解中的name值。

这个流程可以用于在Spring Boot应用中基于方法级别的注解来实现自定义逻辑。你可以根据实际需求调整注解的参数和拦截器中的处理逻辑。

四、监听器Listener

在Spring Boot中实现一个监听器(listener)通常是指创建一个应用事件监听器。这种监听器可以用于响应不同类型的应用事件,如应用启动、停止等。以下是创建一个简单的监听器的步骤:

1. 创建监听器类

首先,创建一个类作为监听器。你可以使用@EventListener注解来指定该类将监听哪种类型的事件。例如,下面的监听器将监听Spring BootApplicationReadyEvent,这个事件在Spring Boot应用准备就绪时触发。

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class MyApplicationListener {@EventListener(ApplicationReadyEvent.class)public void onApplicationEvent(ApplicationReadyEvent event) {// 应用准备就绪时执行的逻辑System.out.println("Application is ready!");}
}

2. 注册监听器

由于使用了@Component注解,Spring Boot将自动检测并注册这个监听器。确保你的监听器类在Spring Boot的组件扫描路径下。

3. 测试监听器

启动你的Spring Boot应用。当应用启动并准备就绪时,你应该能在控制台看到“Application is ready!”的消息,这表示监听器正在按预期工作。

扩展

除了监听Spring Boot内置的事件之外,你还可以创建和监听自定义事件。自定义事件允许你在应用中的不同部分之间有效地传递信息和触发行为。要做到这一点,你需要定义自己的事件类(扩展ApplicationEvent),然后在应用的其他部分中发布这些事件。监听器可以像上面展示的那样去监听这些自定义事件。

通过监听器,你可以为应用增加各种交互和反应逻辑,使其更加动态和响应用户或系统事件。

五、全局异常

再实现一个全局异常

在Spring Boot中实现全局异常处理通常涉及使用@ControllerAdvice注解创建一个全局异常处理类。这个类可以捕获并处理整个应用中抛出的异常。以下是创建和配置全局异常处理器的步骤:

1. 创建全局异常处理类

创建一个使用@ControllerAdvice注解的类,这个类会处理应用中抛出的异常。你可以在这个类中定义多个方法,用来处理不同类型的异常。

javaCopy code
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;@ControllerAdvice
public class GlobalExceptionHandler {// 处理特定类型的异常@ExceptionHandler(SpecificException.class)public ResponseEntity<String> handleSpecificException(SpecificException e) {// 返回一个错误信息和适当的HTTP状态码return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);}// 处理所有其他异常@ExceptionHandler(Exception.class)public ResponseEntity<String> handleGeneralException(Exception e) {// 返回一个通用的错误信息和HTTP状态码return new ResponseEntity<>("An error occurred: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);}
}

在这个例子中,handleSpecificException方法处理SpecificException类型的异常,而handleGeneralException方法处理所有其他类型的异常。你可以根据需要自定义这些方法。

2. 使用自定义异常

为了使全局异常处理更有效,你可能需要定义一些自定义异常类。这些类可以扩展RuntimeException或其他标准异常类。

public class SpecificException extends RuntimeException {public SpecificException(String message) {super(message);}
}// 可以根据需要添加更多自定义异常类

3. 抛出异常

在你的应用中,当遇到异常情况时,可以抛出这些异常。

// 例如,在一个Controller中
@RestController
public class MyController {@GetMapping("/test")public String test() {if (someErrorCondition) {throw new SpecificException("Something went wrong!");}return "Success";}
}

4. 测试全局异常处理

运行你的Spring Boot应用,并通过触发异常条件(例如,访问上面的/test端点并确保someErrorConditiontrue)来测试异常处理。应用应该返回定义在全局异常处理类中的响应。

通过这种方式,你可以确保应用中的所有异常都被适当地捕获并以一致的方式处理,提高了代码的健壮性和维护性。

六、总结

pringboot里容器,控制器、拦截器、过滤器、监听器、全局异常,程序的执行顺序是怎么样的

在Spring Boot应用中,各个组件的执行顺序非常关键,特别是当涉及到容器、控制器、拦截器、过滤器、监听器以及全局异常处理器时。以下是这些组件在处理HTTP请求时的一般执行顺序:

1. 过滤器(Filter):

  • 过滤器首先介入请求处理过程。

  • 它们在Servlet层面上运行,因此它们在Spring的DispatcherServlet开始处理请求之前就已经开始工作了。

  • 过滤器通常用于请求的预处理,如日志记录、安全检查、请求修改等。

  • 它们也可以对响应进行后处理。

2. 拦截器(Interceptor):

  • 拦截器工作在Spring的上下文中,因此它们在DispatcherServlet处理请求之后、控制器(Controller)处理请求之前被调用。

  • 拦截器可以对特定的URL模式应用预处理和后处理逻辑。

  • 它们通常用于处理跨关注点的任务,如日志记录、性能统计、权限检查等。

3. 控制器(Controller):

  • 控制器是处理请求的核心,负责处理具体的业务逻辑。

  • 它接收输入,并提供对应的模型数据和视图。

4. 全局异常处理器(Global Exception Handler):

  • 如果在执行Controller逻辑或之前的步骤中抛出了异常,全局异常处理器将介入处理。

  • 它定义了应用程序的全局异常处理策略,确保异常情况能够被优雅地处理。

5. Spring事件和监听器(Listeners):

  • 监听器通常用于处理应用级别的事件,如应用启动或关闭事件。

  • 它们并不直接介入单个HTTP请求的处理流程,而是在应用的生命周期中起作用。

  • 例如,监听器可以在应用启动时执行某些初始化任务。

6. 请求的后处理:

  • 在Controller处理请求之后,拦截器的后处理方法将被调用。

  • 接着,过滤器可能对响应进行后处理。

  • 最后,响应被发送回客户端。

这个顺序确保了Spring Boot应用能够灵活地处理各种跨切面的关注点,同时也保证了业务逻辑的集中和清晰。每个组件都有其独特的作用和责任,共同构成了Spring Boot应用强大而灵活的基础。

过滤器和拦截器谁先执行

在Spring Boot(或更广泛地说,在任何基于Spring的Web应用程序)中,过滤器(Filter)通常先于拦截器(Interceptor)执行。这是因为过滤器和拦截器在请求处理的流程中处于不同的层级:

  1. 过滤器(Filter):

过滤器是基于Java Servlet API的一部分,它在请求进入Spring的DispatcherServlet之前就开始工作。

它们是在Servlet容器级别处理请求和响应的,这意味着它们在Spring的Web上下文之外执行。

过滤器可以对几乎所有的请求进行操作,不仅仅是那些映射到Spring控制器的请求。

  1. 拦截器(Interceptor):
  • 拦截器是Spring框架的一部分,它们在Spring的DispatcherServlet处理请求之后,且在请求到达具体的Controller之前开始工作。

  • 它们更加集成于Spring的Web上下文中,可以利用Spring的各种特性,例如依赖注入。

  • 拦截器通常用于处理与Spring管理的控制器相关的更细粒度的操作。

因此,在一个标准的Spring Boot Web应用程序中,请求首先通过一系列过滤器,然后才被Spring的DispatcherServlet处理,之后可能经过一个或多个拦截器,最后到达目标控制器。同样地,在响应返回客户端之前,它会先通过拦截器,然后再通过过滤器。

哪种情况下用过滤器、哪种情况用拦截器

在Spring Boot应用中,选择使用过滤器(Filter)还是拦截器(Interceptor)取决于你要解决的问题和所需的功能。下面是各自的用途和适用场景的简要概述:

过滤器(Filter**)

过滤器基于Java Servlet API,适用于处理通用的HTTP请求和响应。主要用于:

  1. 请求日志和审计:
  • 由于过滤器处理所有进入应用的请求,它们非常适合进行请求记录和审计。
  1. 请求和响应的修改:
  • 可以修改HTTP请求和响应的头部和数据。
  1. 认证和授权:
  • 例如,JWT(Json Web Token)的验证通常在过滤器中实现。
  1. 跨域资源共享(CORS)
  • 处理跨源请求,例如设置响应头。
  1. 错误处理:
  • 在请求到达Spring上下文之前处理错误。

拦截器(Interceptor)

拦截器是Spring框架的一部分,适用于与Spring上下文和特定控制器相关的操作。主要用于:

  1. 业务逻辑前后的处理:
  • 在控制器执行前后添加逻辑,如性能监控、日志记录等。
  1. 访问控制:
  • 在方法执行前,基于Spring的安全上下文进行细粒度的控制。
  1. 国际化:
  • 在请求处理之前进行语言设置。
  1. 主题(Theme)解析:
  • 用于Web应用的主题解析。
  1. 数据绑定前的准备工作
  • 例如,设置线程局部变量等。

总结

  • 使用过滤器:当你需要在Servlet级别上进行处理,影响所有请求,或者在Spring上下文之外操作时。

  • 使用拦截器:当你需要在Spring的上下文中进行更细粒度的控制,尤其是与特定控制器的交互相关时。

在实际应用中,你可能会发现两者都有其独特的用途,并且它们可以在同一个应用中共存,各司其职。

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

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

相关文章

uniapp 云打包 生成安卓证书文件

现在使用uniapp来开发小程序&#xff0c;H5&#xff0c;APP越来越多了&#xff0c;目前开发了一款APP&#xff0c;使用的也是uniapp。在此记录下用uniapp开发app云打包时约到的一些问题吧。 前因是我司安卓同学休产假&#xff0c;像云打包时需要的证书文件只能自己动手来搞。看…

index加上alias

查询index记录 POST prod-lumi-demo3-alias*/_search {"size": 1000,"query": {"match_all": {}},"sort": [{"ts": {"order": "desc"}}] }给指定index加上或者删除某一alias POST /_aliases {"a…

【C语言】【二级】移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p的数组元素平移到数组的最后...

题目 请编写函数fun,函数的功能是:移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p(含p, p小于等于n-1)的数组元素平移到数组的最后。 例如&#xff0c;一维数组中的原始内容为:1,2,3,4,5,6,7,8,9,10;p的值为3。移动后&#xff0c;一维数组中的内容应为:5,6,7,8,9,10…

算法-贪心思想

贪心的思想非常不好解释&#xff0c;而且越使用权威的语言解释越难懂。而且做题的时候根据自己的理解可能直接做出来&#xff0c;但是非要解释一下怎么使用的贪心的话&#xff0c;就懵圈了。一般来说&#xff0c;贪心的题目没有固定的套路&#xff0c;一题一样&#xff0c;不过…

了解应用层的HTTP协议与HTTPS协议,在常规请求的应用中Get与Post的区别

一、HTTP协议 1、http协议的特性2、http协议的请求 请求行 GET请求POST 请求(人脸识别方案)两个请求的区别本质区别&#xff1a; &#xff08;1&#xff09;url 携带的参数是否可见&#xff1a;&#xff08;2&#xff09;参数传递方式&#xff08;3&#xff09;缓存性&#xf…

Java Socket编程:实现网络通信

引言&#xff1a; 在当今数字化时代&#xff0c;网络通信已经成为了人们生活中不可或缺的一部分。Java Socket编程是一种基于TCP/IP协议的网络通信技术&#xff0c;通过它我们可以实现不同计算机之间的数据传输和通信。本文将介绍Java Socket编程的基本概念、原理和实现方法&am…

【Maven】清理 maven 仓库

初始情况下&#xff0c;我们的本地仓库是没有任何jar包的&#xff0c;此时会从私服去下载&#xff08;如果没有配置&#xff0c;就直接从中央仓库去下载&#xff09;。 可能由于网络的原因&#xff0c;jar包下载不完全&#xff0c;这些不完整的jar包都是以lastUpdated结尾。此…

rsync 一个可以让你抛弃scp的工具

目录 1. 基本语法 2. 例子 本地同步 本地同步并压缩传输 本地同步仅复制更新过的文件 本地同步保留软链接 通过SSH进行远程同步 模拟执行同步 3. 注意事项 rsync&#xff08;Remote Sync&#xff09;是一个用于在本地和远程系统之间同步文件和目录的工具。它使用一个远…

JVM arthas下载工具

工具下载地址 链接&#xff1a;https://pan.baidu.com/s/1qkn9HabhuwTiwbKVQ7BXnA?pwdv5ww 提取码&#xff1a;v5ww 启动语句 java -jar arthas-boot.jar输入你的线程&#xff0c;这里是2 dashboardJVM优化 堆的初始大小 最大大小 年轻代的大小 线程栈大小 新生代、伊甸…

娱乐类直播平台

娱乐类直播是一种以娱乐为主要内容的直播形式&#xff0c;包括音乐、舞蹈、游戏、搞笑、访谈等。这种直播形式通常由主播在平台上进行表演&#xff0c;吸引观众的关注和互动。 在娱乐类直播中&#xff0c;主播通常会通过展示自己的才艺、技能或者与观众进行互动来吸引关注。一…

vue-cli创建项目运行报错this[kHandle] = new _Hash(algorithm, xofLen);(完美解决)

1&#xff1a;问题出现的原因 出现这个问题是node.js 的版本问题&#xff0c;因为 node.js V17开始版本中发布的是OpenSSL3.0, 而OpenSSL3.0对允许算法和密钥大小增加了严格的限制&#xff0c;可能会对生态系统造成一些影响。故此以前的项目在使用 nodejs V17以上版本后会报错。…

聊天注意事项

聊天成功的核心就是双方都能舒服 有些人不会聊天是缺乏引导性 聊天聊两句话就没了 聊天要把话题引导向对方 从倾诉者变为倾听者 才能不断交流 沟通不是一个人的独角戏 每个人都渴望被理解 要注意倾听别人说的话 不要只顾自己说一大堆&#xff0c;别人都瞌睡了 不要查户口式问…

flask web学习之flask与http(一)

文章目录 一、请求响应循环二、HTTP请求1. 请求报文2. request对象3. 在flask中处理请求3.1 路由匹配3.2 设置监听的http方法3.3 URL处理 三、请求钩子 一、请求响应循环 每一个web应用都包含这种处理方式&#xff0c;请求-响应循环&#xff1a;客户端发出请求&#xff0c;服务…

rvos 3编译与链接

做下面的两个练习需要&#xff1a; 在vmvb上装一个ubuntu会gcc、vi的基本使用 用vi写一个hello.cgcc -o hello.creadelf -h hello.oreadelf -S hello.oobjdump -S hello.o 用vi编辑一个test.cgcc -c test.creadelf -S test.o.text:代码 .data:初始化的全局变量和静态变量…

MYSQL练题笔记-高级查询和连接-连续出现的数字

一、题目相关内容 1&#xff09;相关的表和题目 2&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 其实这一部分的题目很简单&#xff0c;但是没啥思路啊&#xff0c;怎么想都想不通&#xff0c;还是看题解吧&#xff0c;中等题就是中等题…

力扣215. 数组中的第K个最大元素

堆排序 前言 面试中著名的 TopK 排序&#xff1b;常见的解法有冒泡排序、堆排序&#xff1b;更深入的思路可以参考&#xff1a;拜托&#xff0c;面试别再问我TopK了&#xff01;&#xff01;&#xff01;使用了堆排序的算法&#xff0c;关于堆可以参考&#xff1a;堆数据结构的…

Linux 命令chgrp chown chmod

chgrp chown chmod 介绍 chgrp : 修改文件所属用户组 chown : 修改文件拥有者 chmod : 修改文件权限1 chgrp 命令功能: chgrp命令用来改变文件或目录所属的用户组。该命令用来改变指定文件所属的用户组。其中&#xff0c;组名可以是用户组的id&#xff0c;也可以是用户组的组…

openEuler 22.03 升级openssh9.5

yum安装编译依赖的组件 yum install -y rpm-build gcc gcc-c glibc glibc-devel openssl-devel openssl pcre-devel zlib zlib-devel make wget krb5-devel pam-devel libX11-devel libXt-devel initscripts libXt-devel gtk2-devel lrzsz建立编译目录 mkdir -pv /root/rpm…

22 最长回文子串的3中解决方式

问题描述&#xff1a;给你一个字符串s,找到s中最长的回文子串 暴力求解&#xff1a;通过两个循环遍历所有的子串&#xff0c;找到最长的那个子串并进行记录后返回 Boolean isPalindrome(String s,int indexStart,int indexEnd) { if(indexStartindexEnd) { return true; } in…

使用 TypeChain 从智能合约 ABI 生成类型声明

前言 web3 项目中&#xff0c;前端不可缺少地需要调用智能合约的代码&#xff0c;但是智能合约只有合约地址及对应的 ABI 文档&#xff0c;而没有相应的 typescript 类型声明。本文讲述如何使用 typechain 将智能合约的 ABI 文件自动生成类型声明&#xff0c;这样可以在项目中…