SpringBoot中过滤器的使用

367 阅读4分钟

1. Filter 介绍

Filter 过滤器这个概念应该大家不会陌生,特别是对与从 Servlet 开始入门学 Java 后台的同学来说。那么这个东西我们能做什么呢?Filter 过滤器主要是用来过滤用户请求的,它允许我们对用户请求进行前置处理和后置处理,比如实现 URL 级别的权限控制、过滤非法请求等等。Filter 过滤器是面向切面编程——AOP 的具体实现(AOP切面编程只是一种编程思想而已)。 另外,Filter 是依赖于 Servlet 容器,Filter接口就在 Servlet 包下面,属于 Servlet 规范的一部分。所以,很多时候我们也称其为“增强版 Servlet”。 如果我们需要自定义 Filter 的话非常简单,只需要实现 javax.Servlet.Filter 接口,然后重写里面的 3 个方法即可! Filter.java

public interface Filter {
  
   //初始化过滤器后执行的操作
    default void init(FilterConfig filterConfig) throws ServletException {
    }
   // 对请求进行过滤
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
   // 销毁过滤器后执行的操作,主要用户对某些资源的回收
    default void destroy() {
    }
}

2. Filter是如何实现拦截的?

Filter接口中有一个叫做 doFilter 的方法,这个方法实现了对用户请求的过滤。具体流程大体是这样的:

  1. 用户发送请求到 web 服务器,请求会先到过滤器;
  2. 过滤器会对请求进行一些处理比如过滤请求的参数、修改返回给客户端的 response 的内容、判断是否让用户访问该接口等等。
  3. 用户请求响应完毕。
  4. 进行一些自己想要的其他操作。

![](https://img-blog.csdnimg.cn/img_convert/92c4b704fade4da1d47d8ea86f03a794.png#align=left&display=inline&height=394&margin=[object Object]&originHeight=394&originWidth=647&size=0&status=done&style=none&width=647)

3. 如何自定义Filter

3.1 实习javax.Servlet.Filter接口


@Component
public class MyFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化方法:只在服务器启动初始化的时候执行一次");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行过滤器操作");
        /*放行操作*/
        filterChain.doFilter(servletRequest,servletResponse);
        /*执行完对应的方法回来之后还好经过过滤器*/
        System.out.println("事情干完了,回显到客户端");
    }
 /*在服务器正常关闭的时候执行*/
    @Override
    public void destroy() {
        System.out.println("销毁方法,只在服务器关闭的时候执行一次");
    }
}

3.2 在配置中注册自定义的过滤器

@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter1 myFilter1;
    @Bean
    public FilterRegistrationBean<MyFilter1> Filter1(){
        FilterRegistrationBean<MyFilter1> myFilter1FilterRegistrationBean = new FilterRegistrationBean<>();
        /*设置Filter*/
        myFilter1FilterRegistrationBean.setFilter(myFilter1);
        /*设置访问路径*/
        myFilter1FilterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/filter/*")));
        return myFilter1FilterRegistrationBean;
    }

}

3.3 通过注解实现配置

注意: ** 使用WebFilter,需要在启动类上加上 @ServletComponentScan 注解。

@WebFilter(filterName = "MyFilter1",urlPatterns = "/filter")
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化方法:只在服务器启动初始化的时候执行一次");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行过滤器操作");
        /*放行操作*/
        filterChain.doFilter(servletRequest,servletResponse);
        /*执行完对应的方法回来之后还好经过过滤器*/
        System.out.println("事情干完了,回显到客户端");
    }
 /*在服务器正常关闭的时候执行*/
    @Override
    public void destroy() {
        System.out.println("销毁方法,只在服务器关闭的时候执行一次");
    }
}

4. 自定义多个过滤器,确定过滤器的执行顺序

通过设置过滤器级别来进行操作,调用FilterRegistrationBean的setOrder方法

package com.pjh.Config;

import com.pjh.Filter.MyFilter1;
import com.pjh.Filter.MyFilter2;
import org.springframework.beans.factory.annotation.Autowired;
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.Arrays;

/**
 * @ClassName: MyFilterConfig
 * @Author: 86151
 * @Date: 2021/4/14 14:29
 * @Description: TODO
 */
@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter1 myFilter1;
    @Autowired
    MyFilter2 myFilter2;
    @Bean
    public FilterRegistrationBean<MyFilter1> Filter1(){
        FilterRegistrationBean<MyFilter1> myFilter1FilterRegistrationBean = new FilterRegistrationBean<>();
        /*设置Filter*/
        myFilter1FilterRegistrationBean.setFilter(myFilter1);
        /*设置过滤器的级别*/
        myFilter1FilterRegistrationBean.setOrder(1);
        /*设置访问路径*/
        myFilter1FilterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/filter/*")));
        return myFilter1FilterRegistrationBean;
    }
    @Bean
    public FilterRegistrationBean<MyFilter2> Filter2(){
        FilterRegistrationBean<MyFilter2> myFilter1FilterRegistrationBean = new FilterRegistrationBean<>();
        /*设置Filter*/
        myFilter1FilterRegistrationBean.setFilter(myFilter2);
        /*设置过滤器的级别*/
        myFilter1FilterRegistrationBean.setOrder(2);
        /*设置访问路径*/
        myFilter1FilterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/filter/*")));
        return myFilter1FilterRegistrationBean;
    }
}

5.相关注解介绍

@WebFilter

概述

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

@WebFilter 的常用属性

![](img-blog.csdnimg.cn/img_convert… Object]&originHeight=448&originWidth=866&size=0&status=done&style=none&width=866)

注意事项

filterName的首字母一定要小写!!!小写!!!小写!!!
Application启动类添加@ServletComponentScan注解

@Order

概述

注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响;

代码实现

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {

	/**
	 * 默认是最低优先级,值越小优先级越高
	 */
	int value() default Ordered.LOWEST_PRECEDENCE;

}