SpringCloudGateway--谓词(断言)
创始人
2024-04-13 04:19:54
0

目录

一、定义

二、谓词使用

1、After

2、Before

3、Between

4、Cookie

5、Header

6、Host

7、Method

8、Path

9、Query 

10、RemoteAddr

11、Weight


一、定义

        SpringCloudGateway中三个重要词汇:

        路由(Route):配置网关中的一个完整路由,包括命名,地址,谓词集合(规则),过滤器集合。

        谓词、断言(Predicate):这是一个 Java 8 函数谓词。输入类型是一个 Spring 框架的 ServerWebExchange。这允许开发人员匹配来自 HTTP 请求的任何内容,例如头部或参数。简单说就是看发送的请求url中是否符合谓词中的规则,符合就通过,不符合就进行拦截。

        过滤器(Filter):这些是 Spring 框架网关过滤器在特定工厂中构建的实例。这里,可以在发送下游请求之前或之后修改请求和响应。简单说就是负责在代理服务之前或是之后做的一些事情。

二、谓词使用

        Gateway中有很多已经实现好的谓词,可以查看GatewayPredicate下的实现类:

        接下来单独用这11个实现类举例,Gateway项目可以参考:SpringCloudGateway--自动路由映射与手动路由映射_雨欲语的博客-CSDN博客

1、After

        在指定时间之后,顾名思义就是只有在指定时间之后的请求才会生效:

routes: - id: service-one uri: lb://service-onepredicates: - After=2022-11-26T00:00:00.000+08:00[Asia/Shanghai]filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms

        进入AfterRoutePredicateFactory实现里面,可以看到是由工厂方法加匿名内部类实现:

        在SpringCloudGateway中可以找到加载这些实现类的工厂方法:

        其余的实现类也是同理 

2、Before

        指定时间之前,只有在指定时间之前的请求才会生效:

routes: - id: service-one uri: lb://service-onepredicates: - Before=2022-11-26T00:00:00.000+08:00[Asia/Shanghai]filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms

      

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 {/*** DateTime key.*/public static final String DATETIME_KEY = "datetime";public BeforeRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Collections.singletonList(DATETIME_KEY);}@Overridepublic Predicate apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {final ZonedDateTime now = ZonedDateTime.now();return now.isBefore(config.getDatetime());}@Overridepublic 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;}}}

 

3、Between

        需要在设定的时间范围之内才能进行请求转发:

routes: - id: service-one uri: lb://service-onepredicates: - Between=2022-11-26T00:00:00.000+08:00[Asia/Shanghai],2022-11-30T00:00:00.000+08:00[Asia/Shanghai]filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms

        源码:

package org.springframework.cloud.gateway.handler.predicate;import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;import javax.validation.constraints.NotNull;import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;/*** @author Spencer Gibb*/
public class BetweenRoutePredicateFactory extends AbstractRoutePredicateFactory {/*** DateTime 1 key.*/public static final String DATETIME1_KEY = "datetime1";/*** DateTime 2 key.*/public static final String DATETIME2_KEY = "datetime2";public BetweenRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(DATETIME1_KEY, DATETIME2_KEY);}@Overridepublic Predicate apply(Config config) {Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()),config.getDatetime1() + " must be before " + config.getDatetime2());return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {final ZonedDateTime now = ZonedDateTime.now();return now.isAfter(config.getDatetime1()) && now.isBefore(config.getDatetime2());}@Overridepublic String toString() {return String.format("Between: %s and %s", config.getDatetime1(), config.getDatetime2());}};}@Validatedpublic static class Config {@NotNullprivate ZonedDateTime datetime1;@NotNullprivate ZonedDateTime datetime2;public ZonedDateTime getDatetime1() {return datetime1;}public Config setDatetime1(ZonedDateTime datetime1) {this.datetime1 = datetime1;return this;}public ZonedDateTime getDatetime2() {return datetime2;}public Config setDatetime2(ZonedDateTime datetime2) {this.datetime2 = datetime2;return this;}}}

