目录
[yaml 解决](#yaml 解决)
介绍:
Gateway网络为微服务架构提供简单且统一的API路由管理,作为系统的统一入口。
核心概念
路由 (route):路由是网关中最基础的部分,路由信息包括一个ID、一个URI、一组断言工厂、一组Filter组成。
断言 (predicates):断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。如果断言为真,则说明请求的URL和配置的路由匹配。
过滤器(Filter):Spring Cloud Gateway中的filter分为Gateway Filter和Global Filter。Filter可以对请求和响应进行处理。Filter只有pre和post两种。
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
路由
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 192.168.178.129:8848
gateway:
routes:
- id: shop-user
uri: lb://shop-user # nacos 中注册的服务名
predicates:
- Path=/config/test
- id: shop-user2
uri: 192.168.178.128:111 #ip
predicates:
- Path=/config/test2
断言
基本的断言工厂
|------------|-------------------|---------------------------------------------------------------------------------------------------------|
| Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
| After | 是某个时间点后的请求 | - After=2012-01-20T17:42:47.789-07:00[America/Denver] |
| Before | 是某个时间点之前的请求 | - Before=2012-01-20T17:42:47.789+07:00[Asia/Shanghai |
| Between | 是某两个时间点之前的请求 | - Between=2012-01-20T17:42:47.789-07:00[America/Denver] ,2012-01-20T17:42:47.789+07:00[Asia/Shanghai |
| Cookie | 请求必须包含某些cookie | - Cookie=chocolate,ch.p |
| Header | 请求必须包含某些header | - Header=X-Request-ld, \d+ |
| Host | 请求必须是访问某个host(域名) | - Host=.something.org,.anotherhost.org |
| Method | 请求凡是必须是指定方式 | - Method=GEt,POST |
| Query | 请求参数必须包含指定参数 | - Query=name,kack或者- Query=name |
| RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
官网: 路由谓词工厂
自定义断言
步骤:
-
开头任意取名,但是必须以RoutePredicateFactory后缀结尾
-
继承AbstractRoutePredicateFactory抽象类仿照这个源码写,这个源码的路由规则是根据时间来定义的
public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory<Config> {
public static final String DATETIME_KEY = "datetime";public AfterRoutePredicateFactory() { super(Config.class); } //支持shortcut 如果不重写 用简便形式写就会报错 public List<String> shortcutFieldOrder() { return Collections.singletonList("datetime"); } //ServerWebExchange这个类似与request,这个是判断是否让请求通过的规则 public Predicate<ServerWebExchange> apply(final Config config) { return new GatewayPredicate() { public boolean test(ServerWebExchange serverWebExchange) { ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(config.getDatetime()); } public Object getConfig() { return config; } public String toString() { return String.format("After: %s", config.getDatetime()); } }; } //路由规则 public static class Config { private @NotNull ZonedDateTime datetime; public Config() { } public ZonedDateTime getDatetime() { return this.datetime; } public void setDatetime(ZonedDateTime datetime) { this.datetime = datetime; } }
}
过滤器
路由过滤器
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器仅适用于特定的路由。
过滤器工厂
|------------------------|------------------|------------------------------------------|
| AddRequestHeader | 给当前请求添加一个请求头 | - AddRequestHeader=X-Request-red, blue |
| RemoveRequestHeader | 移除请求头 | - RemoveRequestHeader=X-Request-Foo |
| SetRequestHeader | 标记请求头 | - SetRequestHeader=X-Request-Red, Blue |
| AddRequestParameter | 添加请求参数 | - AddRequestParameter=red, blue |
| RemoveRequestParameter | 删除请求参数 | - RemoveRequestParameter=red |
| RemoveResponseHeader | 从响应结果中移除一个响应头 | - RemoveResponseHeader=X-Response-Foo |
| SetResponseHeader | 编辑响应中的响应头 | - SetResponseHeader=X-Response-Red, Blue |
| RemoveResponseHeader | 删除响应中的响应头 | - RemoveResponseHeader=X-Response-Foo |
| PrefixPath | 这将作为所有匹配请求的路径的前缀 | - PrefixPath=/mypath |
| SetPath | 修改访问地址 | - SetPath=/segment |
| RedirectTo | 重定向 | - RedirectTo=302, https://acme.org |
默认过滤器
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes:
- id: user-service
# url: http://127.0.0.1:8081
url: lb//userservice
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/usr/** # 这个是按照路径匹配,只要以/user/开头就符合要求
- id: order-service
url: lb//orderservice
predicates:
- Path=/order/**
default-filters: # 默认过滤器,会对所有的路由请求都生效
- AddRequestHeader=Truth,luxifa is following her dream # 添加请求头
自定义路由过滤器
1、新建过滤器名称要以GatewayFilterFactory结尾
2、继承AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>重写其中的方法
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
public MyGatewayFilterFactory()
{
super(MyGatewayFilterFactory.Config.class);
}
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config)
{
return new GatewayFilter()
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
ServerHttpRequest request = exchange.getRequest();
System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:"+config.getStatus());
if(request.getQueryParams().containsKey("atguigu")){
return chain.filter(exchange);
}else{
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("status");
}
public static class Config
{
@Getter@Setter
private String status;//设定一个状态值/标志位,它等于多少,匹配和才可以访问
}
}
全局过滤器
创建全局过滤器实现GlobalFilter, Ordered 接口,重写其中的方法
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 在此处编写全局过滤器的逻辑
return chain.filter(exchange);
}
/**
* 数字越小优先级越高
* @return
*/
@Override
public int getOrder()
{
return 1;
}
}
其他
过滤器执行顺序
默认路由过滤器 --》路由过滤器 ---》 全局过滤器
前置后置(?)
前置过滤直接在**return chain.filter(exchange);**前写入前置逻辑
后置过滤器
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain, String name, String args) {
Mono<Void> result = chain.filter(exchange);
return result.then(Mono.fromRunnable(() -> {
// 编写后置逻辑
}));
}
跨域问题
yaml 解决
spring:
cloud:
gateway:
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]': # 拦截所有请求
allowedOrgins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求头携带的信息 * 代表允许所有请求头
allowCredentials: true #是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
配置类解决
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}