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 {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 在控制器执行前调用
System.out.println("preHandle: 请求前调用");
// 返回true继续流程,返回false中断流程
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// 在控制器执行后,视图渲染前调用
System.out.println("postHandle: 请求后调用");
}
@Override
public 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 {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器到Spring MVC机制,然后你可以决定拦截哪些URL路径
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
在这个例子中,MyInterceptor
会拦截所有的URL路径。你可以通过调整addPathPatterns
和excludePathPatterns
方法来自定义拦截和排除的路径。
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 {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化过滤器
System.out.println("MyFilter initialized");
}
@Override
public 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");
}
@Override
public 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 {
@Bean
public 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 {
@Override
public 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 Boot
的ApplicationReadyEvent
,这个事件在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
端点并确保someErrorCondition
为true
)来测试异常处理。应用应该返回定义在全局异常处理类中的响应。
通过这种方式,你可以确保应用中的所有异常都被适当地捕获并以一致的方式处理,提高了代码的健壮性和维护性。
六、总结
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)执行
。这是因为过滤器和拦截器在请求处理的流程中处于不同的层级:
- 过滤器(Filter):
过滤器是基于Java Servlet API的一部分,它在请求进入Spring的DispatcherServlet之前就开始工作。
它们是在Servlet容器级别处理请求和响应的,这意味着它们在Spring的Web上下文之外执行。
过滤器可以对几乎所有的请求进行操作,不仅仅是那些映射到Spring控制器的请求。
- 拦截器(Interceptor):
-
拦截器是Spring框架的一部分,它们在Spring的DispatcherServlet处理请求之后,且在请求到达具体的Controller之前开始工作。
-
它们更加集成于Spring的Web上下文中,可以利用Spring的各种特性,例如依赖注入。
-
拦截器通常用于处理与Spring管理的控制器相关的更细粒度的操作。
因此,在一个标准的Spring Boot Web应用程序中,请求首先通过一系列过滤器,然后才被Spring的DispatcherServlet处理,之后可能经过一个或多个拦截器,最后到达目标控制器。同样地,在响应返回客户端之前,它会先通过拦截器,然后再通过过滤器。
哪种情况下用过滤器、哪种情况用拦截器
在Spring Boot应用中,选择使用过滤器(Filter
)还是拦截器(Interceptor
)取决于你要解决的问题和所需的功能。下面是各自的用途和适用场景的简要概述:
过滤器(Filter**)
过滤器基于Java Servlet API,适用于处理通用的HTTP请求和响应。主要用于:
- 请求日志和审计:
- 由于过滤器处理所有进入应用的请求,它们非常适合进行请求记录和审计。
- 请求和响应的修改:
- 可以修改HTTP请求和响应的头部和数据。
- 认证和授权:
- 例如,JWT(Json Web Token)的验证通常在过滤器中实现。
- 跨域资源共享(CORS):
- 处理跨源请求,例如设置响应头。
- 错误处理:
- 在请求到达Spring上下文之前处理错误。
拦截器(Interceptor)
拦截器是Spring框架的一部分,适用于与Spring上下文和特定控制器相关的操作。主要用于:
- 业务逻辑前后的处理:
- 在控制器执行前后添加逻辑,如性能监控、日志记录等。
- 访问控制:
- 在方法执行前,基于Spring的安全上下文进行细粒度的控制。
- 国际化:
- 在请求处理之前进行语言设置。
- 主题(Theme)解析:
- 用于Web应用的主题解析。
- 数据绑定前的准备工作:
- 例如,设置线程局部变量等。
总结
-
使用过滤器:当你需要在Servlet级别上进行处理,影响所有请求,或者在Spring上下文之外操作时。
-
使用拦截器:当你需要在Spring的上下文中进行更细粒度的控制,尤其是与特定控制器的交互相关时。
在实际应用中,你可能会发现两者都有其独特的用途,并且它们可以在同一个应用中共存,各司其职。