Spring Cloud Gateway - 自定义Filter

最后更新:2020-08-04

Spring Cloud Gateway 提供了两种Filter:全局Filter(GlobalFilter)和局部Filter(GatewayFilter)

  • 全局Filter,对所有的路由都有效,主要实现了GlobalFilter 和 Ordered接口,并将过滤器注册到spring 容器。
  • 局部过滤器,需要在配置文件中配置,如果配置,则该过滤器才会生效。主要实现GatewayFilter, Ordered接口,并通过AbstractGatewayFilterFactory的子类注册到spring容器中,当然也可以直接继承AbstractGatewayFilterFactory,在里面写过滤器逻辑,还可以从配置文件中读取外部数据。

1. 自定义全局Filter

@Component
public class ElapsedGatewayFilter implements GlobalFilter, Ordered {
    public static final int ELAPSED_ORDER = -100000;

    private static final Logger LOGGER = LoggerFactory.getLogger(ElapsedGatewayFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        long startTime = System.currentTimeMillis();
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            Long endTime = System.currentTimeMillis();
            LOGGER.info("{}, elapsed {}ms", exchange.getRequest().getURI().getRawPath(), endTime - startTime);
        }));
    }

    @Override
    public int getOrder() {
        return ELAPSED_ORDER;
    }
}

2. 自定义局部Filter

GatewayFilter使用工厂模式生成

@Component
@Order(-10000)
public class IpBlacklistGatewayFilterFactory
        extends AbstractGatewayFilterFactory<IpBlacklistGatewayFilterFactory.Config> {

    public IpBlacklistGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {

        return (exchange, chain) -> {
            String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            if (config.getBlacklist().contains(ip)) {
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        };
    }

    public static class Config {
        private Set<String> blacklist = new HashSet<>();

        public Set<String> getBlacklist() {
            return blacklist;
        }

        public void setBlacklist(Set<String> blacklist) {
            this.blacklist = blacklist;
        }
    }
}

route配置

- id: route
  uri: http://httpbin.org:80/get
  predicates:
	- After=2020-04-20T00:00:00+08:00[Asia/Shanghai]
  filters:
	- name: IpBlacklist
	  args:
		blacklist:
		- "192.168.2.100"
		- "192.168.1.100"

我们在使用官方提供的Filter的时候,看到有一种简易写法

filters:
  - StripPrefix=2

这种写法需要实现两个方法

@Override
public List<String> shortcutFieldOrder() {
	return Lists.list("blacklist");
}

@Override
public ShortcutType shortcutType() {
	return ShortcutType.DEFAULT;
}

shortcutFieldOrder用了定义参数名称,可以接受多个参数,shortcutType用了定义参数类型,默认实现为DEFAULT

  - id: route
	uri: http://httpbin.org:80/get
	predicates:
	  - After=2020-04-20T00:00:00+08:00[Asia/Shanghai]
	filters:
	  - IpBlacklist=192.168.2.100, 192.168.2.101

ShortcutType.DEFAULT只会解析出一个IP192.168.2.100,而ShortcutType.GATHER_LIST会解析出两个IP:192.168.2.100 192.168.2.101

Edgar

Edgar
一个略懂Java的小菜比