1.静态路由配置
spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
#断言,相当于if判断
#1. 请求cookie要有
- id: predicates_route_demo
#代理的访问地址 token,1212
uri: http://localhost:8081/
predicates:
- Path=/gateway/** #访问地址中有gateway
- Query=name,zhang #url中有key=name,vlaue=zhang
- Method=GET
#- Header=key,value
- Cookie=token,1212 #cookie中key=token,value=1212
- Auth=Authorization #自定义key= Authorization
#拦截器
filters:
# http://localhost:8081/gateway/hello
- StripPrefix=1 #去掉端口后的第一个节点,即将gateway去掉
#2. 请求头限制
# - id: add_request_parameter_router
- id: add_request_header_router
uri: http://localhost:8081/
predicates:
- Path=/header/** #访问地址中有gateway
filters:
# 在header中增加一个 key=name,value=unix
- AddRequestParameter=name,unix
#3.请求路由限制
- id: request_reatelimiter_route
uri: http://localhost:8081/
predicates:
- Path=/ratelimiter/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
keyResolver: '#{@ipAddressKeyResolver}'
redis-rate-limiter.replenishRate: 1 #处理速度
redis-rate-limiter.burstCapacity: 2 #容量
#4.报503,重试3次
- id: retry_route
uri: http://localhost:8081/
predicates:
- Path=/retry/**
filters:
- StripPrefix=1
- name: Retry
args:
retries: 3
status: 503 #当服务端返回的状态买是503的时候,才会重试
#5。自定义路由
- id: define_route
uri: http://localhost:8081/
predicates:
- Path=/define/**
filters:
- StripPrefix=1
- name: TestDefine
- TestDefine=Test_X # 自定义TestDefine=》TestDefineGatewayFilterFactory
#6.负载均衡
- id: gateway_router
uri: lb://eureka-user-service
predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
#7动态路由,服务发现
discovery:
locator:
lower-case-service-id: true #小写
enabled: true
redis:
host: 127.0.0.1
server:
port: 8888
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka,http://localhost:8762/eureka
#动态路由 服务
management:
endpoints:
web:
exposure:
include: "*"
2.动态路由
a. #7动态路由,服务发现
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
/**
* 自定义路由
*/
@Component
public class TestDefineGatewayFilterFactory extends AbstractGatewayFilterFactory<TestDefineGatewayFilterFactory.Config> {
Logger logger=LoggerFactory.getLogger(TestDefineGatewayFilterFactory.class);
public TestDefineGatewayFilterFactory() {
super(Config.class);
}
public static final String NAME_KEY="name";
/**
* 定义快捷键name,application.yml=》 - TestDefine=Test_X 可以直接定义
* TestDefine相当于namea
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(NAME_KEY);
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
logger.info("[Pred] Filter Request,Name:"+config.getName());
return chain.filter(exchange).then(Mono.fromRunnable(()->{
String code = exchange.getResponse().getStatusCode().toString();
logger.info("[Post] Response Filter " + code);
}));
});
}
public static class Config{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
b. 动态路由持久化到redis中,
gateway动态路由默认是保存在内存中,重启会删除。
package com.example.demo;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
@Component
public class RedisRouteDefinitionRespository implements RouteDefinitionRepository {
private final static String GATEWAY_ROUTE_KEY="gateway_dynamic_route";
@Autowired
RedisTemplate<String,String> redisTemplate;
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> routeDefinitions = new ArrayList<>();
redisTemplate.opsForHash().values(GATEWAY_ROUTE_KEY).stream().forEach(route->{
routeDefinitions.add(JSON.parseObject(route.toString(),RouteDefinition.class));
});
return Flux.fromIterable(routeDefinitions);
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> {
redisTemplate.opsForHash().put(GATEWAY_ROUTE_KEY,routeDefinition.getId(), JSON.toJSONString(routeDefinition));
return Mono.empty();
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id->{
if(redisTemplate.opsForHash().hasKey(GATEWAY_ROUTE_KEY,id)){
redisTemplate.opsForHash().delete(GATEWAY_ROUTE_KEY,id);
return Mono.empty();
}
return Mono.defer(()->Mono.error(new Exception("routeDefiniton no found"+routeId)));
});
}
}