天天看點

Spring Boot 自定義過濾器(Filter)

Spring Boot 自定義過濾器(Filter)

Filter 過濾器主要是用來過濾使用者請求的,它允許我們對使用者請求進行前置處理和後置處理,比如實作 URL 級别的權限控制、過濾非法請求等等。Filter 過濾器是面向切面程式設計——AOP 的具體實作(AOP切面程式設計隻是一種程式設計思想而已)。

自定義 Filter 隻需要實作

import javax.servlet.Filter

接口即可。Filter 接口依賴于 Servlet 容器,

Filter

接口就在 Servlet 包下,屬于 Servlet 規範的一部分。

javax.servlet.Filter

public interface Filter {
  
   //初始化過濾器後執行的操作
    default void init(FilterConfig filterConfig) throws ServletException {
    }
   // 對請求進行過濾
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
   // 銷毀過濾器後執行的操作,主要使用者對某些資源的回收
    default void destroy() {
    }
}
           
Filter 是如何實作攔截的?

通過

FIlter

接口中的

doFilter

方法,實作了對使用者請求的過濾,其中請求流程為

  1. 使用者發送請求到 web 伺服器,請求會先到過濾器;
  2. 過濾器會對請求進行一些處理比如過濾請求的參數、修改傳回給用戶端的 response 的内容、判斷是否讓使用者通路該接口等等。
  3. 使用者請求響應完畢。
  4. 進行一些自己想要的其他操作。
    Spring Boot 自定義過濾器(Filter)
自定義 Filter 的方法

提供兩種方法

1. 通過 手動注冊配置實作

MyFilter

實作了

javax.servlet.Filter

package com.zwk.spring_boot_filter_listener.util;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @description:
 * @author: zwk
 * @date: 2021/6/10
 */
@Component
public class MyFilter implements Filter {

	Logger log = LoggerFactory.getLogger(MyFilter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		Filter.super.init(filterConfig);
		System.out.println("init");
		log.info("init");
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		servletRequest.setAttribute("filter", " doFilter");
		log.info("doFilter");
		System.out.println("請求接口為:" + ((HttpServletRequest) servletRequest).getRequestURI());
		filterChain.doFilter(servletRequest, servletResponse);
	}


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

           

MyFilterConfig.java

将 Filter 注冊

之所使用 @Bean + FilterRegistrationBean 的方式注冊Filter 是為了更靈活的設定映射。

當然,也可以不使用 @Bean + FilterRegistrationBean 的方式注冊,即使用基于約定的映射:

/*

。直接建立自定義 Filter 并且注冊為 Spring 的元件即可。

@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter myFilter;
    @Bean
    public FilterRegistrationBean<MyFilter> thirdFilter() {
        FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
		// 注冊自定義的 Filter
        filterRegistrationBean.setFilter(myFilter);
		// 設定攔截 Url映射
        filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
        return filterRegistrationBean;
    }
}
           

2. 通過注解實作

在自己的過濾器的類上加上

@WebFilter

然後在這個注解中通過它提供好的一些參數進行配置。

@WebFilter(filterName = "MyFilterWithAnnotation", urlPatterns = "/api/*")
public class MyFilterWithAnnotation implements Filter {

   ......
}
           

注意

另外,為了能讓 Spring 找到它,你需要在啟動類上加上

@ServletComponentScan

注解

控制多個 Filter 的執行順序

通過 @Order 注解,控制 順序

通過将 @Order 注解 放置于 Filter 實作類上調整 value 的值控制執行順序(value越小優先級越高)

@Order(1)
public class MyFilter implements Filter {

   ......
}
           

下例優先級低于上例

@Order(2)
public class MyFilter2 implements Filter {

   ......
}
           

注意

: 這種方式适用于,不使用 @Bean + FilterRegistrationBean 注冊的Filter。

當需要使用 @Bean + FilterRegistrationBean 注冊 Filter 時則可以使用

FilterRegistrationBean

setOrder(int value)

方法

package com.zwk.spring_boot_filter_listener.config;

import com.zwk.spring_boot_filter_listener.util.MyFilter;
import com.zwk.spring_boot_filter_listener.util.MyFilter2;
import java.util.ArrayList;
import java.util.Arrays;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description:
 * @author: zwk
 * @date: 2021/6/10
 */
@Configuration
public class MyFilterConfig {
	final
	MyFilter myFilter;
	final
	MyFilter2 myFilter2;

	public MyFilterConfig(MyFilter myFilter, MyFilter2 myFilter2) {
		this.myFilter = myFilter;
		this.myFilter2 = myFilter2;
	}

	@Bean
	public FilterRegistrationBean<MyFilter> filterFilterRegistrationBean() {
		FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
		filterRegistrationBean.setFilter(myFilter);
		filterRegistrationBean.setOrder(2);
		filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/testFilterController", "/testFilterController1")));
		return filterRegistrationBean;
	}

	@Bean
	public FilterRegistrationBean<MyFilter2> filterFilter2RegistrationBean() {
		FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<>();
		filterRegistrationBean.setFilter(myFilter2);
		filterRegistrationBean.setOrder(1);
		filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/testFilterController", "/testFilterController1")));
		return filterRegistrationBean;
	}
}

           

引用:

本文部分知識點總結引用自:https://github.com/CodingDocs/springboot-guide/blob/master/docs/basis/springboot-filter.md

作者:Snailclimb

繼續閱讀