赞
踩
id: 路由的ID
uri: 匹配路由的转发地址
predicates: 配置该路由的断言,通过PredicateDefinition类进行接收配置。
order: 路由的优先级,数字越小,优先级越高。
Filter: 过滤器 过滤掉一些请求, 满足则转发
配置该路由的断言,通过PredicateDefinition类进行接收配置。
Predicate 来源于Java8,接受输入参数,返回一个布尔值结果
Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则
转发的判断条件.
SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等
支持多个Predicate请求的转发是必须满足所有的Predicate后才可以进行路由转发
参数编写规则 XXXRoutePredicateFactory,使用XXX作为参数配置, 例如下面
predicates:
我们来看一个类 叫做 BeforeRoutePredicateFactory 类 这个类定义断言行为是 如果当前时间大于我们配置的时候,则不允许转发。源码如下
/* * Copyright 2013-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * 1: 继承 AbstractRoutePredicateFactory 类 * 2: 重写 apply 方法 定义我们的转发规则 */ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; import java.util.Collections; import java.util.List; import java.util.function.Predicate; import org.springframework.web.server.ServerWebExchange; /** * @author Spencer Gibb */ public class BeforeRoutePredicateFactory extends AbstractRoutePredicateFactory<BeforeRoutePredicateFactory.Config> { /** * DateTime key. */ public static final String DATETIME_KEY = "datetime"; public BeforeRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Collections.singletonList(DATETIME_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { final ZonedDateTime now = ZonedDateTime.now(); return now.isBefore(config.getDatetime()); } @Override public String toString() { return String.format("Before: %s", config.getDatetime()); } }; } public static class Config { private ZonedDateTime datetime; public ZonedDateTime getDatetime() { return datetime; } public void setDatetime(ZonedDateTime datetime) { this.datetime = datetime; } } }
则我们可以同相同的方式 自定义我们自己的转发规则。
需求: 自定义我们的规格 配置传入参数必须要有orderId 并且orderId的值配置为10 否则禁止转发 代码如下
package com.leave.cloud.forward; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; /** * @Description * @Author 自定义断言工厂 * @Version V1.0.0 * @Date 2021/6/16 0016 */ @Component public class ParameterRoutePredicateFactory extends AbstractRoutePredicateFactory<ParameterRoutePredicateFactory.Config> { //与内部类属性名保持一致 private final static String parameter = "orderId"; public ParameterRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { //赋值 为 内部类 Config 中的 orderId属性赋值 return Arrays.asList(parameter); } @Override public Predicate<ServerWebExchange> apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { //获取请求参数体 final String firstOrderId =serverWebExchange.getRequest().getQueryParams().getFirst(parameter); Assert.notNull(firstOrderId); return config.getOrderId().equals(firstOrderId); } @Override public String toString() { return String.format("Parameter: %s", config.getOrderId()); } }; } public static class Config { private String orderId; public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } } }
yml的配置如下
gateway:
routes: #数组形式
- id: xdclass-order-service #路由唯一标识
uri: lb://order-service #想要转发到的地址
order: 1 #优先级,数字越小优先级越高
predicates: #断言 配置参数
- Parameter=10
请求测试截图如下
我们把参数换成9
可以看到404 访问路径不存在 没有进行转发
是一种过滤器,能过滤掉一些不满足要求的request请求。如下图
PRE: 这种过滤器在请求被路由之前调用,一般用于鉴权、限流等
POST:这种过滤器在路由到微服务以后执行,一般用于修改响应结果,比如增加header信息、打点结果日志
局部过滤器GatewayFilter:应用在某个路由上,每个过滤器工厂都对应一个实现类,并且这些类的名称必须以 GatewayFilterFactory 结尾
全局过滤器:作用全部路由上
需求1: 自定义局部过滤器, 要求订单服务的请求头中必须含有token , 代码如下
package com.leave.cloud.filters; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @Description * @Author 局部过滤器 * @Version V1.0.0 * @Date 2021/6/16 0016 */ @Component public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config> { /** * Token_KEY */ public static final String Token_KEY = "token"; public static final String enable = "true"; public TokenGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(Token_KEY); } @Override public GatewayFilter apply(Config config) { return new GatewayFilter() { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //是否开启token验证 if(config.getToken().equals(enable)){ String token = exchange.getRequest().getHeaders().getFirst(Token_KEY); if (StringUtils.isEmpty(token)) { return exchange.getResponse().setComplete(); } } //生产环境需要验证token的有效性 return chain.filter(exchange); } @Override public String toString() { return filterToStringCreator(TokenGatewayFilterFactory.this) .append("token", config.getToken()).toString(); } }; } public static class Config { private String token; public String getToken() { return token; } public void setToken(String token) { this.token = token; } } }
yml配置
gateway:
routes: #数组形式
- id: xdclass-order-service #路由唯一标识
uri: lb://xdclass-order-service #想要转发到的地址
order: 1 #优先级,数字越小优先级越高
predicates: #断言 配置哪个路径才转发
- Path=/order/**
- Parameter=10
filters: #过滤器,请求在传递过程中通过过滤器修改
- StripPrefix=1 #去掉第一层前缀
- Token=true #是否开启token验证
测试调用
不带token
带token
需求2: 自定义全局过滤器, 要求必须携带token,并且token的值为userAuth , 代码如下
package com.leave.cloud.filters; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.Objects; /** * @Description * @Author 全局过滤器 * @Version V1.0.0 * @Date 2021/6/16 0016 */ @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private final static String User_Auth = "userAuth"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getHeaders().getFirst("token"); if (Objects.isNull(token)) { return notCheckReturn(exchange); } else { if (token.equals(User_Auth)) { return chain.filter(exchange); } return notCheckReturn(exchange); } } private Mono<Void> notCheckReturn(ServerWebExchange exchange) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } /** * 执行等级 * @return */ @Override public int getOrder() { return 0; } }
测试调用
token值不为userAuth 时
为userAuth时
gateway最大的能力是在于转发,一些过滤最好下沉到各个服务。否则会影响性能
人有逆天之时,天无绝人之路
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。