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不起作用的问题,也很可能是因为版本问题。

相关文章
|
9月前
|
Java 应用服务中间件 Spring
【Spring Boot系列】-Spring Boot过滤器Filter
【Spring Boot系列】-Spring Boot过滤器Filter
157 0
|
11月前
|
Java Spring
Filter 不能利用spring 注入
Filter 不能利用spring 注入
|
12月前
|
XML 缓存 前端开发
Spring Boot2.x-12 Spring Boot2.1.2中Filter和Interceptor 的使用
Spring Boot2.x-12 Spring Boot2.1.2中Filter和Interceptor 的使用
37 0
|
12月前
|
Java 数据安全/隐私保护 Spring
Spring Boot中使用过滤器
对于前后端分离的项目来说跨域是一个难题,对于跨域问题有多中解决方案,比如JSONP,网关支持等等。主要介绍如何使用过滤器来解决跨域问题。
104 0
|
12月前
|
Java Spring
spring cloud gateway Filter拦截器
spring cloud gateway Filter拦截器
562 0
|
Java API Spring
在spring boot中添加servlet filter *Listener
在spring boot中添加servlet filter *Listener
在spring boot中添加servlet filter *Listener
|
Java Spring
如何在spring-boot项目里面添加filter
如何在spring-boot项目里面添加filter
如何在spring-boot项目里面添加filter
|
Java Spring
Spring Boot filter
Spring Boot filter
|
存储 SQL 安全
Spring Boot中Spring data注解的使用
Spring Boot中Spring data注解的使用
|
Web App开发 Java 容器
spring 过滤器 Filter
简介 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。 使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据。 WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如JSP,Servlet,静态图片文件或静态HTML文件进行拦截,从而实现一些特殊功能。
11267 0