springboot(11)过滤器Filter

1.过滤器介绍

过滤器的英文名称为Filter,是Servlet技术中最实用的技术。如同它的名字一样,过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常它被用作 Session校验,判断用户权限,如果不符合设定条件,就会被拦截到特殊的地址或者给予特殊的响应。

Spring Boot过滤器可以用于拦截请求并在它们到达目标资源之前执行一些操作。过滤器通常用于修改请求或响应、验证请求参数或头部、记录请求日志等。

2.Filter生命周期

使用过滤器很简单,只需要实现Filter类,然后重写它的3个方法即可。

  • init方法:程序启动调用Filter的init()方法(永远只调用一次);在容器中创建当前过滤器的时候自动调用这个方法。
  • destory方法:程序停止调用Filter的destroy()方法(永远只调用一次);在容器中销毁当前过滤器的时候自动调用这个方法。
  • doFilter方法:doFilter()方法每次的访问请求如果符合拦截条件都会调用(程序第一次运行,会在servlet调用init()方法以后调用;不管第几次,都在调用doGet(),doPost()方法之前)。这个方法有3个参数,分别是ServletRequest、ServletResponse和FilterChain可以从参数中获取HttpServletReguest和HttpServletResponse对象进行相应的处理操作。

4.1注解方式实现过滤器

4.1.1 @WebFilter

@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 )

@WebFilter注解用于定义过滤器,它可以应用于Servlet、JSP或静态资源等Web资源。@WebFilter注解有以下几个属性:

  • filterName:用于指定过滤器的名称。
  • urlPatterns:用于指定需要过滤的URL模式,可以指定多个URL模式。
  • value:与urlPatterns作用相同,也是用于指定需要过滤的URL模式。
  • servletNames:用于指定需要过滤的Servlet名称,可以指定多个Servlet名称。
  • dispatcherTypes:用于指定过滤器的拦截类型,包括:FORWARD、INCLUDE、REQUEST、ASYNC、ERROR。
  • initParams:用于指定过滤器的初始化参数,可以指定多个初始化参数。
属性名 类型 描述
filterName String 指定过滤器的名称
urlPatterns String[] 指定需要过滤的URL模式,可以指定多个URL模式
value String[] 与urlPatterns作用相同,也是用于指定需要过滤的URL模式
servletNames String[] 指定需要过滤的Servlet名称,可以指定多个Servlet名称
dispatcherTypes DispatcherType[] 指定过滤器的拦截类型,包括:FORWARD、INCLUDE、REQUEST、ASYNC、ERROR
initParams WebInitParam[] 指定过滤器的初始化参数,可以指定多个初始化参数

例如,以下代码定义了一个名为MyFilter的过滤器,它会拦截名为myServlet的Servlet,以及URL模式为/mypage的请求:

@WebFilter(filterName = "MyFilter",
        servletNames = {
    
    "myServlet"},
        urlPatterns = {
    
    "/mypage"})
public class MyFilter implements Filter {
    
    
    // ...
}

4.1.2 @Order

@Order()注解是用于指定过滤器链中过滤器的执行顺序的注解。当有多个过滤器时,@Order值小的过滤器先执行。如果没有指定@Order注解,则默认按照过滤器名称的字母顺序执行。

4.1.3 @ServletComponentScan

@ServletComponentScan注解是用于扫描指定包或类下的Servlet、Filter、Listener等Web组件,并将其注册到Servlet容器中的注解。在Spring Boot项目中,使用该注解可以让Spring Boot自动扫描并注册Servlet、Filter和Listener,而不需要手动进行配置。默认情况下,@ServletComponentScan会扫描主应用程序类所在的包及其子包下的所有类。

例如,以下代码演示了如何使用@ServletComponentScan注解来自动注册Servlet、Filter和Listener:

@ServletComponentScan(basePackages = {
    
    "com.example.servlets", "com.example.filters"})
@SpringBootApplication
public class MyApp {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(MyApp.class, args);
    }
}

在上面的例子中,@ServletComponentScan注解会扫描com.example.servletscom.example.filters包下的所有Servlet和Filter,并将它们注册到Servlet容器中。同时,Spring Boot还会自动扫描并注册位于主应用程序类所在包及其子包下的所有组件。

需要注意的是,@ServletComponentScan注解只能在Spring Boot项目中使用,在普通的Servlet项目中是无效的。

4.1.4 使用

首先使用@ServletComponentScan注解来扫描过滤器类

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

接下来在过滤器类上使用@WebFilter注解来定义过滤器,例如:

@WebFilter(urlPatterns = "/user/*", filterName = "testFilter")
@Order(1)
public class TokenFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("doFilter");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("token");
        System.out.println("token");
        //该方法执行后直接运行至下一个过滤器
        if(token!=null){
    
    
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
    
    
            servletResponse.setCharacterEncoding("UTF-8");
            servletResponse.setContentType("application/json; charset=utf-8");
            PrintWriter out = servletResponse.getWriter();
            JSONObject res = new JSONObject();
            res.put("msg", "错误");
            res.put("success", "false");
            out.append(res.toString());
        }
    }

    @Override
    public void destroy() {
    
    
        Filter.super.destroy();
    }
}

