這裡分類和彙總了欣宸的全部原創(含配套原始碼):https://github.com/zq2599/blog_demos
spring:
application:
name: hello-gateway
cloud:
gateway:
routes:
- id: path_route
uri: http://127.0.0.1:8082
predicates:
- Path=/hello/**
名稱 | 連結 | 備註 |
---|---|---|
專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協定 |
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協定 |
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tutorials</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway-dynamic-route</artifactId>
<dependencies>
<dependency>
<groupId>com.bolingcavalry</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 如果父工程不是springboot,就要用以下方式使用外掛,才能生成正常的jar -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.bolingcavalry.gateway.GatewayDynamicRouteApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.bolingcavalry.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayDynamicRouteApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayDynamicRouteApplication.class,args);
}
}
package com.bolingcavalry.gateway.filter;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
@Component
@Slf4j
public class BizLogicRouteGatewayFilterFactory extends AbstractGatewayFilterFactory<BizLogicRouteGatewayFilterFactory.BizLogicRouteConfig> {
private static final String TAG_TEST_USER = "tag-test-user";
public BizLogicRouteGatewayFilterFactory() {
super(BizLogicRouteConfig.class);
}
@Override
public GatewayFilter apply(BizLogicRouteConfig config) {
return (exchange, chain) -> {
// 本次的請求物件
ServerHttpRequest request = exchange.getRequest();
// 呼叫方請求時的path
String rawPath = request.getURI().getRawPath();
log.info("rawPath [{}]", rawPath);
// 請求頭
HttpHeaders headers = request.getHeaders();
// 請求方法
HttpMethod httpMethod = request.getMethod();
// 請求引數
MultiValueMap<String, String> queryParams = request.getQueryParams();
// 這就是客製化的業務邏輯,isTestUser等於ture代表當前請求來自測試使用者,需要被轉發到測試環境
boolean isTestUser = false;
// 如果header中有tag-test-user這個key,並且值等於true(不區分大小寫),
// 就認為當前請求是測試使用者發來的
if (headers.containsKey(TAG_TEST_USER)) {
String tageTestUser = headers.get(TAG_TEST_USER).get(0);
if ("true".equalsIgnoreCase(tageTestUser)) {
isTestUser = true;
}
}
URI uri;
if (isTestUser) {
log.info("這是測試使用者的請求");
// 從組態檔中得到測試環境的uri
uri = UriComponentsBuilder.fromHttpUrl(config.getTestEnvUri() + rawPath).queryParams(queryParams).build().toUri();
} else {
log.info("這是普通使用者的請求");
// 從組態檔中得到正式環境的uri
uri = UriComponentsBuilder.fromHttpUrl(config.getProdEnvUri() + rawPath).queryParams(queryParams).build().toUri();
}
// 生成新的Request物件,該物件放棄了常規路由設定中的spring.cloud.gateway.routes.uri欄位
ServerHttpRequest serverHttpRequest = request.mutate().uri(uri).method(httpMethod).headers(httpHeaders -> httpHeaders = httpHeaders).build();
// 取出當前的route物件
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
//從新設定Route地址
Route newRoute =
Route.async().asyncPredicate(route.getPredicate()).filters(route.getFilters()).id(route.getId())
.order(route.getOrder()).uri(uri).build();
// 放回exchange中
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR,newRoute);
// 鏈式處理,交給下一個過濾器
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
};
}
/**
* 這是過濾器的設定類,設定資訊會儲存在此處
*/
@Data
@ToString
public static class BizLogicRouteConfig {
// 生產環境的服務地址
private String prodEnvUri;
// 測試環境的服務地址
private String testEnvUri;
}
}
server:
#伺服器埠
port: 8086
spring:
application:
name: gateway-dynamic-route
cloud:
gateway:
routes:
- id: path_route
uri: http://0.0.0.0:8082
predicates:
- Path=/hello/**
filters:
- name: BizLogicRoute
args:
prodEnvUri: http://127.0.0.1:8082
testEnvUri: http://127.0.0.1:8087
package com.bolingcavalry.provider.controller;
import com.bolingcavalry.common.Constants;
import org.springframework.web.bind.annotation.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
@RestController
@RequestMapping("/hello")
public class Hello {
private String dateStr(){
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
}
/**
* 返回字串型別
* @return
*/
@GetMapping("/str")
public String helloStr() {
return Constants.HELLO_PREFIX + ", " + dateStr() + " (from test enviroment)";
}
}