SpringBoot实现过滤器Filter的三种方式

过滤器 Filter 是 Web 三大组件之一,也是项目常用到的工具,本文主要介绍一下 Filter的概念以及常见的使用方式。

过滤器Filter

过滤器 Filter 由 Servlet 提供,基于函数回调实现链式对网络请求与响应的拦截与修改。由于基于 Servlet ,其可以对web服务器管理的几乎所有资源进行拦截(JSP、图片文件、HTML 文件、CSS文件等)。
定义一个过滤器,需要实现 javax.servlet.Filter 接口。
Filter 并不是一个 Servlet,它不能直接向客户端生成响应,只是拦截已有的请求,对不需要或不符合的信息资源进行预处理。

过滤器可以定义多个,按照过滤器链顺序调用:

Filter 的生命周期

init(): 初始化Filter 实例,Filter 的生命周期与 Servlet 是相同的,也就是当 Web 容器(tomcat)启动时,调用 init() 方法初始化实例,Filter只会初始化一次。需要设置初始化参数的时候,可以写到init()方法中。
doFilter(): 业务处理,拦截要执行的请求,对请求和响应进行处理,一般需要处理的业务操作都在这个方法中实现
destroy() : 销毁实例,关闭容器时调用 destroy() 销毁 Filter 的实例。

过滤器的使用方式

首先要实现 javax.servlet.Filter 接口,之后将 Filter 声明为 Bean 交由 Spring 容器管理。以 SpringBoot 为示例:

方式一:@WebFilter注解

通过 @WebFilter 注解,将类声明为 Bean 过滤器类,在启动类添加注解 @ServletComponentScan ,让 Spring 可以扫描到。

@WebFilter
public class WebVisitFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /**
     * 输出访问 ip
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //获取访问 ip 地址
        HttpServletRequest req = (HttpServletRequest) request;
        String visitIp = req.getRemoteAddr();
        visitIp = "0:0:0:0:0:0:0:1".equals(visitIp) ? "127.0.0.1" : visitIp;
        // 每次拦截到请求输出访问 ip
        System.out.println("访问 IP = " + visitIp);
        chain.doFilter(req, response);
    }

    @Override
    public void destroy() {
    }
}



@SpringBootApplication
@ServletComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
@WebFilter作用

Tomcat 的 servlet 包下的注解,通过 @WebFilter 注解可以将指定类声明为过滤器。
@WebFilter 属性中没有配置顺序的,其执行顺序和 Filter 类名称字符排序有关,如果需要设置执行顺序,可以在命名的时候注意一下。

方式二:@Component注解

使用 @Component 将类声明为 Bean ,配合使用 @Order 注解可以设置过滤器执行顺序。

@Order(1)
@Component
public class WebVisitFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /**
     * 输出访问 IP
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 业务处理
    }

    @Override
    public void destroy() {
    }
}

方式三:Java Config 配置类

使用 @Configuration + @Bean 配置类,注解声明Bean,交由 Spring 容器管理。
Java Config 的方式可以通过 @Bean 配置顺序或 FilterRegistrationBean.setOrder() 决定 Filter 执行顺序。

public class WebVisitFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 业务处理
    }
    
    @Override
    public void destroy() {
    }
}



@Configuration
public class WebVisitFilterConfig {

    /**
     * 注册 过滤器 Filter
     */
    @Bean
    public FilterRegistrationBean<Filter> webVisitFilterConfigRegistration() {
        //匹配拦截 URL
        String urlPatterns = "/admin/*,/system/*";
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new WebVisitFilter());
        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
        //设置名称
        registration.setName("webVisitFilter");
        //设置过滤器链执行顺序
        registration.setOrder(3);
        //启动标识
        registration.setEnabled(true);
        //添加初始化参数
        registration.addInitParameter("enabel", "true");
        return registration;
    }
}

FilterChain 的作用

过滤器链是一种责任链模式的设计实现,在一个Filter 处理完成业务后,通过 FilterChain 调用过滤器链中的下一个过滤器。
流程如下:
FilterChain 接口定义了 doFilter 方法

public interface FilterChain {
    
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException;
    
}

ApplicationFilterChain类实现了 FilterChain 接口,管理所有的 Filter 的执行与调用

public final class ApplicationFilterChain implements FilterChain {
    // 数组存储所有的过滤器链
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    
    // 类中实现 doFilter() 方法 调用 调用 internalDoFilter(req,res) 方法
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {
        // ...
        //调用 internalDoFilter
        internalDoFilter(request,response);
        
    }
}

internalDoFilter(req,res) 方法中实现 Filter 调用的具体的操作,如下:

