Spring Boot 整合过滤器拦截器
Spring Boot 整合过滤器
1. 简介
在Spring Boot应用中,我们可以使用Servlet API中的Filter来实现一些全局的功能,比如日志记录、跨域处理、权限验证等。
2. 创建自定义过滤器
创建一个类,实现javax.servlet.Filter
接口,并重写其中的方法。
package com.example.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化过滤器时可以做一些准备工作
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 在这里对请求进行预处理,或者对响应进行后处理
System.out.println("MyFilter is running");
// 调用FilterChain对象的doFilter方法,将请求传递给下一个过滤器或Servlet
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 过滤器被销毁前可以做一些清理工作
}
}
3. 注册过滤器到Spring Boot容器
在Spring Boot的配置类中,通过FilterRegistrationBean
将过滤器注册到Spring Boot的IoC容器中。
package com.example.config;
import com.example.filter.MyFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> filterRegistration() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*"); // 设置过滤器作用的URL路径
return registration;
}
}
4. 配置过滤器顺序和优先级
可以通过FilterRegistrationBean
的setOrder()
方法设置过滤器的排序值。排序值越小,优先级越高,会先执行。
registration.setOrder(0); // 设置排序值为0,表示最高优先级
也可以通过过滤器的名字约定排序,如LogFilter和AuthFilter,字母A比L前面,所以AuthFilter会比LogFilter先执行。
5. 多个过滤器的应用
一个URL可以配置多个过滤器,使用逗号分隔。当设置多个过滤器时,全部验证通过,才视为通过。
registration.addUrlPatterns("/path1", "/path2");
部分过滤器可以指定参数,如perms、roles等。
6. 总结
通过上述步骤,我们成功地在Spring Boot应用中整合了自定义的过滤器。这个过滤器会在所有请求进入Controller之前运行,提供了灵活的扩展点来添加全局功能。
以下是一个Spring Boot整合拦截器的详细文档,包括最新的概念和示例代码:
Spring Boot 整合拦截器
1. 简介
在Spring MVC框架中,我们可以使用Interceptor(拦截器)来实现一些全局的功能,比如日志记录、权限验证等。
2. 创建自定义拦截器
创建一个类,实现org.springframework.web.servlet.HandlerInterceptor
接口,并重写其中的方法。
package com.example.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
System.out.println("MyInterceptor is running for method: " + method.getMethod().getName());
}
return true; // 如果返回false,则中断后续流程
}
//Object handler: 这个参数代表了将要被调用的处理器。
//通常情况下,它是一个实现了HandlerMethod接口的对象,包含了目标方法的信息。
//你可以通过((HandlerMethod) handler).getMethod().getName()来获取目标方法的名字,
//或者通过((HandlerMethod) handler).getBean()来获取目标方法所在的bean。
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在这里对请求进行后处理,或者对响应进行预处理
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 这个方法会在整个请求完成以后被调用,无论是否有异常抛出
}
}
3. 注册拦截器到Spring Boot容器
在Spring Boot的配置类中,通过实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer
接口并重写其addInterceptors()
方法,将拦截器注册到Spring Boot的IoC容器中。
package com.example.config;
import com.example.interceptor.MyInterceptor;
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 InterceptorConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/**"); // 设置拦截器作用的URL路径
}
}
4. 配置拦截器顺序和优先级
可以通过InterceptorRegistry
的order()
方法设置拦截器的排序值。排序值越小,优先级越高,会先执行。
registry.addInterceptor(myInterceptor).order(0); // 设置排序值为0,表示最高优先级
也可以通过拦截器的名字约定排序,如LogInterceptor和AuthInterceptor,字母A比L前面,所以AuthInterceptor会比LogInterceptor先执行。
5. 多个拦截器的应用
一个URL可以配置多个拦截器,它们按照添加的顺序依次执行。如果前一个拦截器返回false
,则后续的拦截器不会执行。
以下是一个Spring Boot整合拦截器的实战应用,该示例演示了如何使用拦截器来实现用户登录验证功能:
6. preHandle、postHandle、afterCompletion三者的区别
preHandle
、postHandle
和afterCompletion
是Spring MVC中的拦截器(Interceptor)接口org.springframework.web.servlet.HandlerInterceptor
的三个方法,它们在请求处理的不同阶段执行,分别用于实现预处理逻辑、后处理逻辑和清理工作。
-
preHandle
:- 执行时机:在目标Controller方法调用之前。
- 返回值:布尔值。如果返回
true
,则允许请求继续进行;如果返回false
,则中断请求流程,后续的拦截器和目标方法都不会被执行。 - 用途:通常用于权限检查、登录验证等操作,决定是否允许请求到达Controller。
-
postHandle
:- 执行时机:在目标Controller方法调用之后,视图渲染之前。
- 返回值:无。
- 用途:可以修改ModelAndView对象,添加或修改模型数据,但不能改变响应状态码和头信息。常用于对处理器方法的后处理,比如修改返回给客户端的数据。
-
afterCompletion
:- 执行时机:在整个请求处理完成之后,包括视图渲染。
- 返回值:无。
- 用途:主要用于资源清理等收尾工作,如关闭数据库连接、清除缓存等。类似于try-catch-finally中的finally块。
这三个方法的关系可以用下面这张简化的时序图来表示:
+---------+ +----------+ +-------------+
| preHandle | ---> | Controller Method |
+---------+ +----------+ +-------------+
| | |
| V V
| +------------+ +--------------+
+-------->| postHandle | ---> | afterCompletion |
+------------+ +--------------+
总结来说,preHandle
主要负责前期的权限控制和决策,postHandle
用于对处理器方法返回的结果进行加工,而afterCompletion
则是用来做一些善后的工作。这三者共同构成了一个完整的请求处理链,在不同的阶段为应用提供了扩展点。
1. 拦截器实际应用
在这个实战应用中,我们将创建一个拦截器,用于检查每个请求是否已经通过了登录验证。如果没有通过验证,将返回401 Unauthorized响应。
2. 创建自定义拦截器
首先,我们创建一个名为LoginInterceptor
的类,实现org.springframework.web.servlet.HandlerInterceptor
接口,并重写其中的方法。
package com.example.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod method = (HandlerMethod) handler;
// 检查当前请求是否需要登录验证
if (method.getMethodAnnotation(LoginRequired.class) != null) {
// 获取当前登录用户的ID(这里假设已存在从session或token中获取用户ID的方法)
Object o = getUserId(request);
if (o == null) {
// 如果未登录,返回401 Unauthorized响应
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Please log in first.");
return false; // 中断后续流程
}
}
return true;
}
private Object getUserId(HttpServletRequest request) {
// 这里只是一个示例,实际项目中应根据实际情况从session或token中获取用户ID
return request.getSession().getAttribute("userId");
}
// 可以选择性地实现postHandle和afterCompletion方法
}
在上述代码中,我们定义了一个LoginInterceptor
类,它会在每个请求到达Controller之前运行。如果请求的方法上标记了@LoginRequired
注解,那么我们就检查当前用户是否已经登录。如果没有登录,就返回401 Unauthorized响应。
3. 注册拦截器到Spring Boot容器
接下来,在Spring Boot的配置类中,通过实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer
接口并重写其addInterceptors()
方法,将拦截器注册到Spring Boot的IoC容器中。
package com.example.config;
import com.example.interceptor.LoginInterceptor;
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 InterceptorConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); // 设置拦截器作用的URL路径
}
}
4. 创建登录验证注解
为了方便地为需要登录验证的Controller方法添加注解,我们可以创建一个名为LoginRequired
的注解。
package com.example.annotation;
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 LoginRequired {
}
5. 使用登录验证注解
现在,我们可以在Controller类的方法上使用@LoginRequired
注解,表示这个方法需要登录验证。
package com.example.controller;
import com.example.annotation.LoginRequired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user/profile")
@LoginRequired
public String getUserProfile() {
return "This is your profile.";
}
}
在上述代码中,getUserProfile
方法被标记了@LoginRequired
注解,所以只有登录用户才能访问这个方法。
6. 示例代码
完整的示例代码可以在GitHub上找到:https://github.com/yourusername/spring-boot-interceptor-login-example
7. 总结
通过上述步骤,我们成功地在Spring Boot应用中整合了一个自定义的拦截器,实现了用户登录验证功能。这个拦截器可以在全局范围内控制哪些请求需要登录验证,增强了应用的安全性。
6. 总结
通过上述步骤,我们成功地在Spring Boot应用中整合了自定义的拦截器。这个拦截器会在所有请求进入Controller之前运行,提供了灵活的扩展点来添加全局功能。
过滤器和拦截器执行的先后顺序
创建一个简单的过滤器(Filter):
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("Filter is running");
chain.doFilter(request, response);
}
}
然后在Spring Boot的配置类中注册这个过滤器:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> filterRegistration() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*");
return registration;
}
}
接下来,我们创建一个拦截器(Interceptor):
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
System.out.println("Interceptor is running for method: " + method.getMethod().getName());
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// ...
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// ...
}
}
最后,在Spring Boot的配置类中添加对拦截器的支持:
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 InterceptorConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
现在,当你发送一个HTTP请求到你的应用时,你会看到这样的输出:
Filter is running
Interceptor is running for method: yourControllerMethodName
这说明过滤器先执行,然后才是拦截器。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!