微服务-网关Spring Gateway Filter入门

379 阅读1分钟

一、概述

Spring Gateway支持自定义Filter实现,可以实现鉴权、限流、日志记录等功能。其Filter的执行顺序通过Ordered接口定义。Order值越小(可以为负数),则执行顺序越靠前;Oder值越大,则执行顺序越靠后。自定义Filter通过实现GlobalFilter实现。

注意:filter的执行内容分为执行业务代码之前(简称Before),以及执行业务代码之后两个部分(简称After)。Before执行的越靠前,则对应的After执行的顺序越靠后。

二、代码实现

通过一个简单的计时实例先上手。

@Component
public class DurationStatisticsFilter implements GlobalFilter, Ordered {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("====== DurationStatisticsFilter start ======");
        exchange.getAttributes().put("durationStart", System.currentTimeMillis());

        return chain.filter(exchange).doFinally(f -> printDurationTime(exchange));
    }

    private void printDurationTime(ServerWebExchange exchange) {
        long start = exchange.getAttribute("durationStart");
        long end = System.currentTimeMillis();
        logger.info("====== DurationStatisticsFilter end, cost: {} ======", (end - start));
    }

    @Override
    public int getOrder() {
        return WRITE_RESPONSE_FILTER_ORDER - 1;
    }
}

通过访问一个API,控制台日志展示如下:

image.png

基于此例子,继续拓展下,我们经常需要获取请求的头信息,因此可以打印出请求的所有头信息。

@Component
public class HttpHeaderInfoFilter implements GlobalFilter, Ordered {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("====== HttpHeaderInfoFilter start ======");
        ServerHttpRequest request = exchange.getRequest();
        logger.info("path: {}", request.getPath());
        HttpHeaders headers = request.getHeaders();
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            if (entry.getValue() != null) {
                String value = entry.getValue().stream().collect(Collectors.joining(","));
                logger.info("entry: {}, value: {}.", entry.getKey(), value);
            } else {
                logger.info("entry: {}, value is null.", entry.getKey());
            }
        }
        return chain.filter(exchange).doFinally(t -> doFinally(exchange));
    }

    private void doFinally(ServerWebExchange exchange) {
        logger.info("====== HttpHeaderInfoFilter end ======");
    }

    @Override
    public int getOrder() {
        return WRITE_RESPONSE_FILTER_ORDER + 1;
    }
}

打印的头信息如下: image.png

三、总结

filter的入门级操作还算是比较简单的,实现过程中没有碰到问题,比较顺利。

四、源码

gitee.com/animal-fox_…