Spring Cloud Gateway (六) 自定義 Global Filter
簡介
在前面五篇的分析中,對 Spring Cloud Gateway 的 filter 組件有了一個大概的認知,今天就練練手,寫一個統計請求返回時長的 global filter
思路整理
閱讀官方文檔和在前面讀源碼的過程中,大致知道 global filter 需要繼承 GlobalFilter 、 Ordered
- GlobalFilter : 需要重寫 filter 方法,在其中實現自己的處理邏輯,很大部分都是對 exchange 進行操作,取值賦值等等
- Ordered : 需要重寫 getOrder 方法,決定自定義 filter 在鏈中的位置,按照數字大小進行的排序
自定義時長統計 filter 編寫
這里就簡單的借鑒下 GatewayMetricsFilter 的寫法,在 filter 鏈觸發完成后,無論失敗或者成功,都進行統計。filter 次序就簡單的取 WRITE_RESPONSE_FILTER_ORDER 之后(用它定義的次序減一)。代碼大致如下:
/**
* 統計一次請求在filter鏈中的時長
*
* @author lw1243925457
*/
public class DurationStatisticsFilter implements GlobalFilter, Ordered {
private static final Log log = LogFactory.getLog(DurationStatisticsFilter.class);
private static final String START_STAMP = "startStamp";
/**
* 請求響應時長統計
* 1.首先將請求進來時的時間戳寫入到 exchange中
* 2.filter鏈走完后,無論成功或者失敗,都視為完成,從exchange取出開始時間戳,打印時長信息
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
* @return mono
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("duration statistics filter");
exchange.getAttributes().put(START_STAMP, System.currentTimeMillis());
return chain.filter(exchange)
.doFinally(f -> printDurationTime(exchange));
}
private void printDurationTime(ServerWebExchange exchange) {
long startStamp = exchange.getAttribute(START_STAMP);
long endStamp = System.currentTimeMillis();
log.debug("duration filter time : " + (endStamp - startStamp) + " ms");
}
/**
* 這里簡單位於 NettyWriteResponseFilter 之后吧
* @return order
*/
@Override
public int getOrder() {
return WRITE_RESPONSE_FILTER_ORDER - 1;
}
}
主函數配置運行
需要在主函數中配置 bean,整個代碼大致如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(p -> p
.path("/")
.filters(f -> f
.addRequestParameter("test", "test")
.addResponseHeader("return", "return")
.retry(retryConsumer)
)
.uri("http://localhost:8082/"))
.build();
}
@Bean
public GlobalFilter durationStatisticsFilter() {
return new DurationStatisticsFilter();
}
}
很簡單,大致就這些,運行起來,瀏覽器訪問,可以看到下面的輸出,over
o.s.c.g.sample.DurationStatisticsFilter : duration statistics filter
o.s.c.g.sample.DurationStatisticsFilter : duration filter time : 349 ms