4、Cookie

        要求请求中包含指定Cookie名和满足特定正则要求的值,Cookie必须有两个值,第一个Cookie包含的参数名,第二个表示参数对应的值,正则表达式:

routes: - id: service-one uri: lb://service-onepredicates: - Cookie=username,admin*filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;import javax.validation.constraints.NotEmpty;import org.springframework.http.HttpCookie;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;/*** @author Spencer Gibb*/
public class CookieRoutePredicateFactory extends AbstractRoutePredicateFactory {/*** Name key.*/public static final String NAME_KEY = "name";/*** Regexp key.*/public static final String REGEXP_KEY = "regexp";public CookieRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(NAME_KEY, REGEXP_KEY);}@Overridepublic Predicate apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {List cookies = exchange.getRequest().getCookies().get(config.name);if (cookies == null) {return false;}for (HttpCookie cookie : cookies) {if (cookie.getValue().matches(config.regexp)) {return true;}}return false;}@Overridepublic String toString() {return String.format("Cookie: name=%s regexp=%s", config.name, config.regexp);}};}@Validatedpublic static class Config {@NotEmptyprivate String name;@NotEmptyprivate String regexp;public String getName() {return name;}public Config setName(String name) {this.name = name;return this;}public String getRegexp() {return regexp;}public Config setRegexp(String regexp) {this.regexp = regexp;return this;}}}

5、Header

        表示请求头中必须包含的内容。

        注意:参数名和参数值之间依然使用逗号,参数值要使用正则表达式

        如果Header只有一个值表示请求头中必须包含的参数。如果有两个值,第一个表示请求头必须包含的参数名,第二个表示请求头参数对应值。

routes: - id: service-one uri: lb://service-onepredicates: - Header=Connection,keep-alive- Header=Cache-Control,max-age=0filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;import javax.validation.constraints.NotEmpty;import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;/*** @author Spencer Gibb*/
public class HeaderRoutePredicateFactory extends AbstractRoutePredicateFactory {/*** Header key.*/public static final String HEADER_KEY = "header";/*** Regexp key.*/public static final String REGEXP_KEY = "regexp";public HeaderRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(HEADER_KEY, REGEXP_KEY);}@Overridepublic Predicate apply(Config config) {boolean hasRegex = !ObjectUtils.isEmpty(config.regexp);return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {List values = exchange.getRequest().getHeaders().getOrDefault(config.header,Collections.emptyList());if (values.isEmpty()) {return false;}// values is now guaranteed to not be emptyif (hasRegex) {// check if a header value matchesfor (int i = 0; i < values.size(); i++) {String value = values.get(i);if (value.matches(config.regexp)) {return true;}}return false;}// there is a value and since regexp is empty, we only check existence.return true;}@Overridepublic String toString() {return String.format("Header: %s regexp=%s", config.header, config.regexp);}};}@Validatedpublic static class Config {@NotEmptyprivate String header;private String regexp;public String getHeader() {return header;}public Config setHeader(String header) {this.header = header;return this;}public String getRegexp() {return regexp;}public Config setRegexp(String regexp) {this.regexp = regexp;return this;}}}

6、Host

        匹配请求参数中Host参数的值,可以有多个,使用逗号隔开,**表示支持模糊匹配:

routes: - id: service-one uri: lb://service-onepredicates: - Host=127.0.0.1:8080,**.test.comfilters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;/*** @author Spencer Gibb*/
public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory {private PathMatcher pathMatcher = new AntPathMatcher(".");public HostRoutePredicateFactory() {super(Config.class);}public void setPathMatcher(PathMatcher pathMatcher) {this.pathMatcher = pathMatcher;}@Overridepublic List shortcutFieldOrder() {return Collections.singletonList("patterns");}@Overridepublic ShortcutType shortcutType() {return ShortcutType.GATHER_LIST;}@Overridepublic Predicate apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {String host = exchange.getRequest().getHeaders().getFirst("Host");String match = null;for (int i = 0; i < config.getPatterns().size(); i++) {String pattern = config.getPatterns().get(i);if (pathMatcher.match(pattern, host)) {match = pattern;break;}}if (match != null) {Map variables = pathMatcher.extractUriTemplateVariables(match, host);ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);return true;}return false;}@Overridepublic String toString() {return String.format("Hosts: %s", config.getPatterns());}};}@Validatedpublic static class Config {private List patterns = new ArrayList<>();public List getPatterns() {return patterns;}public Config setPatterns(List patterns) {this.patterns = patterns;return this;}@Overridepublic String toString() {return new ToStringCreator(this).append("patterns", patterns).toString();}}}

