SpringBoot——过滤器和拦截器

目录

过滤器

实现过滤器

WebFilter注解

SpringBoot配置过滤器 

拦截器概念

作用

入门拦截器

简化写法 

拦截器的执行流程

多拦截器的执行顺序


过滤器

    Filter是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制过滤敏感词汇压缩响应信息等一些高级功能。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。

    使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。接下来介绍,在SpringBoot如何实现过滤器.

实现过滤器

WebFilter注解

    使用该注解进行配置,启动项目时会自动扫描:

@WebFilter(urlPatterns = "/*",filterName ="filtername" )
public class SrvletFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("f00000000000000000000000000000000");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("1111111111111111111111111111");
    }

    @Override
    public void destroy() {
    }
}

But

    该注解是由Servlet提供的,启动项目时并不会生效,所以还要在启动类加上注解:

@ServletComponentScan("过滤器所在的包"),让过滤器生效。

@SpringBootApplication
@ServletComponentScan("com.cc.boot1.filter")
public class Boot1Application {
    public static void main(String[] args) {
        SpringApplication.run(Boot1Application.class, args);

    }
}

SpringBoot配置过滤器 

    该方法和上面一种的filter类的差距仅仅是没有@WebFilter注解,但是要写一个配置类对过滤器进行配置。

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<Ljq> a(){
        FilterRegistrationBean<Ljq> a = new FilterRegistrationBean<>();
        a.setFilter(new Ljq());
        a.addUrlPatterns("/*");
        a.setName("glqglq");
        //设置执行顺序,值越小,越优先
        a.setOrder(1);
        return a;
    }
}

拦截器概念

    拦截器(Interceptor)是一种用于动态拦截请求处理流程的机制。它允许开发者在请求到达控制器(Controller)之前或响应返回给客户端之后,对请求和响应进行预处理和后处理。拦截器是AOP(面向切面编程)思想在Spring MVC中的具体实现之一。

作用

拦截器主要用于在请求处理流程中的特定点执行自定义逻辑,其作用包括但不限于:

  1. 权限验证:检查用户是否拥有访问某个资源的权限。
  2. 日志记录:记录请求和响应的详细信息,便于问题追踪。
  3. 请求预处理:在请求到达控制器之前对请求数据进行修改或补充。
  4. 响应后处理:在响应返回给客户端之前对响应数据进行修改或添加额外的头信息。

 拦截器和过滤器的区别

归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术

拦截内容不同:Filter对所有访问进行增强,Interceptor仅对SpringMVC的访问进行增强

入门拦截器

    在controller包下新建Interceptor包,在里面编写一个类,实现HandlerInterceptor接口,重写里面的三个方法

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Spring MVC拦截器,用于在请求处理的不同阶段执行特定操作。
 * 本拦截器通过实现HandlerInterceptor接口,提供了请求前处理、请求后处理以及请求完成后的回调方法。
 * 使用@Component注解声明为Spring管理的组件,会自动被Spring容器检测并注册为拦截器。
 */
@Component
public class ProjectInterceptor implements HandlerInterceptor {

    /**
     * 在请求处理之前执行(Controller方法调用之前)
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param handler  被调用的处理器对象
     * @return boolean 返回true表示继续流程,返回false则中断流程
     * @throws Exception 可能抛出的异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("perHandle...");
        return true;
    }

    /**
     * 在整个请求处理完成后执行(视图渲染结束后)
     * 主要用于资源清理、统计信息收集等收尾工作
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param handler  被调用的处理器对象
     * @param ex       处理过程中抛出的异常(如果有)
     * @throws Exception 可能抛出的异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }

    /**
     * 在请求处理之后,视图渲染之前执行(Controller方法调用之后)
     * @param request      HTTP请求对象
     * @param response     HTTP响应对象
     * @param handler      被调用的处理器对象
     * @param modelAndView 模型和视图对象,可用于修改模型数据或视图(可为null)
     * @throws Exception 可能抛出的异常
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }
}

    在配置包下创建类,继承WebMvcConfigurationSupport,重写addResourceHandlers

 和addInterceptors

import com.cc.controller.interception.ProjectInterceptor;
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.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * Spring MVC 配置类,用于自定义Web配置
 * 继承WebMvcConfigurationSupport类可覆盖默认的MVC配置
 * 注意:在Spring Boot项目中,更推荐实现WebMvcConfigurer接口替代继承此类
 */
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;  //注入拦截器

    /**
     * 配置静态资源处理
     * 将/pages/**路径的请求映射到类路径下的/pages目录
     * @param registry 资源处理器注册器,用于管理静态资源路径映射
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        //过滤访问静态资源
        // 注册projectInterceptor拦截器,并设置拦截路径
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages");
    }

    /**
     * 注册自定义拦截器并配置拦截规则
     * @param registry 拦截器注册器,用于管理请求拦截规则
     */
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(projectInterceptor).addPathPatterns("/users","/users/*");
    }
}

接下来尝试发送请求:

说明拦截器可以在方法的前和后增强方法。

再次发送请求

 并没有被拦截,原因是:

 添加拦截路径即可:

简化写法 

    前面新建了SpringMVC配置类,继承的是WebMvcConfigurationSupport,该部分可以直接写在SpringMVC配置类中,实现WebMvcConfigurer接口,重写addInterceptor方法

@Configuration
@ComponentScan({"com.cc.controller"})  //不加载SpringMvcSupport
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(projectInterceptor).addPathPatterns("/users","/users/*");
    }
}

拦截器的执行流程

多拦截器的执行顺序

    当配置多个拦截器时,会形成拦截器链。

直接复制前面写的拦截器,修改,并对它进行配置:

重新发送请求,就可以观察到拦截器的执行顺序:

由此可得拦截器的执行顺序:

  • 拦截器的运行顺序参照拦截器的添加顺序为准
  • 执行了controller后执行的顺序相反
  • 当拦截器出现对原始数据的拦截,后面的拦截器均会终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作