这段代码是一个Java Servlet Filter,用于拦截所有url以/user/开头的请求。它的过滤器名称是testFilter,使用urlPatterns参数指定了要拦截的URL模式。

这个过滤器的作用是检查请求头中是否有名为token的值,如果有则直接运行至下一个过滤器;否则返回一个JSON格式的错误信息。

doFilter方法中,首先获取请求对象的token值,然后判断是否为空。如果不为空,则调用filterChain.doFilter方法,该方法会将请求传递给下一个过滤器或目标资源。如果为空,则返回一个JSON格式的错误信息给客户端。

除了doFilter方法,这个过滤器还实现了initdestroy方法,分别在过滤器被初始化和销毁时调用。

4.2用配置类实现过滤器

4.2.1 方式(一)

这是一个使用Spring Boot配置类实现的过滤器。首先,我们需要创建一个类,用@Configuration注解标记它,以指示Spring Boot该类包含配置信息。然后,使用@Bean注解创建一个名为testFilter的过滤器。在这个过滤器中,我们需要实现Filter接口,并重写doFilter方法。

doFilter方法中,我们可以像Java Servlet Filter一样执行过滤器逻辑。如果需要添加更多的过滤器,可以使用filterChain.doFilter方法将请求传递给下一个过滤器。

以下是示例代码:

@Configuration
public class TestFilterConfig {
    
    

    @Bean
    public FilterRegistrationBean<TestFilter> testFilter() {
    
    
        FilterRegistrationBean<TestFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TestFilter());
        registrationBean.addUrlPatterns("/user/*");
        return registrationBean;
    }

    public class TestFilter implements Filter {
    
    

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
    
            // 过滤器初始化逻辑
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    
            // 过滤器逻辑
            chain.doFilter(request, response); // 将请求传递给下一个过滤器或目标资源
        }

        @Override
        public void destroy() {
    
    
            // 过滤器销毁逻辑
        }
    }
}

4.2.2 方式(二)

4.2.2.1 Filter代码
package com.buba.filter;


import com.alibaba.fastjson.JSONObject;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;

public class TestFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("doFilter");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("token");
        System.out.println("token");
        //该方法执行后直接运行至下一个过滤器
        if(token!=null){
    
    
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
    
    
            servletResponse.setCharacterEncoding("UTF-8");
            servletResponse.setContentType("application/json; charset=utf-8");
            PrintWriter out = servletResponse.getWriter();
            JSONObject res = new JSONObject();
            res.put("msg", "错误");
            res.put("success", "false");
            out.append(res.toString());
        }
    }

    @Override
    public void destroy() {
    
    
        System.out.println("destroy");
    }
}
4.2.2.2 Filter配置类代码
package com.buba.config;

import com.buba.filter.TestFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    
    
    // 创建 TestFilter 实例
    @Bean
    public TestFilter myFilter() {
    
    
        return new TestFilter();
    }

    // 注册过滤器
    @Bean
    public FilterRegistrationBean getFilterRegistrationBean(TestFilter myFilter) {
    
    
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(myFilter);
        // 设置过滤器执行顺序
        filterRegistrationBean.setOrder(1);
        // 配置要过滤的 URL 模式
        filterRegistrationBean.addUrlPatterns("/test/*");
        // 设定过滤器名称
        filterRegistrationBean.setName("myFilter");
        return filterRegistrationBean;
    }
}

这段代码是一个过滤器的配置类,用于将 TestFilter 实例注册到 Spring Boot 中的过滤器链中。以下是对代码中每个部分的解释:

  • @Configuration:这个注解表明这是一个 Spring 配置类,它会被 Spring 自动扫描并加载;
  • @Bean:这个注解表明这个方法会返回一个 Bean 实例,它会被 Spring 管理;
  • public TestFilter myFilter():这是一个方法,用于创建 TestFilter 实例;
  • public FilterRegistrationBean getFilterRegistrationBean(TestFilter myFilter):这也是一个方法,用于将 TestFilter 实例注册到 Spring Boot 中的过滤器链中;
  • filterRegistrationBean.setFilter(myFilter):这个方法将 myFilter 设置为过滤器实例;
  • filterRegistrationBean.setOrder(1):设置过滤器执行顺序,这个过滤器将会在其他过滤器之前执行;
  • filterRegistrationBean.addUrlPatterns("/test/*"):配置要过滤的 URL 模式;
  • filterRegistrationBean.setName("myFilter"):设定过滤器名称,这个名称会在控制台输出过滤器执行日志时使用。

猜你喜欢

转载自blog.csdn.net/Bilal_0/article/details/129967156