7、Method

        Method表示请求方式。支持多个值,使用逗号分隔,多个值之间为or条件

routes: - id: service-one uri: lb://service-onepredicates: - Method=GET,POST # 表示只允许GET or POST请求通过filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;import org.springframework.http.HttpMethod;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import static java.util.Arrays.stream;/*** @author Spencer Gibb* @author Dennis Menge*/
public class MethodRoutePredicateFactory extends AbstractRoutePredicateFactory {/*** Methods key.*/public static final String METHODS_KEY = "methods";public MethodRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(METHODS_KEY);}@Overridepublic ShortcutType shortcutType() {return ShortcutType.GATHER_LIST;}@Overridepublic Predicate apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {HttpMethod requestMethod = exchange.getRequest().getMethod();return stream(config.getMethods()).anyMatch(httpMethod -> httpMethod == requestMethod);}@Overridepublic String toString() {return String.format("Methods: %s", Arrays.toString(config.getMethods()));}};}@Validatedpublic static class Config {private HttpMethod[] methods;public HttpMethod[] getMethods() {return methods;}public void setMethods(HttpMethod... methods) {this.methods = methods;}}}

8、Path

        请求url包含的路径,这种是使用得最多的一种,路径可以配置多个,用逗号隔开。

routes: - id: service-one uri: lb://service-onepredicates: - Path=/service/**,/server/**filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import org.springframework.core.style.ToStringCreator;
import org.springframework.http.server.PathContainer;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPattern.PathMatchInfo;
import org.springframework.web.util.pattern.PathPatternParser;import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.putUriTemplateVariables;
import static org.springframework.http.server.PathContainer.parsePath;/*** @author Spencer Gibb* @author Dhawal Kapil*/
public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory {private static final Log log = LogFactory.getLog(PathRoutePredicateFactory.class);private static final String MATCH_TRAILING_SLASH = "matchTrailingSlash";private PathPatternParser pathPatternParser = new PathPatternParser();public PathRoutePredicateFactory() {super(Config.class);}private static void traceMatch(String prefix, Object desired, Object actual, boolean match) {if (log.isTraceEnabled()) {String message = String.format("%s \"%s\" %s against value \"%s\"", prefix, desired,match ? "matches" : "does not match", actual);log.trace(message);}}public void setPathPatternParser(PathPatternParser pathPatternParser) {this.pathPatternParser = pathPatternParser;}@Overridepublic List shortcutFieldOrder() {return Arrays.asList("patterns", MATCH_TRAILING_SLASH);}@Overridepublic ShortcutType shortcutType() {return ShortcutType.GATHER_LIST_TAIL_FLAG;}@Overridepublic Predicate apply(Config config) {final ArrayList pathPatterns = new ArrayList<>();synchronized (this.pathPatternParser) {pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchTrailingSlash());config.getPatterns().forEach(pattern -> {PathPattern pathPattern = this.pathPatternParser.parse(pattern);pathPatterns.add(pathPattern);});}return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {PathContainer path = parsePath(exchange.getRequest().getURI().getRawPath());PathPattern match = null;for (int i = 0; i < pathPatterns.size(); i++) {PathPattern pathPattern = pathPatterns.get(i);if (pathPattern.matches(path)) {match = pathPattern;break;}}if (match != null) {traceMatch("Pattern", match.getPatternString(), path, true);PathMatchInfo pathMatchInfo = match.matchAndExtract(path);putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());return true;}else {traceMatch("Pattern", config.getPatterns(), path, false);return false;}}@Overridepublic String toString() {return String.format("Paths: %s, match trailing slash: %b", config.getPatterns(),config.isMatchTrailingSlash());}};}@Validatedpublic static class Config {private List patterns = new ArrayList<>();private boolean matchTrailingSlash = true;public List getPatterns() {return patterns;}public Config setPatterns(List patterns) {this.patterns = patterns;return this;}/*** @deprecated use {@link #isMatchTrailingSlash()}*/@Deprecatedpublic boolean isMatchOptionalTrailingSeparator() {return isMatchTrailingSlash();}/*** @deprecated use {@link #setMatchTrailingSlash(boolean)}*/@Deprecatedpublic Config setMatchOptionalTrailingSeparator(boolean matchOptionalTrailingSeparator) {setMatchTrailingSlash(matchOptionalTrailingSeparator);return this;}public boolean isMatchTrailingSlash() {return matchTrailingSlash;}public Config setMatchTrailingSlash(boolean matchTrailingSlash) {this.matchTrailingSlash = matchTrailingSlash;return this;}@Overridepublic String toString() {return new ToStringCreator(this).append("patterns", patterns).append(MATCH_TRAILING_SLASH, matchTrailingSlash).toString();}}}

