Spring 中 Filter 使用

简介: 要使用Filter,首先我们应该了解过滤器与拦截器的区别

要使用Filter,首先我们应该了解过滤器与拦截器的区别

区别如下:

1 、拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2 、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

3 、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

4 、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

5 、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

在 Spring Boot中使用Filter有两种方法。

在 Spring boot中使用Filter积累了一下的经验,首先,业务场景是,客户采用yml文件上传到系统,系统根据上传到的yml文件生成动态接口,以后用户使用动态接口进行业务操作。

这个业务的思路是:用户请求动态接口时,需要给他过滤到,不管是拦截到还是过滤到,不能让他到servlet的层面,让他报404,在拦截到之后进行业务的处理,然后直接返回。

最终选用了Filter,因为拦截器根据网上的demo进行配置后,并不能拦截到请求(这个在后文中会讲到),其实由于项目赶的比较紧,没有太多时间进行思考,其实针对于上面拦截器和过滤器的比较来说,使用拦截器会更好,因为由于业务需要,后面的版本可能需要拦截到action的上下文并访问到上下文的对象,而拦截器是做不到的。


下面是我在使用Filter的过程中踩过的坑:

由于Springboot的一大优点就是使用注解来生命很方便。于是就有了以下的一个方式来进行声明:

@Slf4j
@WebFilter(filterName = "urlFilter",urlPatterns = "/api/cds/common/*")
public class URLFilter implements Filter {
   
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
   

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
   
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String url = request.getRequestURI();
        log.info("the url of request is {}",url);
        //根绝url拿到API接口的配置 拿到 ApiInfoDTO
        //业务处理。。。
    }

    @Override
    public void destroy() {
   

    }
}

上面的主要的步骤就是实现了Filter接口,实现三个主要的方法,最主要的就是添加了 @WebFilter(filterName = "urlFilter",urlPatterns = "/api/cds/common/*")

以下是启动类的代码:

@SpringBootApplication
@ServletComponentScan
public class IscCdsServiceBootstrap {
   
    public static void main(String[] args) {
   
        IsysCoreSpringApplication.run(IscCdsServiceBootstrap.class, args);
    }
}

参照网上的说法是,加上@ServletComponentScan后,Spring容器就会创建Filter的实例,但是在调试过程中并没有创建自定义的Filter的bean,又有网上说,需要在自定义的Filter类上加上@Component或者是@Configuration注解,加上后,能够创建相关的bean对象,但是@WebFilter注解就失效了,路径匹配也就失效了,所有的请求路径都会被过滤,这肯定是不能够符合我的要求的。

这主要是因为加上了 @Component或者@Configuration之后,Spring在创建Filter这个bean的时候,就不会再走@WebFilter了,他就默认过滤全部的路径了。

由于时间比较急,所以就没来得急去深究,我就采用了另一种方式,采用配置类的形式进行创建的:

@Slf4j
public class URLFilter implements Filter {
   
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
   

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
   
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String url = request.getRequestURI();
        log.info("the url of request is {}",url);
        //根绝url拿到API接口的配置 拿到 ApiInfoDTO
        ApiInfoDTO apiInfoDTO = commonService.getApiInfo(url);
        //业务处理。。。
    }

    @Override
    public void destroy() {
   

    }
package com.isyscore.bigdatagroup.isccdsservice.config;

import com.isyscore.bigdatagroup.isccdsservice.filter.URLFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FilterConfig {
   
    @Bean
    public FilterRegistrationBean authFilterRegistrationBean() {
   
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setName("urlFilter");
        registrationBean.setFilter(urlFilter());
        registrationBean.setOrder(1);
        List<String> urlList = new ArrayList<String>();
        //设置拦截路径
        urlList.add("/api/cds/common/*");
        registrationBean.setUrlPatterns(urlList);
        return registrationBean;
    }

    @Bean
    public URLFilter urlFilter(){
   
        return new URLFilter();
    }
}

这样的话就能够根据自定义的路径规则进行过滤了。


而对于拦截器来说,也会出现上述这种问题,根绝拦截器的问题来说,这可能是Spring的版本问题:

很多网上都采用以下的方法进行配置拦截器,你会发现按照上面的方式进行配置后,并不能够实现拦截,根本就没有走拦截器:

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: ");
    }
}

然后注册自定义的拦截器:

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport{
   

     /**
     * 注册自定义拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
   

           registry.addInterceptor(new InterceptorDemo2()).addPathPatterns("/**");
        registry.addInterceptor(new InterceptorDemo()).addPathPatterns("/**");
    }
 }

配置好后,你会发现并不能欧拦截到任何路径,也就是说,拦截器不起作用。这是因为 WebMvcConfigurationSupport 这个类,再行版本的Spring中就已经启用了。

解决办法是:

  1. 把WebMvcConfigurationSupport改为WebMvcConfigurer这个接口
  2. 把HandlerInterceptorAdapter改为HandlerInterceptor这个类就好了。

针对于Filter不起作用的问题,也很可能是因为版本问题。

相关文章
|
6月前
|
JSON 缓存 Java
Springboot 之 Filter 实现超大响应 JSON 数据压缩
Springboot 之 Filter 实现超大响应 JSON 数据压缩
166 0
|
26天前
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
26天前
|
搜索推荐 Java Spring
Spring Filter深度解析
【10月更文挑战第21天】Spring Filter 是 Spring 框架中非常重要的一部分,它为请求处理提供了灵活的控制和扩展机制。通过合理配置和使用 Filter,可以实现各种个性化的功能,提升应用的安全性、可靠性和性能。还可以结合具体的代码示例和实际应用案例,进一步深入探讨 Spring Filter 的具体应用和优化技巧,使对它的理解更加全面和深入。
|
5月前
|
Java API 数据安全/隐私保护
在Spring Boot中,过滤器(Filter)是一种非常有用的组件
在Spring Boot中,过滤器(Filter)是一种非常有用的组件
84 6
|
6月前
|
安全 Java 开发者
[AIGC] Spring Filter 过滤器详解
[AIGC] Spring Filter 过滤器详解
|
6月前
|
Java
springboot项目出现Exception in thread “main“ java.lang.NoClassDefFoundError: javax/servlet/Filter
springboot项目出现Exception in thread “main“ java.lang.NoClassDefFoundError: javax/servlet/Filter
241 0
|
6月前
|
存储 JSON NoSQL
Springboot 之 Filter 实现 Gzip 压缩超大 json 对象
Springboot 之 Filter 实现 Gzip 压缩超大 json 对象
120 0
|
6月前
|
前端开发 Java 容器
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
126 0
|
6月前
|
XML Java 数据格式
如何在Filter中使用Spring容器中的Bean?
如何在Filter中使用Spring容器中的Bean?
237 0
|
Java Spring
Spring Cloud Gateway 源码剖析之Filter Chain过滤器链
Spring Cloud Gateway 源码剖析之Filter Chain过滤器链
284 0
下一篇
无影云桌面