目录
介绍:
核心概念
依赖
路由
断言
基本的断言工厂
自定义断言
过滤器
路由过滤器
过滤器工厂
自定义路由过滤器
全局过滤器
其他
过滤器执行顺序
前置后置(?)
跨域问题
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: gatewaycloud:nacos:discovery:server-addr: 192.168.178.129:8848gateway:routes:- id: shop-useruri: lb://shop-user # nacos 中注册的服务名predicates:- Path=/config/test- id: shop-user2uri: 192.168.178.128:111 #ippredicates:- 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 |
全部:GatewayFilter 工厂
默认过滤器
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//orderservicepredicates:- 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);}@Overridepublic GatewayFilter apply(MyGatewayFilterFactory.Config config){return new GatewayFilter(){@Overridepublic 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();}}};}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("status");}public static class Config{@Getter@Setterprivate String status;//设定一个状态值/标志位,它等于多少,匹配和才可以访问}
}
全局过滤器
创建全局过滤器实现GlobalFilter, Ordered 接口,重写其中的方法
public class MyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 在此处编写全局过滤器的逻辑return chain.filter(exchange);}/*** 数字越小优先级越高* @return*/@Overridepublic int getOrder(){return 1;}
}
其他
过滤器执行顺序
默认路由过滤器 --》路由过滤器 ---》 全局过滤器
前置后置(?)
前置过滤直接在return chain.filter(exchange); 前写入前置逻辑
后置过滤器
@Overridepublic 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 #是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期
配置类解决
@Configuration
public class CorsConfig {@Beanpublic 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);}
}