赞
踩
即使Spring Cloud Gateway
自带有许多实用的GatewayFilter Factory、Gateway Filter、Global Filter
,但是在很多情景下我们仍然希望可以自定义自己的过滤器。实现一些骚操作。所以自定义过滤器就显得非常有必要。本文主要介绍了自定义Gateway Filter
、自定义Global Filter
、自定义Gateway Filter Factory
。
实现自己的过滤器我们其实可以去查看Spring Cloud Gateway
自带过滤器源码是如何实现的,
自定义Gateway Filter
实现自定义的Gateway Filter
我们需要GatewayFilter、Ordered
两个接口
- /**
- * 此过滤器功能为计算请求完成时间
- */
- public class MyFilter implements GatewayFilter, Ordered {
-
- private static final String ELAPSED_TIME_BEGIN = "elapsedTimeBegin";
-
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- exchange.getAttributes().put(ELAPSED_TIME_BEGIN, System.currentTimeMillis());
- return chain.filter(exchange).then(
- Mono.fromRunnable(() -> {
- Long startTime = exchange.getAttribute(ELAPSED_TIME_BEGIN);
- if (startTime != null) {
- System.out.println(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
- }
- })
- );
- }
-
- /*
- *过滤器存在优先级,order越大,优先级越低
- */
- @Override
- public int getOrder() {
- return Ordered.LOWEST_PRECEDENCE;
- }
- }
-
- 复制代码
定义好MyFilter
以后,其需要跟Route
绑定使用,不能在application.yml
文件中配置使用
- @Bean
- public RouteLocator routeLocator(RouteLocatorBuilder builder) {
- return builder.routes().route(r ->
- r.path("/aa")
- //转发路由
- .uri("http://localhost:8003/provider/test")
- //注册自定义过滤器
- .filters(new MyFilter())
- //给定id
- .id("user-service"))
- .build();
- }
- 复制代码
测试结果:可以在控制台看到请求响应时间。
自定义Gateway Filter Factory
很多时候我们更希望在配置文件中配置Gateway Filter
,所以我们可以自定义过滤器工厂实现。
自定义过滤器工厂需要继承AbstractGatewayFilterFactory
- @Component
- public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
-
- private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
-
- private static final String AUTHORIZE_TOKEN = "token";
- private static final String AUTHORIZE_UID = "uid";
-
- @Autowired
- private StringRedisTemplate stringRedisTemplate;
-
- public AuthorizeGatewayFilterFactory() {
- super(Config.class);
- logger.info("Loaded GatewayFilterFactory [Authorize]");
- }
-
- @Override
- public List<String> shortcutFieldOrder() {
- return Arrays.asList("enabled");
- }
-
- @Override
- public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
- return (exchange, chain) -> {
- if (!config.isEnabled()) {
- return chain.filter(exchange);
- }
-
- ServerHttpRequest request = exchange.getRequest();
- HttpHeaders headers = request.getHeaders();
- String token = headers.getFirst(AUTHORIZE_TOKEN);
- String uid = headers.getFirst(AUTHORIZE_UID);
- if (token == null) {
- token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
- }
- if (uid == null) {
- uid = request.getQueryParams().getFirst(AUTHORIZE_UID);
- }
-
- ServerHttpResponse response = exchange.getResponse();
- if (StringUtils.isEmpty(token) || StringUtils.isEmpty(uid)) {
- response.setStatusCode(HttpStatus.UNAUTHORIZED);
- return response.setComplete();
- }
- String authToken = stringRedisTemplate.opsForValue().get(uid);
- if (authToken == null || !authToken.equals(token)) {
- response.setStatusCode(HttpStatus.UNAUTHORIZED);
- return response.setComplete();
- }
- return chain.filter(exchange);
- };
- }
-
- public static class Config {
- // 控制是否开启认证
- private boolean enabled;
-
- public Config() {}
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
- }
- }
- 复制代码
在application.yml
配置使用
- # 网关路由配置
- spring:
- cloud:
- gateway:
- routes:
- - id: user-service
- uri: http://localhost:8077/api/user/list
- predicates:
- - Path=/user/list
- filters:
- # 关键在下面一句,值为true则开启认证,false则不开启
- # 这种配置方式和spring cloud gateway内置的GatewayFilterFactory一致
- - Authorize=true
- 复制代码
自定义Global Filter
实现自定义全局过滤器需要继承GlobalFilter
和Ordered
- @Component
- public class MyGloablFilter implements GlobalFilter, Ordered {
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- System.out.println("1111111111111111");
- return chain.filter(exchange);
- }
-
- @Override
- public int getOrder() {
- return 0;
- }
- }
- 复制代码
使用它只需要加上@Component
注解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。