新建cloud-gateway-service项目
在项目下创建pom.xml
<?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>cloud</artifactId><groupId>com.gf.springcloud</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-gateway-service</artifactId><dependencies><!--SpringCloud ailibaba nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--基于 reactive stream 的redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.gf.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--一般基础配置类--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</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></project>
创建配置
创建bootstrap.yml
server:
port: 8004 #服务端口
spring:
application:
name: cloud-gateway-service #服务名
cloud:
nacos:
discovery:
server-addr: 172.18.0.3:30000 #配置Nacos地址
devtools:
restart:
enabled: true #是否支持热部署
创建application.yml
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
# routes:
# - id: api-order
# # uri: http://localhost:8002
# uri: lb://cloud-order-consumer
# order: 8002
# predicates:
# - Path=/consumer/payment/get/**
redis:
################### redis 单机版 start ##########################
host: 127.0.0.1
port: 6379
timeout: 6000
database: 8
lettuce:
pool:
max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)
max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8
max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0
shutdown-timeout: 100ms
################### redis 单机版 end ##########################
# cluster:
# nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001
# #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001
# #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001
# timeout: 1000 # 连接超时时间(毫秒)
# lettuce:
# pool:
# max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)
# max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8
# max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
# min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0
# shutdown-timeout: 100ms
ribbon:
ReadTimeout: 90000
ConnectTimeout: 90000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: false
feign:
sentinel:
# 为feign整合sentinel
enabled: true
java代码
创建RedisConstants.java,用于记录redis的key
public class RedisConstants {
public static final String GATEWAY_ROUTES_PREFIX = "GATEWAY_ROUTES";
}
创建dto
GatewayPredicateDefinition.java
/**
* 路由断言模型
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GatewayPredicateDefinition {
private String name;
@Builder.Default
private Map<String, String> args = new LinkedHashMap<>();
}
GatewayFilterDefinition.java
/**
* 路由过滤器模型
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GatewayFilterDefinition {
private String name;
@Builder.Default
private Map<String, String> args = new LinkedHashMap<>();
}
GatewayRouteDefinition.java
/**
* 创建路由模型
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GatewayRouteDefinition {
//路由的Id
private String id;
//路由断言集合配置
@Builder.Default
private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
//路由过滤器集合配置
@Builder.Default
private List<GatewayFilterDefinition> filters = new ArrayList<>();
//路由规则转发的目标uri
private String uri;
//路由执行的顺序
@Builder.Default
private int order = 0;
//路由描述
private String description;
}
创建service
DynamicRouteService.java
/**
* 操作 路由 Service
*/
public interface DynamicRouteService {
/**
* 新增路由
*
* @param gatewayRouteDefinition
* @return
*/
String add(GatewayRouteDefinition gatewayRouteDefinition);
/**
* 修改路由
*
* @param gatewayRouteDefinition
* @return
*/
String update(GatewayRouteDefinition gatewayRouteDefinition);
/**
* 删除路由
*
* @param id
* @return
*/
String delete(String id);
}
实现接口DynamicRouteServiceImpl.java
@Service
public class DynamicRouteServiceImpl implements DynamicRouteService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
@Override
public String add(GatewayRouteDefinition gatewayRouteDefinition) {
stringRedisTemplate.boundHashOps(GATEWAY_ROUTES_PREFIX)
.put(gatewayRouteDefinition.getId(), JSONObject.toJSONString(gatewayRouteDefinition));
return gatewayRouteDefinition.getId();
}
@Override
public String update(GatewayRouteDefinition gatewayRouteDefinition) {
delete(gatewayRouteDefinition.getId());
add(gatewayRouteDefinition);
return gatewayRouteDefinition.getId();
}
@Override
public String delete(String id) {
stringRedisTemplate.boundHashOps(GATEWAY_ROUTES_PREFIX).delete(id);
return id;
}
}
创建controller
RouteController.java
@RestController
@RequestMapping("/route")
public class RouteController {
@Autowired
private DynamicRouteService dynamicRouteService;
//增加路由
@PostMapping("/add")
public Mono<CommonResult> add(@RequestBody GatewayRouteDefinition gatewayRouteDefinition) {
return Mono.just(CommonResult.succeed(dynamicRouteService.add(gatewayRouteDefinition)));
}
//更新路由
@PostMapping("/update")
public Mono<CommonResult> update(@RequestBody GatewayRouteDefinition gatewayRouteDefinition) {
return Mono.just(CommonResult.succeed(dynamicRouteService.update(gatewayRouteDefinition)));
}
//删除路由
@DeleteMapping("/{id}")
public Mono<CommonResult> delete(@PathVariable String id) {
return Mono.just(CommonResult.succeed(dynamicRouteService.delete(id)));
}
}
创建RedisRouteDefinitionRepository.java路由的配置从redis上面获取
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
@Resource
private StringRedisTemplate stringRedisTemplate;
private Set<RouteDefinition> routeDefinitions = new HashSet<>();
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
routeDefinitions.clear();
BoundHashOperations<String, String, String> boundHashOperations = stringRedisTemplate.boundHashOps(GATEWAY_ROUTES_PREFIX);
Map<String, String> map = boundHashOperations.entries();
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
routeDefinitions.add(JSON.parseObject(entry.getValue(), RouteDefinition.class));
}
return Flux.fromIterable(routeDefinitions);
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> {
routeDefinitions.add(routeDefinition);
return Mono.empty();
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
List<RouteDefinition> routeDefinitionList = routeDefinitions.stream().filter(
routeDefinition -> StringUtils.equals(routeDefinition.getId(), id)
).collect(Collectors.toList());
routeDefinitions.removeAll(routeDefinitionList);
return Mono.empty();
});
}
}
创建启动类GateWayMain.java
@SpringBootApplication
public class GateWayMain
{
public static void main(String[] args) {
SpringApplication.run(GateWayMain.class, args);
}
}
测试
使用postman请求http://127.0.0.1:8004/route/add,
请求的body
{
"id": "api-order",
"uri": "lb://cloud-order-consumer",
"order": 8002,
"predicates": [{"name":"Path","args": {"pattern":"/consumer/payment/get/**"}}]
}

启动cloud-provider-payment、cloud-consumer-order、cloud-gateway-service这里的启动顺序不能乱
访问http://127.0.0.1:8004/consumer/payment/get/1

