1 pom.xml中引入依赖,最新GA版本

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
      <version>3.1.0</version>
    </dependency>

2 启动类

@SpringBootApplication
public class DemoApplication {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes().route("routeA", r -> r.path("/pathA")
        .uri("http://www.a.com")).build();
    }

    public static void main(String[] args) {
        System.setProperty("reactor.netty.ioWorkerCount", "n");
        SpringApplication.run(DemoApplication.class, args);
    }

}

3 application.yml

server:
    port: 80
logging:
    level:
        org.springframework.cloud.gateway: INFO
        org.springframework.http.server.reactive: INFO
        org.springframework.web.reactive: INFO
        reactor.ipc.netty: INFO
        reactor.netty: INFO
spring:
    cloud:
        gateway:
            routes:
                - id: routeB
                  uri: http://www.b.com
                  predicates:
                      - Path=/pathB

4 启动
这样启动后具备一个最简单的工程能力,里面具备两条静态路由功能:
pathA 转发至 www.a.com
pathB 转发至 www.b.com

5 动态路由
需路实现该接口:

package org.springframework.cloud.gateway.route;

public interface RouteDefinitionRepository extends RouteDefinitionLocator, RouteDefinitionWriter {

}

接下来来一个简单的小例子看一下:

@Component
public class DemoRouteDefinitionRepository implements RouteDefinitionRepository {
    private int idx = 1;

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        System.out.println("===========执行getRouteDefinitions");
        RouteDefinition definition = new RouteDefinition();
        definition.setId("routeC");
        if (idx++ % 2 == 0) {
            definition.setUri(URI.create("http://www.c1.com"));
        } else {
            definition.setUri(URI.create("http://www.c2.com"));
        }

        PredicateDefinition predicate = new PredicateDefinition();
        predicate.setName("Path");
        Map<String, String> map = new HashMap<>();
        map.put("pattern", "/pathC");
        predicate.setArgs(map);

        definition.setPredicates(Arrays.asList(predicate));
        return Flux.fromIterable(Arrays.asList(definition));
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return null;
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return null;
    }

}

可以看到getRouteDefinitions()提供路由信息,启动的时候会读取一次。在这里为模拟一下动态的情形,需要有事件去触发调用getRouteDefinitions()来更新路由,触发的动作是发送一个RefreshRoutesEvent事件:

@RestController
public class HomeController implements ApplicationEventPublisherAware{
    private ApplicationEventPublisher publisher;

    @GetMapping("/change")
    public Mono<Void> msg() {
        publisher.publishEvent(new RefreshRoutesEvent(this));
        return Mono.empty();
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher 
        applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

每调用一次/change,路由信息会变化一次,当然,也可以增加一条或者删除一条路由信息,本例子中save、delete都未实现。
5 依赖远程服务的过滤器
继承AbstractGatewayFilterFactory类,一个NameValue参数的实现形式:

public abstract class AbstractNameValueGatewayFilterFactory
        extends AbstractGatewayFilterFactory<AbstractNameValueGatewayFilterFactory
.NameValueConfig> {

    public AbstractNameValueGatewayFilterFactory() {
        super(NameValueConfig.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(GatewayFilter.NAME_KEY, GatewayFilter.VALUE_KEY);
    }

    @Validated
    public static class NameValueConfig {

        @NotEmpty
        protected String name;

        @NotEmpty
        protected String value;

        public String getName() {
            return name;
        }

        public NameValueConfig setName(String name) {
            this.name = name;
            return this;
        }

        public String getValue() {
            return value;
        }

        public NameValueConfig setValue(String value) {
            this.value = value;
            return this;
        }

        @Override
        public String toString() {
            return new ToStringCreator(this).append("name",
                name).append("value", value).toString();
        }

    }

}

比如配置的yml的时候:

@Component
public class DemoGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    private WebClient client = WebClient.create();

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        System.out.println("config.getName() = " + config.getName());
        System.out.println("config.getValue() = " + config.getValue());
        return (exchange, chain) -> {
            System.out.println("====0" + Thread.currentThread() + System.currentTimeMillis());
            return client.get().uri("http://127.0.0.1:1701/abc1").exchangeToMono(response -> {
                System.out.println("====1" + Thread.currentThread() + System.currentTimeMillis());
                return response.bodyToMono(String.class);
            }).map(abc -> {
                System.out.println("====2" + Thread.currentThread() + System.currentTimeMillis());
                exchange.getRequest().mutate().header("abc", "a1").build();
                return exchange;
            }).flatMap(chain::filter);

        };

    }

}

supermassive
1 声望1 粉丝