yml配置网关路由
Gateway网关路由有两种配置方式,一种用yml配置
新建cloud-gateway-gateway9527
模块

pom
不要引入spring web依赖,否则启动不了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.kylin</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
yml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| server: port: 9527 spring: application: name: cloud-gateway
eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
主启动类
创建主启动类GateWayMain9527

1 2 3 4 5 6 7
| @SpringBootApplication @EnableEurekaClient public class GateWayMain9527 { public static void main(String[] args) { SpringApplication.run( GateWayMain9527.class,args); } }
|
新增网关配置
我们目前不想暴露8001端口,希望在8001外面套一层9527
给cloud-provider-payment8001
的两个方法做路由映射


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: routes: - id: payment_routh uri: http://localhost:8001 predicates: - Path=/payment/get/**
- id: payment_routh2 uri: http://localhost:8001 predicates: - Path=/payment/lb/**
eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
测试
启动7001 8001 9527 http://eureka7001.com:7001/
成功注册到Eureka注册中心

访问http://localhost:8001/payment/get/31

访问http://localhost:9527/payment/get/31
,也能访问成功

访问http://localhost:9527/payment/lb
d
编码码配置网关路由
Gateway网关路由有两种配置方式,一种用编码配置
我们想通过9527网关访问到外网的百度新闻网址
配置类
编写配置类GateWayConfig

1 2 3 4 5 6 7 8 9
| @Configuration public class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_rote_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build(); return routes.build(); } }
|
测试
重新启动9527,访问http://localhost:9527/guonei

实现动态路由
我们当前的路由映射是将地址写死了

而我们应该要达到的效果是同以前一样,通过访问微服务提供者的服务命调用所提供的服务,尽管这个微服务是一个集群。这些客户端都不关心,所以我们要配置GateWay通过微服务名实现动态路由。
yml

通过配置spring.cloud.gateway.discovery.locator.enabled
开启从注册中心动态创建路由的功能,利用微服务名进行路由,默认false
此时的spring.cloud.gateway.routes
list集合中的uri属性值为lb://serviceName
uri的协议为lb,表示启用Gateway的负载均衡功能。serviceName时注册中心注册的名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true routes: - id: payment_routh uri: lb://cloud-payment-service predicates: - Path=/payment/get/**
- id: payment_routh2 uri: lb://cloud-payment-service predicates: - Path=/payment/lb/**
eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
测试
启动7001 8001 8002 9525 访问http://localhost:9527/payment/lb


动态路由配置成功!
Predicate的使用
当我们启动的我们9527的时候会看见控制台输出

我们之前使用Predicate是属性名是predicates
说明它能配置多个匹配条件,而我们目前只匹配了Path
条件

Route Predicate Factorie
查看官网https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping
基础架构的一部分。Spring Cloud Gateway包括许多内置的路由谓词工厂。
Spring Cloud Gateway创建Route对象时,使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories。
所有这些谓词都与HTTP请求的不同属性匹配。您可以将多个路由谓词工厂与逻辑and
语句结合使用。
常用的Predicate


请求时间满足在配置时间之后

这个时间怎么获得呢?
通过Java提供的ZonoeDateTime.now()
获得当地的时间

After=时间
我们把时间改为自己当地的时间后一分钟进行测试
重新启动测试,访问http://localhost:9527/payment/get/31
此时再配置时间之前。报错404

配置时间之后在访问,一切正常

同理Before Between也是一样的配置和使用
配置文件predicates
加上Cookie

Cookie=username,kylin
只允许cookie键为username 值为kylin
通过命令行curl http://localhost:9527/payment/lb
访问

不符合条件报错404
加上cookie访问curl http://localhost:9527/payment/lb --cookie "username=kylin"

访问成功!一切正常

Header=X-Request-Id, \d+
请求头要有X-Request-Id属性并且值为整数的正则表达式
访问curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
值为整数,一切正常

值为负数curl http://localhost:9527/payment/lb -H "X-Request-Id:-123"

报错404,配置成功!
说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理
Filter的使用
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器适用于特定路由。Spring Cloud Gateway内置了多种路由过滤器,他们都有GatewayFilter的工厂类来产生
Filter的声明周期只有两个“pre” 和 “post”。“pre”和 “post” 分别会在请求被执行前调用和被执行后调用。种类分为单一的,和全局的。
Filter,在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出、流量监控等,有非常重要的作用
Filter除了分为“pre”和“post”两种方式的Filter外,在Spring Cloud Gateway中,Filter从作用范围可分为另外两种,一种是针对于单个路由的Gateway Filter,它在配置文件中的写法同predict类似;另外一种是针对于所有路由的Global Gateway Filer。现在从作用范围划分的维度来讲解这两种Filer。
单一过滤器GatewayFilter
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories
全局GlobalFilter
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#global-filters

自定义全局过滤器
Gateway提供好的过滤器并没有太大的意义,我们可以自定义过滤器编写业务逻辑
将我们配置Predicate注释,编写MyLogGateWayFilter
实现GlobalFilter, Ordered
,判断是否带有uname参数不能为null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Component @Slf4j public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("*************come in MyLogGateWayFilter:"+new Date()); String uname = exchange.getRequest().getQueryParams().getFirst("uname"); if (uname==null){ log.info("********用户名为null,非法用户,/(ㄒoㄒ)/~~"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange); }
@Override public int getOrder() { return 0; } }
|
启动7001 8001 8002 9527进行测试直接访问http://localhost:9527/payment/lb
,访问不拦截

http://localhost:9527/payment/lb?uname=kylin
加上uanme参数且值不为null


访问成功!