9、Query 

        Query指请求参数,有两种,一种是必须包含参数名:

routes: - id: service-one uri: lb://service-onepredicates: - Query=usernamefilters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms

        另外一种是设置参数的值,用正则匹配:

routes: - id: service-one uri: lb://service-onepredicates: - Query=username,admin*filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;import javax.validation.constraints.NotEmpty;import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;/*** @author Spencer Gibb*/
public class QueryRoutePredicateFactory extends AbstractRoutePredicateFactory {/*** Param key.*/public static final String PARAM_KEY = "param";/*** Regexp key.*/public static final String REGEXP_KEY = "regexp";public QueryRoutePredicateFactory() {super(Config.class);}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(PARAM_KEY, REGEXP_KEY);}@Overridepublic Predicate apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {if (!StringUtils.hasText(config.regexp)) {// check existence of headerreturn exchange.getRequest().getQueryParams().containsKey(config.param);}List values = exchange.getRequest().getQueryParams().get(config.param);if (values == null) {return false;}for (String value : values) {if (value != null && value.matches(config.regexp)) {return true;}}return false;}@Overridepublic String toString() {return String.format("Query: param=%s regexp=%s", config.getParam(), config.getRegexp());}};}@Validatedpublic static class Config {@NotEmptyprivate String param;private String regexp;public String getParam() {return param;}public Config setParam(String param) {this.param = param;return this;}public String getRegexp() {return regexp;}public Config setRegexp(String regexp) {this.regexp = regexp;return this;}}}

10、RemoteAddr