//取得数组中下一个过滤器实例
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = filterConfig.getFilter();

// ...

//调用下一个过滤器的 doFilter() 方法
filter.doFilter(request, response, this);

通过这种方式完成整个过滤器链的调用执行。

常见应用场景

  • 登录验证
  • 统一编码处理
  • 敏感字符过滤

过滤器链抛出异常处理方式

在过滤器进行拦截操作时,如发生异常,与业务类相同需要捕获异常进行记录并处理。如果想继续执行业务,可以通过 chain.doFilter(req, response); 对之后的过滤器进行调用。


之后我还会写一些有关技术的文章,欢迎关注

  • 23
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在 Spring Boot实现过滤器有两种方法: 1. 通过编写过滤器类并使用注解 @WebFilter 将其注册为过滤器。例如: ``` @WebFilter(urlPatterns = "/*") public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 处理过滤逻辑 chain.doFilter(request, response); } } ``` 2. 通过编写过滤器类并通过编写配置类来注册过滤器。例如: ``` @Configuration public class WebConfiguration { @Bean public FilterRegistrationBean<MyFilter> filterRegistrationBean() { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/*"); return registrationBean; } } ``` 注意:在 Spring Boot 2.3 及更高版本中,使用注解 @WebFilter 注册过滤器时,需要添加以下依赖: ``` <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> ``` 在 Spring Boot 2.2 及更低版本中,不需要添加此依赖。 ### 回答2: Spring Boot可以通过使用过滤器Filter实现对于应用程序的请求进行预处理或后处理的功能。在Spring Boot中,实现过滤器非常简单。 首先,我们需要创建一个实现javax.servlet.Filter接口的过滤器类。我们可以在过滤器类中实现对请求的预处理或后处理逻辑。例如,我们可以在过滤器中对请求进行日志记录、授权验证、防止跨站点请求伪造(CSRF)等操作。 接下来,我们需要在Spring Boot应用程序的配置文件(例如application.properties或application.yml)中配置过滤器。我们可以使用Spring Boot提供的特定属性来配置过滤器的顺序、URL匹配模式和其他属性。例如,我们可以使用以下配置来注册并配置过滤器spring.servlet.filter.order=1 spring.servlet.filter.dispatcher-types=REQUEST spring.servlet.filter.url-pattern=/api/* spring.servlet.filter.init-param.debug=true 最后,我们需要在Spring Boot应用程序的启动类(例如带有@SpringBootApplication注解的主类)中添加一个注解@ServletComponentScan,以扫描并注册我们创建的过滤器类。这将使Spring Boot自动识别并加载该过滤器实现过滤器后,当应用程序收到请求时,过滤器将自动拦截请求并执行预处理或后处理逻辑。过滤器的执行顺序可以通过配置文件中的spring.servlet.filter.order属性进行调整。 通过以上步骤,我们就可以在Spring Boot应用程序中实现一个过滤器过滤器可以帮助我们在请求到达控制器之前或返回给客户端之前对请求进行额外处理,从而实现对请求的自定义处理逻辑。 ### 回答3: Spring Boot提供了一种简单且易于实现方式实现过滤器。在Spring Boot中,我们可以通过创建一个实现javax.servlet.Filter接口的类来实现过滤器。 首先,我们需要在Spring Boot应用程序的代码中创建一个新的类并实现Filter接口。该类需要实现doFilter方法,该方法的目的是在请求进入Web应用程序之前或之后执行一些操作。该方法接受三个参数,分别是ServletRequest、ServletResponse和FilterChain。 在doFilter方法中,我们可以编写我们的逻辑代码来进行过滤操作。例如,我们可以检查请求的URL,如果满足我们的条件,则可以进行一些特定的处理,比如记录日志、验证权限等。然后,我们需要调用FilterChain对象的doFilter方法,以便将请求传递给下一个过滤器或Web应用程序。 接下来,我们还需要在Spring Boot应用程序的配置类中注册我们的过滤器。可以通过使用@Bean注解将过滤器类声明为一个bean,并将其添加到Spring Boot应用程序的过滤器链中。这将确保在请求到达控制器之前,我们的过滤器将被调用。 最后,我们可以通过在配置类中使用@Order注解来指定过滤器的执行顺序。如果有多个过滤器,根据需要可以使用不同的顺序来执行它们。 总的来说,Spring Boot通过实现javax.servlet.Filter接口和在配置类中注册过滤器方式实现过滤器。通过编写逻辑代码并将过滤器添加到过滤器链中,我们可以在请求进入Web应用程序之前或之后进行一些自定义操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值