pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<packaging>jarpackaging>
<parent>
<groupId>com.tdt.platform.cloudgroupId>
<artifactId>platform-cloud-b-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
parent>
<artifactId>cloud-gatewayartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>io.nettygroupId>
<artifactId>netty-resolver-dns-native-macosartifactId>
<version>4.1.79.Finalversion>
<classifier>osx-aarch_64classifier>
dependency>
dependencies>
project>
配置文件:
server:
port: 8000
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: product_route
uri: http://localhost:9002
order: 1
predicates:
- Path=/cloud-product-service/**
filters:
- StripPrefix=1
启动类:
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
然后启动网关工程,请求接口如图:
这样一个简易的网关就搭建好了。
引入依赖:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
启动类增加注解@EnableDiscoveryClient
配置文件中增加nacos相关配置:
server:
port: 8000
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
# 让gateway可以发现nacos中的微服务
enabled: false
routes:
# 路由标识
- id: product_route
# 路由指向的目的地,也就是说被转发到那个服务上
# uri: http://localhost:9002
uri: lb://cloud-product-service
# 断言条件判断,所有断言都验证通过,才会执行真正的路由
predicates:
# 以/cloud-product-service开头的请求
- Path=/cloud-product-service/**
# 过滤器
filters:
- StripPrefix=1
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
gateway中请求的执行流程,如图:
执行流程大体如下:
Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。 断言就是说: 满足什么条件才能进行路由转发。
该配置有坑: spring.cloud.gateway.discovery.locator.enabled
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
– After=2013-01-20T17:42:47.789-07:00[America/Denver]
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
– Before=2013-01-20T17:42:47.789-07:00[America/Denver]
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
– Between=Before=2013-01-20T17:42:47.789-07:00[America/Denver],Before=2013-01-20T17:42:47.789-07:00[America/Denver]
RemoteAddrRoutePredicateFactory接收一个IP地址段,判断请求主 机地址是否在地址段中
– RemoteAddr=192.168.1.1/24
CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求中cookie是否具有给定名称且值与正则表达式匹配
– Cookie=chocolate, ch.
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否具有给定名称且值与正则表达式匹配
– Header=X-Request-Id, \d+
HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
– Host=**.spring.org
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。
– Method=GET
PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。
– Path=/order-service/**
QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具有给定名称且值与正则表达式匹配。
– Query=baz, ba.
WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发
routes:
- id: weight_route1
uri: host1
predicates:
- Path=/product/**
- Weight=group3, 1
- id: weight_route2
uri: host2
predicates:
- Path=/product/**
- Weight= group3, 9
需求: 仅仅让年龄age在【minAge, maxAge】范围之间的请求通过。
首先在配置中添加Age断言:
– Age 18,65
自定义断言工厂:
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.AgeRoutePredicateConfig> {
public AgeRoutePredicateFactory() {
super(AgeRoutePredicateConfig.class);
}
// 用于从配置文件中获取参数值赋值到配置类中的属性上
@Override
public List<String> shortcutFieldOrder() {
// 这里的顺序要跟配置文件中的参数顺序一致
return Arrays.asList("minAge", "maxAge");
}
@Override
public Predicate<ServerWebExchange> apply(AgeRoutePredicateConfig config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
String age = serverWebExchange.getRequest().getQueryParams().getFirst("age");
if (StringUtils.hasText(age)) {
int targetAge = Integer.parseInt(age);
return targetAge >= config.getMinAge() && targetAge <= config.getMaxAge();
}
return false;
}
};
}
/**
* 用于接收配置文件中的参数
*/
public static class AgeRoutePredicateConfig {
private int minAge;
private int maxAge;
public int getMinAge() {
return minAge;
}
public void setMinAge(int minAge) {
this.minAge = minAge;
}
public int getMaxAge() {
return maxAge;
}
public void setMaxAge(int maxAge) {
this.maxAge = maxAge;
}
}
}
测试: