Spring Boot 整合过滤器拦截器

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

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. 配置过滤器顺序和优先级

可以通过FilterRegistrationBeansetOrder()方法设置过滤器的排序值。排序值越小优先级越高会先执行。

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. 配置拦截器顺序和优先级

可以通过InterceptorRegistryorder()方法设置拦截器的排序值。排序值越小优先级越高会先执行。

registry.addInterceptor(myInterceptor).order(0); // 设置排序值为0表示最高优先级

也可以通过拦截器的名字约定排序如LogInterceptor和AuthInterceptor字母A比L前面所以AuthInterceptor会比LogInterceptor先执行。

5. 多个拦截器的应用

一个URL可以配置多个拦截器它们按照添加的顺序依次执行。如果前一个拦截器返回false则后续的拦截器不会执行。

以下是一个Spring Boot整合拦截器的实战应用该示例演示了如何使用拦截器来实现用户登录验证功能

6. preHandle、postHandle、afterCompletion三者的区别

preHandlepostHandleafterCompletion是Spring MVC中的拦截器Interceptor接口org.springframework.web.servlet.HandlerInterceptor的三个方法它们在请求处理的不同阶段执行分别用于实现预处理逻辑、后处理逻辑和清理工作。

  1. preHandle:

    • 执行时机在目标Controller方法调用之前。
    • 返回值布尔值。如果返回true则允许请求继续进行如果返回false则中断请求流程后续的拦截器和目标方法都不会被执行。
    • 用途通常用于权限检查、登录验证等操作决定是否允许请求到达Controller。
  2. postHandle:

    • 执行时机在目标Controller方法调用之后视图渲染之前。
    • 返回值无。
    • 用途可以修改ModelAndView对象添加或修改模型数据但不能改变响应状态码和头信息。常用于对处理器方法的后处理比如修改返回给客户端的数据。
  3. 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

这说明过滤器先执行然后才是拦截器。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6