[TOC]
*****
# 1. Spring Cloud Gateway是什么?
```
1. 是Spring Cloud的網關(第二代),未來將會取代Zuul(第一代)
2. 基于Netty, Reactor以及WebFlux構建
3. 性能是Zuul的1.6倍, 參考: https://www.imooc.com/article/285068
4. 功能強大,內置了很多實用功能,比如轉發 / 監控 / 限流等.
5. 設置優雅,容易擴展
缺點:
依賴Netty與WebFlux,不是Servlet編程模型;
不能在Servlet容器下工作,也不能構建成WAR包,只能構建成jar包;
不支持Spring Boot 1.x
```
# 2. 使用gateway搭建網關
代碼參考: [ali-gateway-service 服務](https://gitee.com/lin_2019/alibaba-cloud/tree/master/ali-gateway-service)
```
注意: 不要引入spring-boot-starter-web包,會導致Gateway啟動拋出異常,錯誤如下. 因為Spring Cloud Gateway 是使用 netty+webflux實現,webflux與web是沖突的.
Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.
```
# 3. Gateway的核心概念
```
源碼:
Gateway Handler Mapping: org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping
Gateway Web Handler: org.springframework.cloud.gateway.handler.FilteringWebHandler
運行原理:
外部請求請求到Gateway, Gateway Handler Mapping會判斷請求是否匹配路由的配置,
若匹配則交給Gateway Web Handler,它對讀取路由上配置的過濾器,把請求交給過濾器做處理.
```

```
1. Route(路由)
Spring Cloud Gateway的基礎元素, 可簡單理解成一條轉發的規則.
包含: ID,目標URL, Predicate集合以及Filter集合.
2. Predicate(謂詞/斷言)
即 java.util.function.Predicate, Spring Cloud Gateway使用Predicate實現路由的匹配條件.
3. Filter(過濾器)
修改請求及相應
```
```
如圖示例:
代表訪問spring cloud gateway的 /users/1這個路徑時,就會進入該路由,它會用AddRequestHeader這個過濾器做一些處理,
然后再把請求轉發到uri指定的 http://www.itmuch.com
```

# 4. 內置路由謂詞工廠詳解(RoutePredicateFactories)
```
路由謂詞即條件 具體使用參考: https://www.imooc.com/article/290804
```

# 5. 自定義路由謂詞工廠
```
需求: 自定義謂詞工廠 限制09:00 - 17:00才能訪問
```
```
# 網關gateway配置
spring:
cloud:
gateway:
discovery:
locator:
# 讓gateway通過服務發現組件找到其他微服務
enabled: true
# 配置路由
routes:
- id: after_route
uri: lb://ali-app-service
predicates:
# 當且僅當請求時的時間After配置的時間時,才會轉發到用戶微服務
# 目前配置不會進該路由配置,所以返回404
# 將時間改成 < now的時間,則訪問localhost:8040/** -> user-center/**
# eg. 訪問http://localhost:8040/users/1 -> user-center/users/1
# - After=2030-01-20T17:42:47.789-07:00[America/Denver]
# 自定義謂詞工廠規則 http://localhost:9999/test?param=1
- TimeBetween=上午10:50,下午5:00
```
```
/**
* TimeBetweenRoutePredicateFactory = 配置文件中定義的名稱(TimeBetween) + RoutePredicateFactory(約定)
* 自定義謂詞路由工廠要以[RoutePredicateFactory]結尾
* TimeBetweenConfig配置類指配置文件中的配置 [9:00, 17:00]
*
* TimeBetween
*/
@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenConfig> {
public TimeBetweenRoutePredicateFactory() {
super(TimeBetweenConfig.class);
}
//
@Override
public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
LocalTime startTime = config.getStart();
LocalTime endTime = config.getEnd();
return exchange -> {
LocalTime now = LocalTime.now();
return now.isAfter(startTime) && now.isBefore(endTime);
};
}
//控制配置類與配置文件的映射關系(start映射為9:00, end映射為17:00)
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("start", "end");
}
}
@Data
public class TimeBetweenConfig {
private LocalTime start;
private LocalTime end;
}
```
# 6. 內置過濾器工廠詳解(GatewayFilterFactories)
```
過濾器為請求及相應添加業務邏輯處理;
具體使用參考: https://www.imooc.com/article/290816
如: 配置
# 過濾器配置
filters:
- AddRequestParameter=foo, bar
可以斷點打在 org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter,就可以調試Gateway轉發的具體細節
```
# 7. 自定義過濾器工廠【生命周期、自定義的方式、核心API、編碼】
```
7-1. 過濾器生命周期
pre: Gateway轉發請求之前
post: Gateway轉發請求之后
```
```
7-2. 自定義過濾器工廠的方式
方式1. 繼承AbstractGatewayFilterFactory, 配置形式如下圖:
源碼參考: org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory
```

```
方式2. 繼承AbstractNameValueGatewayFilterFactory, 配置形式如下圖:
源碼參考: org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory
```

```
7-3. 核心API
exchange.getRequest().mutate().xxx //修改request請求
exchange..mutate().xxx //修改exchange
chain.filter(exchange) //傳遞給下一個過濾器處理
exchange.getResponse() //拿到響應
```
```
7-4. 編寫一個過濾器工廠(注意: 新建類必須以[GatewayFilterFactory]結尾)
需求: 進入到過濾器工廠時,記錄一下日志
注意: PreLogGatewayFilterFactory 的組成是配置文件中PreLog + GatewayFilterFactory,嚴格定義
@Slf4j
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return ((exchange, chain) -> {
//getName獲取a, getValue獲取b
log.info("請求進來了...{}, {}", config.getName(), config.getValue());
//修改請求
ServerHttpRequest modifiedRequest = exchange.getRequest().mutate().build();
//修改Exchange
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
//處理完成傳遞給下一個過濾器處理
return chain.filter(modifiedExchange);
});
}
}
# 過濾器配置
filters:
- PreLog=a,b
```
# 8. 全局過濾器
```
參考: https://www.imooc.com/article/290821
```
# 9. 監控SpringCloudGateway
```
參考: https://www.imooc.com/article/290822
```
# 10. 排錯、調試技巧總結【調試排錯三板斧】
```
參考: https://www.imooc.com/article/290824
```
# 11. 過濾器執行順序
`11-1. 執行順序`

`11-2. 自定義控制order`
```
@Slf4j
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
GatewayFilter filter = ((exchange, chain) -> {
//getName獲取a, getValue獲取b
log.info("請求進來了...{}, {}", config.getName(), config.getValue());
//修改請求
ServerHttpRequest modifiedRequest = exchange.getRequest().mutate().build();
//修改Exchange
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
//處理完成傳遞給下一個過濾器處理
return chain.filter(modifiedExchange);
});
//第二個參數就是定義order順序的
return new OrderedGatewayFilter(filter, 1000);
}
}
```
# 12. 源碼分析

# 13. SpringCloudGateway限流
```
參考: https://www.imooc.com/article/290828
```
# 生成漂亮的靜態文檔說明頁
```
參考:http://www.itmuch.com/other/doc-generate/
```