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);
};
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。