在前文中,我們介紹了Spring Cloud Gateway內置了一系列的內置過濾器工廠,若Spring Cloud Gateway內置的過濾器工廠無法滿足我們的業務需求,那么此時就需要自定義自己的過濾器工廠以實現特定功能。所謂過濾器工廠實際上就是用於創建過濾器實例的,而創建的過濾器實例都實現於GatewayFilter接口。
過濾器生命周期
Gateway以轉發請求為邊界,分為兩個生命周期
- pre:Gateway轉發請求之前
- post:Gateway轉發請求之后
自定義過濾器工廠
繼承AbstractGatewayFilterFactory
可參考源碼:org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory
配置形式如下:
spring:
cloud:
gateway:
routes:
filters:
# 過濾器工廠的名稱
- name: RequestSize
# 該過濾器工廠的參數
args:
maxSize: 500000
繼承AbstractNameValueGatewayFilterFactory
可參考源碼:org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory
配置形式如下:
spring:
cloud:
gateway:
routes:
filters:
# 過濾器工廠的名稱及參數以name-value的形式配置
- AddRequestHeader=S-Header, Bar
PS:AbstractNameValueGatewayFilterFactory繼承了AbstractGatewayFilterFactory,所以實際上第二種方式是第一種方式的簡化
核心API
- exchange.getRequest().mutate().xxx:修改request
*exchange.mutate().xxx:修改exchange
*chain.filter(exchange):傳遞給下一個過濾器處理
*exchange.getResponse():獲取響應對象
PS::exchange實際類型為ServerWebExchange,chain實際類型為GatewayFilter
實現自定義過濾器工廠
需求:記錄訪問日志
自定義過濾器工廠
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
@Slf4j
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
log.info("配置參數:{}, {}", config.getName(), config.getValue());
ServerHttpRequest request = exchange.getRequest()
.mutate().build();
ServerWebExchange webExchange = exchange.mutate()
.request(request)
.build();
return chain.filter(webExchange);
};
}
}
添加相關配置
spring:
gateway:
discovery:
locator:
enabled: false
routes:
- id: study
uri: lb://study01
predicates:
- TimeBetween=上午0:00,下午11:59
filters:
# 名稱必須為過濾器工廠類名的前綴,並且參數只能有兩個,因為NameValueConfig里只定義了兩個屬性
- PreLog=testName,testValue
PS:
- 自定義過濾器工廠類時,按照Spring Cloud Stream的約定,類名須為“過濾器名(本文例中:PreLog)” + GatewayFilterFactory
測試結果
2019-10-28 15:05:10.620 INFO 8734 --- [or-http-epoll-2] c.e.gateway.PreLogGatewayFilterFactory : 配置參數:testName, testValue