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
方法,實作了對使用者請求的過濾,其中請求流程為
- 使用者發送請求到 web 伺服器,請求會先到過濾器;
- 過濾器會對請求進行一些處理比如過濾請求的參數、修改傳回給用戶端的 response 的内容、判斷是否讓使用者通路該接口等等。
- 使用者請求響應完畢。
- 進行一些自己想要的其他操作。
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