项目示例 - 3.服务网关 - 3.Gateway
关联知识:
- 分布式微服务 - 3.服务网关 - 4.Gateway
内容提要:
- 基本使用
- 自定义断言
- 自定义局部、全局过滤器
基本使用
- 建Module:微服务起名为gateway-server
- 改pom:引入以下依赖
xml
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--Nacos服务注册-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
- 写yml:在resources目录下创建application.yml文件,并做以下配置
yml
server:
port: 80
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
# nacos的地址
server-addr: localhost:8848
gateway:
discovery:
locator:
# 从服务注册中心根据别名来进行路由
enabled: true
routes:
# 路由Id,自定义,唯一即可
- id: nacos-provider-test
# 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
uri: lb://nacos-provider
# 成功匹配后,要转换成的路由地址(不配合服务注册中心)
#uri: http://localhost:8001
# 断言
predicates:
# 路径匹配的进行路由
- Path=/**
- 主启动:在src下创建如下主启动类
java
package learn.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayServer {
public static void main(String[] args) {
SpringApplication.run(GatewayServer.class, args);
}
}
- 测试:
- 启动nacos,能正常打开nacos首页
- 启动nacos-provider微服务,浏览器访问
localhost:8001/nacos/provider/test
接口,能正常返回信息,且在nacos服务列表中可看到成功注册 - 启动本微服务后,浏览器访问
localhost/nacos/provider/test
接口,能正常返回信息
自定义断言
- 创建自定义断言类:
java
package learn.demo.config;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {
public CustomRoutePredicateFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("key", "value");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
List<String> strings = serverWebExchange.getRequest().getHeaders().get(config.key);
if (strings==null || strings.isEmpty())
return false;
return config.value.equals(strings.get(0));
}
};
}
public static class Config {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
- application.yml中配置断言:
yml
server:
port: 80
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
# nacos的地址
server-addr: localhost:8848
gateway:
discovery:
locator:
# 从服务注册中心根据别名来进行路由
enabled: true
routes:
# 路由Id,自定义,唯一即可
- id: nacos-provider-test
# 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
uri: lb://nacos-provider
# 成功匹配后,要转换成的路由地址(不配合服务注册中心)
#uri: http://localhost:8001
# 断言
predicates:
# 路径匹配的进行路由
- Path=/**
- Custom=test, a
- 测试:
- 启动nacos,能正常打开nacos首页
- 启动nacos-provider微服务,浏览器访问
localhost:8001/nacos/provider/test
接口,能正常返回信息,且在nacos服务列表中可看到成功注册 - 启动本微服务后,API工具访问
localhost/nacos/provider/test
接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息。
自定义过滤器
自定义局部过滤器
- 创建自定义过滤器类:
java
package learn.demo.config;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {
public CustomGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("key", "value");
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// pre操作
String pre;
List<String> strings = exchange.getRequest().getHeaders().get("pre");
if (strings==null || strings.isEmpty())
pre="no args";
else
pre=strings.get(0);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 异步post操作
exchange.getResponse().getHeaders().set(config.key, pre+" | "+config.value);
}));
}
};
}
public static class Config {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
- 添加配置:
yml
server:
port: 80
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
# nacos的地址
server-addr: localhost:8848
gateway:
discovery:
locator:
# 从服务注册中心根据别名来进行路由
enabled: true
routes:
# 路由Id,自定义,唯一即可
- id: nacos-provider-test
# 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
uri: lb://nacos-provider
# 成功匹配后,要转换成的路由地址(不配合服务注册中心)
#uri: http://localhost:8001
# 断言
predicates:
# 路径匹配的进行路由
- Path=/**
- Custom=test, a
filters:
- Custom=post,test
- 测试:
- 启动nacos,能正常打开nacos首页
- 启动nacos-provider微服务,浏览器访问
localhost:8001/nacos/provider/test
接口,能正常返回信息,且在nacos服务列表中可看到成功注册 - 启动本微服务后,API工具访问
localhost/nacos/provider/test
接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息,查看响应头中有key为post、value为no args | test的参数。
自定义全局过滤器
- 创建自定义过滤器类:
java
package learn.demo.config;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// pre操作
String pre;
List<String> strings = exchange.getRequest().getHeaders().get("pre");
if (strings==null || strings.isEmpty())
pre="no args";
else
pre=strings.get(0);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 异步post操作
exchange.getResponse().getHeaders().set("post", pre+" | test");
}));
}
// 值越小,优先级越高
@Override
public int getOrder() {
return 0;
}
}
- 修改配置文件:
yml
server:
port: 80
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
# nacos的地址
server-addr: localhost:8848
gateway:
discovery:
locator:
# 从服务注册中心根据别名来进行路由
enabled: true
routes:
# 路由Id,自定义,唯一即可
- id: nacos-provider-test
# 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名)
uri: lb://nacos-provider
# 成功匹配后,要转换成的路由地址(不配合服务注册中心)
#uri: http://localhost:8001
# 断言
predicates:
# 路径匹配的进行路由
- Path=/**
- Custom=test, a
- 测试:
- 启动nacos,能正常打开nacos首页
- 启动nacos-provider微服务,浏览器访问
localhost:8001/nacos/provider/test
接口,能正常返回信息,且在nacos服务列表中可看到成功注册 - 启动本微服务后,API工具访问
localhost/nacos/provider/test
接口,返回404。在header中,携带key为test、value为a的参数后再次访问,可以正常返回信息,查看响应头中有key为post、value为no args | test的参数。