springboot下使用拦截器和过滤器

本文详细介绍了SpringBoot下拦截器Interceptor和过滤器Filter的使用方法及区别。包括拦截器的实现、注册,过滤器的注解形式和代码注册方式,以及它们在应用中的场景和与监听器的比较。强调了拦截器的工作原理和执行顺序,以及在Spring框架中优先使用拦截器的原因。

1. 拦截器Interceptor

Spring MVC的拦截器(Interceptor)和Filter不同,但是也可以实现对请求进行预处理,后处理。先介绍它的使用,只需要两步:
1.1 实现拦截器
实现拦截器可以通过继承HandlerInterceptorAdapter类。如果preHandle方法return true,则继续后续处理。

public class InterceptorDemo extends HandlerInterceptorAdapter {


    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        StringBuffer requestURL = httpServletRequest.getRequestURL();
        System.out.println("前置拦截器1 preHandle: 请求的uri为:"+requestURL.toString());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器1 postHandle: ");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("拦截器1 afterCompletion: ");
    }
}

1.2 注册拦截器
实现拦截器后还需要将拦截器注册到spring容器中,可以通过implements WebMvcConfigurer,覆盖其addInterceptors(InterceptorRegistry registry)方法。记得把Bean注册到Spring容器中,可以选择@Component 或者 @Configuration。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer{

	 /**
     * 注册自定义拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        
       	registry.addInterceptor(new InterceptorDemo2()).addPathPatterns("/**");
        registry.addInterceptor(new InterceptorDemo()).addPathPatterns("/**");
    }
 }

注意这里注册了两个拦截器。这两个拦截器的执行顺序和配置顺序有关系,即先配置顺序就在前(感觉这样不太方便,但没有找到设置类似order的API)。

发起一个请求,在控制台可以看到拦截器生效:

前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle: 
拦截器2 postHandle: 
拦截器1 afterCompletion: 
拦截器2 afterCompletion:

1.3 拦截器的总结
1.3.1 工作原理
一个拦截器,只有preHandle方法返回true,postHandle、afterCompletion才有可能被执行;如果preHandle方法返回false,则该拦截器的postHandle、afterCompletion必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:

  • 所有的拦截器(Interceptor)和处理器(Handler)都注册在HandlerMapping中。
  • Spring MVC中所有的请求都是由DispatcherServlet分发的。
  • 当请求进入DispatcherServlet.doDispatch()时候,首先会得到处理该请求的Handler(即Controller中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。

1.3.2 拦截器工作流程

  • 正常流程:

      	1.Interceptor2.preHandle
      	2.Interceptor1.preHandle
      	3.Controller处理请求
      	4.Interceptor1.postHandle
      	5.Interceptor2.postHandle
      	6.渲染视图view
      	2.Interceptor1.afterCompletion
      	2.Interceptor2.afterCompletion
    
  • 中断流程
    如果在Interceptor1.preHandle中报错或返回false ,那么接下来的流程就会被中断,但注意被执行过的拦截器的afterCompletion仍然会执行。下图为Interceptor1.preHandle返回false的情况:

    前置拦截器2 preHandle: 用户名:null
    前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
    拦截器2 afterCompletion:
    

1.3.3 和Filter共存时的执行顺序
拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter。其顺序如下。

Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter

1.3.4 应用场景
拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

  • 登录验证,判断用户是否登录。
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
  • 处理cookie、本地化、国际化、主题等。
  • 性能监控,监控请求处理时长等。

2. 过滤器Filter

springboot下过滤器的使用有两种形式:
2.1 注解形式
创建一个Filter,并使用WebFilter注解进行修饰,表示该类是一个Filter,以便于启动类进行扫描的时候确认

@WebFilter(urlPatterns = "/*",filterName = "filter2")
public class FilterAnnotationTest implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器2开始初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器2开始工作");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("过滤器2销毁");
    }
}

然后在启动类上添加注解@ServletComponentScan,该注解用于自动扫描指定包下(默认是与启动类同包下)的WebFilter/WebServlet/WebListener等特殊类。
2.2 代码注册方式
同样编写Filter,但是不添加WebFilter注解,通过@Bean注入spring

public class FilterDemo implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        System.out.println("过滤器开始工作。。"+httpServletRequest.getRequestURL());
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("过滤器开始销毁");
    }
}

然后利用filterRegistrationBean来进行注册。也可以在代码里设置Order

@Configuration
public class FilterDemo {
    @Bean
    @Order(2)
    //spring boot会按照order值的大小,从小到大的顺序来依次过滤
    public FilterRegistrationBean configFilter(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new FilterDemo());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("sessionFilter");
        //filterRegistrationBean.setOrder(2);
        return filterRegistrationBean;
    }
    
}

2.3 过滤器filter和拦截器Interceptor的区别
spring的拦截器和servlet的过滤器有相似之处,都是AOP思想的体现,都可以实现权限检查,日志记录,不同的是

  1. 适用范围不同:Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器的使用范围就大得多
  2. 使用的资源不同:拦截器是属于spring的一个组件,因此可以使用spring的所有资源,对象,如service对象,数据源,事务控制等,而过滤器就不行
  3. 深度不同:Filter还在servlet前后起作用。而拦截器能够深入到方法前后,异常抛出前后,因此拦截器具有更大的弹性,所有在spring框架中应该优先使用拦截器。
    通过调试可以发现,拦截器的执行过程是在过滤器的doFilter中执行的,过滤器的初始化会在项目启动时执行。
过滤器开始工作。。http://localhost:8010/user/353434
前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle: 
拦截器2 postHandle: 
拦截器1 afterCompletion: 
拦截器2 afterCompletion: 
过滤器开始工作。。http://localhost:8010/favicon.ico

可以通过这个博客里的一张图来说明:
这里写图片描述

3. 监听器

监听器的简单使用如下:先编写监听器的实现:

@WebListener
public class WebListenerDemo implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("监听器初始化。。。。。。。。。。。。");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("监听器销毁。。。。。。。。。。。");
    }
}

监听session创建的监听器(可以用来统计在线人数)

@WebListener
public class SessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("。。。创建session成功");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("。。。销毁session");
    }
}

然后在启动类上添加注解@ServletComponentScan即可,当然也可以注册到spring容器中省却@ServletComponentScan注解。

@Configuration
public class ListenerConfig {
    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean() {
        ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
        slrBean.setListener(new WebListenerDemo());
        return slrBean;
    }

    @Bean
    public ServletListenerRegistrationBean sessionListenerRegistrationBean() {
        ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
        slrBean.setListener(new SessionListener());
        return slrBean;
    }
}


<think>首先,用户的问题是:"我想了解springboot项目中拦截器过滤器的区别 请问Spring Boot项目里拦截器过滤器的区别"。根据系统指令,我必须使用中文回答,确保行内数学表达式用$...$,独立公式用$$...$$,但这个问题是关于Spring Boot的,没有数学表达式,所以不需要。 用户提供了引用:[^1], [^2], [^3], [^4],这些是关于Spring Boot中过滤器拦截器的文章。作为AI,我应该基于这些引用我的知识来回答。 系统指令包括:"回答中引用的段落末尾自然地添加引用标识",所以我需要在回答中引用时添加引用标识如[^1]。 还要"生成相关问题",在回答结束时添加相关问题。 回答的结构要清晰,逐步解决问题,保证真实可靠。 关键点:用户想知道Spring Boot项目中拦截器过滤器的区别。 从引用中提取信息: - [^1]: 讨论过滤器拦截器的概念,提到它们用于预处理后处理HTTP请求响应,但有差异。 - [^2]: 专门比较过滤器(Filter)拦截器Interceptor)的区别。 - [^3]: 详细解释拦截器过滤器的工作原理、使用场景实现方法。 - [^4]: 提供一个示例,配置拦截器在登录验证中。 具体区别: - **过滤器(Filter)**: 是Servlet规范的一部分,在请求到达Servlet之前或响应发送之后执行。过滤器可以拦截所有请求,包括静态资源。在Spring Boot中,可以通过实现javax.servlet.Filter接口或使用FilterRegistrationBean注册。 - **拦截器Interceptor)**: 是Spring框架的一部分,在Spring MVC中执行。它作用于控制器(Controller)方法之前之后,以及视图渲染之前。拦截器只能拦截Spring管理的请求,不能拦截静态资源。 主要区别: 1. **作用范围**: - 过滤器:作用于整个Web应用,拦截所有请求,包括静态资源。 - 拦截器:作用于Spring MVC框架内,只拦截控制器处理的请求。 2. **执行顺序**: - 在请求处理中,过滤器先于拦截器执行。顺序是:Filter -> DispatcherServlet -> Interceptor -> Controller。 3. **配置方式**: - 过滤器:通过web.xml或FilterRegistrationBean注册。 - 拦截器:通过实现HandlerInterceptor接口并在WebMvcConfigurer中配置。 4. **依赖**: - 过滤器:不依赖Spring容器,是Servlet标准。 - 拦截器:依赖Spring容器,是Spring MVC的一部分。 5. **功能**: - 过滤器:主要用于通用处理如编码设置、日志记录、安全过滤(如登录验证)。 - 拦截器:更适合于Spring特定操作,如权限检查、数据绑定、异常处理。 从引用中提到: - [^2]: "过滤器(Filter)拦截器Interceptor)有什么区别?" 参考它。 - [^3]: 解释了工作原理使用场景。 回答结构: 1. **介绍**:简要说明过滤器拦截器的概念作用。 2. **详细区别**:列出关键区别点。 3. **总结**:归纳何时使用哪种。 4. **生成相关问题**:在结束时提出问题。 参考引用时自然添加,例如在提及特定点后添加[^1], [^2], etc。 最终添加相关问题。 </think>### Spring Boot项目中拦截器过滤器的区别 在Spring Boot项目中,过滤器拦截器都是用于处理HTTP请求的常用组件,但它们在工作原理、作用范围、执行顺序配置方式上存在显著差异。理解这些区别有助于开发者在实际应用中合理选择使用。以下我将基于引用内容,逐步解析两者的关键区别,并给出总结。 #### 1. **定义作用范围** - **过滤器(Filter)**: - 过滤器是Servlet规范的一部分(javax.servlet.Filter),作用于整个Web应用,包括静态资源(如CSS、JS文件)。它在请求到达Servlet之前或响应发送之后执行,主要用于通用预处理后处理,比如设置字符编码、记录日志、安全过滤(如登录验证)[^1][^2]。 - 在Spring Boot中,过滤器通常通过实现Filter接口并使用FilterRegistrationBean注册: ```java public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { // 预处理逻辑 chain.doFilter(request, response); // 继续执行链 // 后处理逻辑 } } ``` 然后在配置类中注册: ```java @Bean public FilterRegistrationBean<MyFilter> filterRegistrationBean() { FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new MyFilter()); bean.addUrlPatterns("/*"); // 拦截所有请求 return bean; } ``` - **拦截器Interceptor)**: - 拦截器是Spring MVC框架的一部分(HandlerInterceptor),仅作用于Spring管理的控制器(Controller)层。它在请求进入控制器方法之前、之后或视图渲染之前执行,主要用于Spring特定逻辑,如权限校验、数据绑定、异常处理[^2][^3]。 - 拦截器无法处理静态资源,因为它依赖DispatcherServlet。在Spring Boot中,通过实现HandlerInterceptor接口并在WebMvcConfigurer中配置: ```java public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 控制器方法执行前的逻辑 return true; // 返回true继续流程 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { // 控制器方法执行后、视图渲染前的逻辑 } } ``` 然后在配置类中注册拦截路径: ```java @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/**") // 拦截所有控制器路径 .excludePathPatterns("/login/**", "/static/**"); // 排除静态资源 } } ``` 参考[^4]中的登录验证示例。 #### 2. **执行顺序位置** - **执行流程**: - 在HTTP请求处理中,过滤器的执行先于拦截器。标准顺序为: 1. 过滤器(Filter)→ 2. DispatcherServlet(Spring MVC核心)→ 3. 拦截器Interceptor)→ 4. 控制器(Controller)[^1][^2]。 - 例如:一个请求首先被过滤器处理(如设置编码),然后传递给Spring的DispatcherServlet,再经过拦截器(如权限检查),最后到达控制器。 - **关键点**: - 过滤器在Servlet层执行,适用于所有Web请求。 - 拦截器在Spring MVC层执行,仅作用于控制器方法调用的前后阶段[^3]。 #### 3. **配置方式依赖** - **配置方式**: - 过滤器:通过Servlet原生方式(如web.xml)或Spring Boot的FilterRegistrationBean注册。不依赖Spring容器,可以独立于Spring框架使用[^1]。 - 拦截器:必须通过Spring的WebMvcConfigurer接口配置(如addInterceptors方法)。它依赖于Spring IoC容器,只能用于Spring Boot项目中[^3][^4]。 - **依赖关系**: - 过滤器:基于Java EE标准,无需Spring支持。 - 拦截器:是Spring MVC的一部分,需要Spring上下文管理其生命周期。 #### 4. **使用场景优缺点** - **过滤器适用场景**: - 全局性处理:如跨域设置(CORS)、请求压缩、日志记录。 - 安全过滤:例如登录验证(但需注意,过滤器更适合基础验证)。 - 优点:覆盖范围广,能处理静态资源。 - 缺点:无法访问Spring上下文,难以处理Spring特定逻辑(如依赖注入Bean)[^1][^2]。 - **拦截器适用场景**: - Spring相关逻辑:如权限控制(如基于用户的角色校验)、数据校验、性能监控。 - 优点:与Spring无缝集成,可直接使用@Autowired注入Bean。 - 缺点:无法拦截静态资源,仅限于控制器请求[^3][^4]。 #### 5. **总结对比** | 特点 | 过滤器(Filter) | 拦截器Interceptor) | |--------------------|----------------------------------------|----------------------------------------| | **所属规范** | Servlet规范 | Spring MVC框架 | | **作用范围** | 所有HTTP请求(包括静态资源) | 仅Spring控制器请求 | | **执行顺序** | 先于拦截器执行 | 在过滤器之后、控制器前后执行 | | **配置方式** | FilterRegistrationBean或web.xml | WebMvcConfigurer.addInterceptors | | **依赖容器** | 不依赖Spring(Servlet容器) | 依赖Spring IoC容器 | | **适用场景** | 通用底层处理(如编码、日志) | Spring逻辑处理(如权限、数据绑定) | | **静态资源处理** | 支持 | 不支持 | 在实际项目中: - 优先使用拦截器处理业务逻辑(如权限校验),因为它与Spring集成更紧密[^4]。 - 过滤器更适合底层基础设施任务(如请求过滤),尤其是需要处理静态资源时[^1]。
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值