        允许访问的客户端地址,不能使用类似localhost这种:

routes: - id: service-one uri: lb://service-onepredicates: - RemoteAddr=127.0.0.1filters:- StripPrefix=1metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #ms
package org.springframework.cloud.gateway.handler.predicate;import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import org.springframework.cloud.gateway.support.ipresolver.RemoteAddressResolver;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import static org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST;/*** @author Spencer Gibb*/
public class RemoteAddrRoutePredicateFactoryextends AbstractRoutePredicateFactory {private static final Log log = LogFactory.getLog(RemoteAddrRoutePredicateFactory.class);public RemoteAddrRoutePredicateFactory() {super(Config.class);}@Overridepublic ShortcutType shortcutType() {return GATHER_LIST;}@Overridepublic List shortcutFieldOrder() {return Collections.singletonList("sources");}@NotNullprivate List convert(List values) {List sources = new ArrayList<>();for (String arg : values) {addSource(sources, arg);}return sources;}@Overridepublic Predicate apply(Config config) {List sources = convert(config.sources);return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange);if (remoteAddress != null && remoteAddress.getAddress() != null) {String hostAddress = remoteAddress.getAddress().getHostAddress();String host = exchange.getRequest().getURI().getHost();if (log.isDebugEnabled() && !hostAddress.equals(host)) {log.debug("Remote addresses didn't match " + hostAddress + " != " + host);}for (IpSubnetFilterRule source : sources) {if (source.matches(remoteAddress)) {return true;}}}return false;}@Overridepublic String toString() {return String.format("RemoteAddrs: %s", config.getSources());}};}private void addSource(List sources, String source) {if (!source.contains("/")) { // no netmask, add defaultsource = source + "/32";}String[] ipAddressCidrPrefix = source.split("/", 2);String ipAddress = ipAddressCidrPrefix[0];int cidrPrefix = Integer.parseInt(ipAddressCidrPrefix[1]);sources.add(new IpSubnetFilterRule(ipAddress, cidrPrefix, IpFilterRuleType.ACCEPT));}@Validatedpublic static class Config {@NotEmptyprivate List sources = new ArrayList<>();@NotNullprivate RemoteAddressResolver remoteAddressResolver = new RemoteAddressResolver() {};public List getSources() {return sources;}public Config setSources(List sources) {this.sources = sources;return this;}public Config setSources(String... sources) {this.sources = Arrays.asList(sources);return this;}public Config setRemoteAddressResolver(RemoteAddressResolver remoteAddressResolver) {this.remoteAddressResolver = remoteAddressResolver;return this;}}}

11、Weight

        负载均衡中权重:

routes:- id: service-oneuri: lb://service-onepredicates:- Weight=group,2filters: StripPrefix=1- id: service-twouri: lb://service-twopredicates:- Weight=group,8filters: StripPrefix=1
package org.springframework.cloud.gateway.handler.predicate;import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import org.springframework.cloud.gateway.event.WeightDefinedEvent;
import org.springframework.cloud.gateway.support.WeightConfig;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.web.server.ServerWebExchange;import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.WEIGHT_ATTR;/*** @author Spencer Gibb*/
// TODO: make this a generic Choose out of group predicate?
public class WeightRoutePredicateFactory extends AbstractRoutePredicateFactoryimplements ApplicationEventPublisherAware {/*** Weight config group key.*/public static final String GROUP_KEY = WeightConfig.CONFIG_PREFIX + ".group";/*** Weight config weight key.*/public static final String WEIGHT_KEY = WeightConfig.CONFIG_PREFIX + ".weight";private static final Log log = LogFactory.getLog(WeightRoutePredicateFactory.class);private ApplicationEventPublisher publisher;public WeightRoutePredicateFactory() {super(WeightConfig.class);}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher;}@Overridepublic List shortcutFieldOrder() {return Arrays.asList(GROUP_KEY, WEIGHT_KEY);}@Overridepublic String shortcutFieldPrefix() {return WeightConfig.CONFIG_PREFIX;}@Overridepublic void beforeApply(WeightConfig config) {if (publisher != null) {publisher.publishEvent(new WeightDefinedEvent(this, config));}}@Overridepublic Predicate apply(WeightConfig config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {Map weights = exchange.getAttributeOrDefault(WEIGHT_ATTR, Collections.emptyMap());String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);// all calculations and comparison against random num happened in// WeightCalculatorWebFilterString group = config.getGroup();if (weights.containsKey(group)) {String chosenRoute = weights.get(group);if (log.isTraceEnabled()) {log.trace("in group weight: " + group + ", current route: " + routeId + ", chosen route: "+ chosenRoute);}return routeId.equals(chosenRoute);}else if (log.isTraceEnabled()) {log.trace("no weights found for group: " + group + ", current route: " + routeId);}return false;}@Overridepublic String toString() {return String.format("Weight: %s %s", config.getGroup(), config.getWeight());}};}}

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...