前言
Spring Cloud Gateway为Spring生态系统上的一个API网关组件,主要提供一种简单而有效的方式路由映射到指定的API,并为他们提供安全性、监控和限流等等。
前提条件
1.在项目中包含Spring Cloud Gateway,在Maven项目中pom.xml中将_groupId=org.springframework.cloud_和_artifactId=spring-cloud-starter-gateway_依赖进去,如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
2.如果包含了spring-cloud-starter-gateway启动器,由于某种原因,不希望启动gateway,则可以在 application.properties配置文件中进行设置:
spring.cloud.gateway.enabled=false
或在application.yml配置:
spring:
cloud:
gateway:
enabled: false
3.Spring Cloud Gateway基于Spring Boot2.0,Spring WebFlux和Project Reactor构建;如果想深入了解建议先了解它们。
4.需要了解的用到词汇
Route(路由):路由网关的基本构建模块,它是由ID、目标URl、断言集合和过滤器集合定义,如果集合断言为真,则匹配路由。
Predicate(断言):这是java 8的一个函数式接口predicate,可以用于lambda表达式和方法引用,输入类型是:Spring Framework ServerWebExchange,允许开发人员匹配来自HTTP请求的任何内容,例如请求头headers和参数paramers.
Filter(过滤器):这些是使用特定工厂构建的Spring Framework GatewayFilter实例,这里可以在发送下游请求之前或之后修改请求和响应。
5.必须知道Spring Cloud Gateway运行流程:
解释:当客户端向spring cloud gateway发送请求,如果网关处理程序映射请求与路由匹配,就将其发送到指定的网关web处理程序服务,此处理程序服务运行并通过特定请求的过滤器之后发送请求,过滤器被虚线划分的原因是过滤器可以在发送代理请求之前或之后执行逻辑,执行完前面指定"pre"类型的过滤器之后进行代理服务请求,在代理服务请求被执行之后,又执行指定"post"类型的过滤器的相关逻辑处理。
具体使用
一、路由断言(Route Predicate)使用
0.使用之前先说一下关于断言predicate的用法:
predicate是java 8中的新特性,java.util.function.Predicate的一个功能接口,可用做lambda表达式的赋值目标。Predicate接口表示采用单个输入并判断返回boolean值的操作;判断的条件可以使用与或非(and,or,negate)等,通过一个断言predicate可以重复利用判断。用例:
package com.demo.pakage;
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
/*
* 1.predicate test()方法
*
* */
//predicate Sting
Predicate<String> predicateStr=str->{
return str.equals("String");
};
//使用test()方法执行断言,输出true,false
System.out.println(predicateStr.test("String"));
System.out.println(predicateStr.test("string"));
//Predicate integer
Predicate<Integer> predicateInt=i->{
return i>0;
};
//输出true,false
System.out.println(predicateInt.test(5));
System.out.println(predicateInt.test(-1));
/*
*
* 2.predicate add(),or(),negate()方法
* */
Predicate<String> predicate=s->{
return s.equals("String");
};
//and()方法,输出true
Predicate<String> predicateAnd=predicate.and(s->s.length()>5);
System.out.println(predicateAnd.test("String"));
//or()方法,输出true
Predicate<String> predicateOr=predicate.or(s->s.length()==4);
System.out.println(predicateOr.test("String"));
//negate()方法,取反,输出false
Predicate<String> predicateNegate=predicate.negate();
System.out.println(predicateNegate.test("String"));
}
}
1.通过配置applicaton.yml文件进行路由断言使用,predicate根据具体的请求规则,匹配具体的route去处理;Spring Cloud Gateway包含很多的内置路由断言(Route Predicate),这些断言可以去匹配HTTP请求的不同属性如Cookie匹配、Header匹配、Host匹配、Method匹配、Path匹配、Query匹配、RemoteAddr匹配以及匹配路由断言之前或之后或之间的请求。如下图:
具体yml配置文件格式如下:
spring:
profiles:
active: "与下面的某个id值相同"
---
#路由断言之后匹配
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://xxxx.com
predicates:
- After=xxxxx
#路由断言之前匹配
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://xxxxxx.com
predicates:
- Before=xxxxxxx
#路由断言之间
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://xxxx.com
predicates:
- Between=xxxx,xxxx
#路由断言Cookie匹配,此predicate匹配给定名称(chocolate)和正则表达式(ch.p)
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://xxxx.com
predicates:
- Cookie=chocolate, ch.p
#路由断言Header匹配,header名称匹配X-Request-Id,且正则表达式匹配d+
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://xxxx.com
predicates:
- Header=X-Request-Id, d+
#路由断言匹配Host匹配,匹配下面Host主机列表,**代表可变参数
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://xxxx.com
predicates:
- Host=**.somehost.org,**.anotherhost.org
#路由断言Method匹配,匹配的是请求的HTTP方法
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://xxxx.com
predicates:
- Method=GET
#路由断言匹配,{segment}为可变参数
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://xxxx.com
predicates:
- Path=/foo/{segment},/bar/{segment}
#可以通过java方法获取{segname}:
#Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
#String segment = uriVariables.get("segment");
#路由断言Query匹配,将请求的参数param(baz)进行匹配,也可以进行regexp正则表达式匹配 (参数包含foo,并且foo的值匹配ba.)
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://xxxx.com
predicates:
- Query=baz 或 Query=foo,ba.
#路由断言RemoteAddr匹配,将匹配192.168.1.1~192.168.1.254之间的ip地址,其中24为子网掩码位数即255.255.255.0
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
二、Gateway Filter过滤器的使用(网关的重点)
上面的Router Predicate路由断言就决定了请求由哪一个路由处理,在路由处理之前,需要经过"pre"类型的Filter路由过滤器处理,处理完返回响应之后,又可以由"post"类型的路由过滤器处理。Gateway路由过滤器允许修改传入的HTTP请求和返回的HTTP响应,过滤器可以限定作用在某些特定请求路径上;在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;在"post"类型的过滤器可以做响应内容、响应头的修改,日志的输出,流量监控等。因此filter可以分两种类型:"pre"类型和"post"类型。从作用范围又可以分为针对单个路由的filter和针对所有路由的global filter。
Spring Cloud Gateway包含很多内置的GatewayFilter工厂,如下图:
1.列举其中一个Gateway Filter例子:RewritePath GatewayFilter Factory(重写路径,zuul是没有的功能)
spring:
profiles:
action: rewritepath_route
---
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: http://www.baidu.com
predicate:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*),/${segment}
profiles: rewritepath_route
上面的配置中,所有的/foo/**开始的路径都会命中配置的router,并执行过滤器的逻辑,在本案例中配置了RewritePath过滤器工厂,此工厂将/foo/(.*)重写为{segment}
2.自定义过滤器
可以实现自己定义的过滤器,在自己定义的过滤器类中需要实现GatewayFilter接口,主要重写其抽象方法filter(ServerWebExchange,GatewayFilterChain);和实现Ordered接口,重写getOrder()返回该过滤器的优先顺序order;也可以不实现Ordered接口,在启动类调用该过滤器的时候使用注解@Order(-1)来设置优先顺序。
待续。。。。