• SpringCloudGateway--谓词(断言)


    目录

    一、定义

    二、谓词使用

    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

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - After=2022-11-26T00:00:00.000+08:00[Asia/Shanghai]
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms

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

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

            其余的实现类也是同理 

    2、Before

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Before=2022-11-26T00:00:00.000+08:00[Asia/Shanghai]
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms

          

    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.time.ZonedDateTime;
    3. import java.util.Collections;
    4. import java.util.List;
    5. import java.util.function.Predicate;
    6. import org.springframework.web.server.ServerWebExchange;
    7. /**
    8. * @author Spencer Gibb
    9. */
    10. public class BeforeRoutePredicateFactory extends AbstractRoutePredicateFactory {
    11. /**
    12. * DateTime key.
    13. */
    14. public static final String DATETIME_KEY = "datetime";
    15. public BeforeRoutePredicateFactory() {
    16. super(Config.class);
    17. }
    18. @Override
    19. public List shortcutFieldOrder() {
    20. return Collections.singletonList(DATETIME_KEY);
    21. }
    22. @Override
    23. public Predicate apply(Config config) {
    24. return new GatewayPredicate() {
    25. @Override
    26. public boolean test(ServerWebExchange serverWebExchange) {
    27. final ZonedDateTime now = ZonedDateTime.now();
    28. return now.isBefore(config.getDatetime());
    29. }
    30. @Override
    31. public String toString() {
    32. return String.format("Before: %s", config.getDatetime());
    33. }
    34. };
    35. }
    36. public static class Config {
    37. private ZonedDateTime datetime;
    38. public ZonedDateTime getDatetime() {
    39. return datetime;
    40. }
    41. public void setDatetime(ZonedDateTime datetime) {
    42. this.datetime = datetime;
    43. }
    44. }
    45. }

    3、Between

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Between=2022-11-26T00:00:00.000+08:00[Asia/Shanghai],2022-11-30T00:00:00.000+08:00[Asia/Shanghai]
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms

            源码:

    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.time.ZonedDateTime;
    3. import java.util.Arrays;
    4. import java.util.List;
    5. import java.util.function.Predicate;
    6. import javax.validation.constraints.NotNull;
    7. import org.springframework.util.Assert;
    8. import org.springframework.validation.annotation.Validated;
    9. import org.springframework.web.server.ServerWebExchange;
    10. /**
    11. * @author Spencer Gibb
    12. */
    13. public class BetweenRoutePredicateFactory extends AbstractRoutePredicateFactory {
    14. /**
    15. * DateTime 1 key.
    16. */
    17. public static final String DATETIME1_KEY = "datetime1";
    18. /**
    19. * DateTime 2 key.
    20. */
    21. public static final String DATETIME2_KEY = "datetime2";
    22. public BetweenRoutePredicateFactory() {
    23. super(Config.class);
    24. }
    25. @Override
    26. public List shortcutFieldOrder() {
    27. return Arrays.asList(DATETIME1_KEY, DATETIME2_KEY);
    28. }
    29. @Override
    30. public Predicate apply(Config config) {
    31. Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()),
    32. config.getDatetime1() + " must be before " + config.getDatetime2());
    33. return new GatewayPredicate() {
    34. @Override
    35. public boolean test(ServerWebExchange serverWebExchange) {
    36. final ZonedDateTime now = ZonedDateTime.now();
    37. return now.isAfter(config.getDatetime1()) && now.isBefore(config.getDatetime2());
    38. }
    39. @Override
    40. public String toString() {
    41. return String.format("Between: %s and %s", config.getDatetime1(), config.getDatetime2());
    42. }
    43. };
    44. }
    45. @Validated
    46. public static class Config {
    47. @NotNull
    48. private ZonedDateTime datetime1;
    49. @NotNull
    50. private ZonedDateTime datetime2;
    51. public ZonedDateTime getDatetime1() {
    52. return datetime1;
    53. }
    54. public Config setDatetime1(ZonedDateTime datetime1) {
    55. this.datetime1 = datetime1;
    56. return this;
    57. }
    58. public ZonedDateTime getDatetime2() {
    59. return datetime2;
    60. }
    61. public Config setDatetime2(ZonedDateTime datetime2) {
    62. this.datetime2 = datetime2;
    63. return this;
    64. }
    65. }
    66. }

    4、Cookie

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Cookie=username,admin*
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.Arrays;
    3. import java.util.List;
    4. import java.util.function.Predicate;
    5. import javax.validation.constraints.NotEmpty;
    6. import org.springframework.http.HttpCookie;
    7. import org.springframework.validation.annotation.Validated;
    8. import org.springframework.web.server.ServerWebExchange;
    9. /**
    10. * @author Spencer Gibb
    11. */
    12. public class CookieRoutePredicateFactory extends AbstractRoutePredicateFactory {
    13. /**
    14. * Name key.
    15. */
    16. public static final String NAME_KEY = "name";
    17. /**
    18. * Regexp key.
    19. */
    20. public static final String REGEXP_KEY = "regexp";
    21. public CookieRoutePredicateFactory() {
    22. super(Config.class);
    23. }
    24. @Override
    25. public List shortcutFieldOrder() {
    26. return Arrays.asList(NAME_KEY, REGEXP_KEY);
    27. }
    28. @Override
    29. public Predicate apply(Config config) {
    30. return new GatewayPredicate() {
    31. @Override
    32. public boolean test(ServerWebExchange exchange) {
    33. List cookies = exchange.getRequest().getCookies().get(config.name);
    34. if (cookies == null) {
    35. return false;
    36. }
    37. for (HttpCookie cookie : cookies) {
    38. if (cookie.getValue().matches(config.regexp)) {
    39. return true;
    40. }
    41. }
    42. return false;
    43. }
    44. @Override
    45. public String toString() {
    46. return String.format("Cookie: name=%s regexp=%s", config.name, config.regexp);
    47. }
    48. };
    49. }
    50. @Validated
    51. public static class Config {
    52. @NotEmpty
    53. private String name;
    54. @NotEmpty
    55. private String regexp;
    56. public String getName() {
    57. return name;
    58. }
    59. public Config setName(String name) {
    60. this.name = name;
    61. return this;
    62. }
    63. public String getRegexp() {
    64. return regexp;
    65. }
    66. public Config setRegexp(String regexp) {
    67. this.regexp = regexp;
    68. return this;
    69. }
    70. }
    71. }

    5、Header

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

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

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Header=Connection,keep-alive
    6. - Header=Cache-Control,max-age=0
    7. filters:
    8. - StripPrefix=1
    9. metadata:
    10. connect-timeout: 15000 #ms
    11. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.Arrays;
    3. import java.util.Collections;
    4. import java.util.List;
    5. import java.util.function.Predicate;
    6. import javax.validation.constraints.NotEmpty;
    7. import org.springframework.util.ObjectUtils;
    8. import org.springframework.validation.annotation.Validated;
    9. import org.springframework.web.server.ServerWebExchange;
    10. /**
    11. * @author Spencer Gibb
    12. */
    13. public class HeaderRoutePredicateFactory extends AbstractRoutePredicateFactory {
    14. /**
    15. * Header key.
    16. */
    17. public static final String HEADER_KEY = "header";
    18. /**
    19. * Regexp key.
    20. */
    21. public static final String REGEXP_KEY = "regexp";
    22. public HeaderRoutePredicateFactory() {
    23. super(Config.class);
    24. }
    25. @Override
    26. public List shortcutFieldOrder() {
    27. return Arrays.asList(HEADER_KEY, REGEXP_KEY);
    28. }
    29. @Override
    30. public Predicate apply(Config config) {
    31. boolean hasRegex = !ObjectUtils.isEmpty(config.regexp);
    32. return new GatewayPredicate() {
    33. @Override
    34. public boolean test(ServerWebExchange exchange) {
    35. List values = exchange.getRequest().getHeaders().getOrDefault(config.header,
    36. Collections.emptyList());
    37. if (values.isEmpty()) {
    38. return false;
    39. }
    40. // values is now guaranteed to not be empty
    41. if (hasRegex) {
    42. // check if a header value matches
    43. for (int i = 0; i < values.size(); i++) {
    44. String value = values.get(i);
    45. if (value.matches(config.regexp)) {
    46. return true;
    47. }
    48. }
    49. return false;
    50. }
    51. // there is a value and since regexp is empty, we only check existence.
    52. return true;
    53. }
    54. @Override
    55. public String toString() {
    56. return String.format("Header: %s regexp=%s", config.header, config.regexp);
    57. }
    58. };
    59. }
    60. @Validated
    61. public static class Config {
    62. @NotEmpty
    63. private String header;
    64. private String regexp;
    65. public String getHeader() {
    66. return header;
    67. }
    68. public Config setHeader(String header) {
    69. this.header = header;
    70. return this;
    71. }
    72. public String getRegexp() {
    73. return regexp;
    74. }
    75. public Config setRegexp(String regexp) {
    76. this.regexp = regexp;
    77. return this;
    78. }
    79. }
    80. }

    6、Host

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Host=127.0.0.1:8080,**.test.com
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.ArrayList;
    3. import java.util.Collections;
    4. import java.util.List;
    5. import java.util.Map;
    6. import java.util.function.Predicate;
    7. import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
    8. import org.springframework.core.style.ToStringCreator;
    9. import org.springframework.util.AntPathMatcher;
    10. import org.springframework.util.PathMatcher;
    11. import org.springframework.validation.annotation.Validated;
    12. import org.springframework.web.server.ServerWebExchange;
    13. /**
    14. * @author Spencer Gibb
    15. */
    16. public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory {
    17. private PathMatcher pathMatcher = new AntPathMatcher(".");
    18. public HostRoutePredicateFactory() {
    19. super(Config.class);
    20. }
    21. public void setPathMatcher(PathMatcher pathMatcher) {
    22. this.pathMatcher = pathMatcher;
    23. }
    24. @Override
    25. public List shortcutFieldOrder() {
    26. return Collections.singletonList("patterns");
    27. }
    28. @Override
    29. public ShortcutType shortcutType() {
    30. return ShortcutType.GATHER_LIST;
    31. }
    32. @Override
    33. public Predicate apply(Config config) {
    34. return new GatewayPredicate() {
    35. @Override
    36. public boolean test(ServerWebExchange exchange) {
    37. String host = exchange.getRequest().getHeaders().getFirst("Host");
    38. String match = null;
    39. for (int i = 0; i < config.getPatterns().size(); i++) {
    40. String pattern = config.getPatterns().get(i);
    41. if (pathMatcher.match(pattern, host)) {
    42. match = pattern;
    43. break;
    44. }
    45. }
    46. if (match != null) {
    47. Map variables = pathMatcher.extractUriTemplateVariables(match, host);
    48. ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
    49. return true;
    50. }
    51. return false;
    52. }
    53. @Override
    54. public String toString() {
    55. return String.format("Hosts: %s", config.getPatterns());
    56. }
    57. };
    58. }
    59. @Validated
    60. public static class Config {
    61. private List patterns = new ArrayList<>();
    62. public List getPatterns() {
    63. return patterns;
    64. }
    65. public Config setPatterns(List patterns) {
    66. this.patterns = patterns;
    67. return this;
    68. }
    69. @Override
    70. public String toString() {
    71. return new ToStringCreator(this).append("patterns", patterns).toString();
    72. }
    73. }
    74. }

    7、Method

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Method=GET,POST # 表示只允许GET or POST请求通过
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.Arrays;
    3. import java.util.List;
    4. import java.util.function.Predicate;
    5. import org.springframework.http.HttpMethod;
    6. import org.springframework.validation.annotation.Validated;
    7. import org.springframework.web.server.ServerWebExchange;
    8. import static java.util.Arrays.stream;
    9. /**
    10. * @author Spencer Gibb
    11. * @author Dennis Menge
    12. */
    13. public class MethodRoutePredicateFactory extends AbstractRoutePredicateFactory {
    14. /**
    15. * Methods key.
    16. */
    17. public static final String METHODS_KEY = "methods";
    18. public MethodRoutePredicateFactory() {
    19. super(Config.class);
    20. }
    21. @Override
    22. public List shortcutFieldOrder() {
    23. return Arrays.asList(METHODS_KEY);
    24. }
    25. @Override
    26. public ShortcutType shortcutType() {
    27. return ShortcutType.GATHER_LIST;
    28. }
    29. @Override
    30. public Predicate apply(Config config) {
    31. return new GatewayPredicate() {
    32. @Override
    33. public boolean test(ServerWebExchange exchange) {
    34. HttpMethod requestMethod = exchange.getRequest().getMethod();
    35. return stream(config.getMethods()).anyMatch(httpMethod -> httpMethod == requestMethod);
    36. }
    37. @Override
    38. public String toString() {
    39. return String.format("Methods: %s", Arrays.toString(config.getMethods()));
    40. }
    41. };
    42. }
    43. @Validated
    44. public static class Config {
    45. private HttpMethod[] methods;
    46. public HttpMethod[] getMethods() {
    47. return methods;
    48. }
    49. public void setMethods(HttpMethod... methods) {
    50. this.methods = methods;
    51. }
    52. }
    53. }

    8、Path

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Path=/service/**,/server/**
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.ArrayList;
    3. import java.util.Arrays;
    4. import java.util.List;
    5. import java.util.function.Predicate;
    6. import org.apache.commons.logging.Log;
    7. import org.apache.commons.logging.LogFactory;
    8. import org.springframework.core.style.ToStringCreator;
    9. import org.springframework.http.server.PathContainer;
    10. import org.springframework.validation.annotation.Validated;
    11. import org.springframework.web.server.ServerWebExchange;
    12. import org.springframework.web.util.pattern.PathPattern;
    13. import org.springframework.web.util.pattern.PathPattern.PathMatchInfo;
    14. import org.springframework.web.util.pattern.PathPatternParser;
    15. import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.putUriTemplateVariables;
    16. import static org.springframework.http.server.PathContainer.parsePath;
    17. /**
    18. * @author Spencer Gibb
    19. * @author Dhawal Kapil
    20. */
    21. public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory {
    22. private static final Log log = LogFactory.getLog(PathRoutePredicateFactory.class);
    23. private static final String MATCH_TRAILING_SLASH = "matchTrailingSlash";
    24. private PathPatternParser pathPatternParser = new PathPatternParser();
    25. public PathRoutePredicateFactory() {
    26. super(Config.class);
    27. }
    28. private static void traceMatch(String prefix, Object desired, Object actual, boolean match) {
    29. if (log.isTraceEnabled()) {
    30. String message = String.format("%s \"%s\" %s against value \"%s\"", prefix, desired,
    31. match ? "matches" : "does not match", actual);
    32. log.trace(message);
    33. }
    34. }
    35. public void setPathPatternParser(PathPatternParser pathPatternParser) {
    36. this.pathPatternParser = pathPatternParser;
    37. }
    38. @Override
    39. public List shortcutFieldOrder() {
    40. return Arrays.asList("patterns", MATCH_TRAILING_SLASH);
    41. }
    42. @Override
    43. public ShortcutType shortcutType() {
    44. return ShortcutType.GATHER_LIST_TAIL_FLAG;
    45. }
    46. @Override
    47. public Predicate apply(Config config) {
    48. final ArrayList pathPatterns = new ArrayList<>();
    49. synchronized (this.pathPatternParser) {
    50. pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchTrailingSlash());
    51. config.getPatterns().forEach(pattern -> {
    52. PathPattern pathPattern = this.pathPatternParser.parse(pattern);
    53. pathPatterns.add(pathPattern);
    54. });
    55. }
    56. return new GatewayPredicate() {
    57. @Override
    58. public boolean test(ServerWebExchange exchange) {
    59. PathContainer path = parsePath(exchange.getRequest().getURI().getRawPath());
    60. PathPattern match = null;
    61. for (int i = 0; i < pathPatterns.size(); i++) {
    62. PathPattern pathPattern = pathPatterns.get(i);
    63. if (pathPattern.matches(path)) {
    64. match = pathPattern;
    65. break;
    66. }
    67. }
    68. if (match != null) {
    69. traceMatch("Pattern", match.getPatternString(), path, true);
    70. PathMatchInfo pathMatchInfo = match.matchAndExtract(path);
    71. putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
    72. return true;
    73. }
    74. else {
    75. traceMatch("Pattern", config.getPatterns(), path, false);
    76. return false;
    77. }
    78. }
    79. @Override
    80. public String toString() {
    81. return String.format("Paths: %s, match trailing slash: %b", config.getPatterns(),
    82. config.isMatchTrailingSlash());
    83. }
    84. };
    85. }
    86. @Validated
    87. public static class Config {
    88. private List patterns = new ArrayList<>();
    89. private boolean matchTrailingSlash = true;
    90. public List getPatterns() {
    91. return patterns;
    92. }
    93. public Config setPatterns(List patterns) {
    94. this.patterns = patterns;
    95. return this;
    96. }
    97. /**
    98. * @deprecated use {@link #isMatchTrailingSlash()}
    99. */
    100. @Deprecated
    101. public boolean isMatchOptionalTrailingSeparator() {
    102. return isMatchTrailingSlash();
    103. }
    104. /**
    105. * @deprecated use {@link #setMatchTrailingSlash(boolean)}
    106. */
    107. @Deprecated
    108. public Config setMatchOptionalTrailingSeparator(boolean matchOptionalTrailingSeparator) {
    109. setMatchTrailingSlash(matchOptionalTrailingSeparator);
    110. return this;
    111. }
    112. public boolean isMatchTrailingSlash() {
    113. return matchTrailingSlash;
    114. }
    115. public Config setMatchTrailingSlash(boolean matchTrailingSlash) {
    116. this.matchTrailingSlash = matchTrailingSlash;
    117. return this;
    118. }
    119. @Override
    120. public String toString() {
    121. return new ToStringCreator(this).append("patterns", patterns)
    122. .append(MATCH_TRAILING_SLASH, matchTrailingSlash).toString();
    123. }
    124. }
    125. }

    9、Query 

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Query=username
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Query=username,admin*
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.Arrays;
    3. import java.util.List;
    4. import java.util.function.Predicate;
    5. import javax.validation.constraints.NotEmpty;
    6. import org.springframework.util.StringUtils;
    7. import org.springframework.validation.annotation.Validated;
    8. import org.springframework.web.server.ServerWebExchange;
    9. /**
    10. * @author Spencer Gibb
    11. */
    12. public class QueryRoutePredicateFactory extends AbstractRoutePredicateFactory {
    13. /**
    14. * Param key.
    15. */
    16. public static final String PARAM_KEY = "param";
    17. /**
    18. * Regexp key.
    19. */
    20. public static final String REGEXP_KEY = "regexp";
    21. public QueryRoutePredicateFactory() {
    22. super(Config.class);
    23. }
    24. @Override
    25. public List shortcutFieldOrder() {
    26. return Arrays.asList(PARAM_KEY, REGEXP_KEY);
    27. }
    28. @Override
    29. public Predicate apply(Config config) {
    30. return new GatewayPredicate() {
    31. @Override
    32. public boolean test(ServerWebExchange exchange) {
    33. if (!StringUtils.hasText(config.regexp)) {
    34. // check existence of header
    35. return exchange.getRequest().getQueryParams().containsKey(config.param);
    36. }
    37. List values = exchange.getRequest().getQueryParams().get(config.param);
    38. if (values == null) {
    39. return false;
    40. }
    41. for (String value : values) {
    42. if (value != null && value.matches(config.regexp)) {
    43. return true;
    44. }
    45. }
    46. return false;
    47. }
    48. @Override
    49. public String toString() {
    50. return String.format("Query: param=%s regexp=%s", config.getParam(), config.getRegexp());
    51. }
    52. };
    53. }
    54. @Validated
    55. public static class Config {
    56. @NotEmpty
    57. private String param;
    58. private String regexp;
    59. public String getParam() {
    60. return param;
    61. }
    62. public Config setParam(String param) {
    63. this.param = param;
    64. return this;
    65. }
    66. public String getRegexp() {
    67. return regexp;
    68. }
    69. public Config setRegexp(String regexp) {
    70. this.regexp = regexp;
    71. return this;
    72. }
    73. }
    74. }

    10、RemoteAddr

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

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - RemoteAddr=127.0.0.1
    6. filters:
    7. - StripPrefix=1
    8. metadata:
    9. connect-timeout: 15000 #ms
    10. response-timeout: 15000 #ms
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.net.InetSocketAddress;
    3. import java.util.ArrayList;
    4. import java.util.Arrays;
    5. import java.util.Collections;
    6. import java.util.List;
    7. import java.util.function.Predicate;
    8. import javax.validation.constraints.NotEmpty;
    9. import javax.validation.constraints.NotNull;
    10. import io.netty.handler.ipfilter.IpFilterRuleType;
    11. import io.netty.handler.ipfilter.IpSubnetFilterRule;
    12. import org.apache.commons.logging.Log;
    13. import org.apache.commons.logging.LogFactory;
    14. import org.springframework.cloud.gateway.support.ipresolver.RemoteAddressResolver;
    15. import org.springframework.validation.annotation.Validated;
    16. import org.springframework.web.server.ServerWebExchange;
    17. import static org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST;
    18. /**
    19. * @author Spencer Gibb
    20. */
    21. public class RemoteAddrRoutePredicateFactory
    22. extends AbstractRoutePredicateFactory {
    23. private static final Log log = LogFactory.getLog(RemoteAddrRoutePredicateFactory.class);
    24. public RemoteAddrRoutePredicateFactory() {
    25. super(Config.class);
    26. }
    27. @Override
    28. public ShortcutType shortcutType() {
    29. return GATHER_LIST;
    30. }
    31. @Override
    32. public List shortcutFieldOrder() {
    33. return Collections.singletonList("sources");
    34. }
    35. @NotNull
    36. private List convert(List values) {
    37. List sources = new ArrayList<>();
    38. for (String arg : values) {
    39. addSource(sources, arg);
    40. }
    41. return sources;
    42. }
    43. @Override
    44. public Predicate apply(Config config) {
    45. List sources = convert(config.sources);
    46. return new GatewayPredicate() {
    47. @Override
    48. public boolean test(ServerWebExchange exchange) {
    49. InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange);
    50. if (remoteAddress != null && remoteAddress.getAddress() != null) {
    51. String hostAddress = remoteAddress.getAddress().getHostAddress();
    52. String host = exchange.getRequest().getURI().getHost();
    53. if (log.isDebugEnabled() && !hostAddress.equals(host)) {
    54. log.debug("Remote addresses didn't match " + hostAddress + " != " + host);
    55. }
    56. for (IpSubnetFilterRule source : sources) {
    57. if (source.matches(remoteAddress)) {
    58. return true;
    59. }
    60. }
    61. }
    62. return false;
    63. }
    64. @Override
    65. public String toString() {
    66. return String.format("RemoteAddrs: %s", config.getSources());
    67. }
    68. };
    69. }
    70. private void addSource(List sources, String source) {
    71. if (!source.contains("/")) { // no netmask, add default
    72. source = source + "/32";
    73. }
    74. String[] ipAddressCidrPrefix = source.split("/", 2);
    75. String ipAddress = ipAddressCidrPrefix[0];
    76. int cidrPrefix = Integer.parseInt(ipAddressCidrPrefix[1]);
    77. sources.add(new IpSubnetFilterRule(ipAddress, cidrPrefix, IpFilterRuleType.ACCEPT));
    78. }
    79. @Validated
    80. public static class Config {
    81. @NotEmpty
    82. private List sources = new ArrayList<>();
    83. @NotNull
    84. private RemoteAddressResolver remoteAddressResolver = new RemoteAddressResolver() {
    85. };
    86. public List getSources() {
    87. return sources;
    88. }
    89. public Config setSources(List sources) {
    90. this.sources = sources;
    91. return this;
    92. }
    93. public Config setSources(String... sources) {
    94. this.sources = Arrays.asList(sources);
    95. return this;
    96. }
    97. public Config setRemoteAddressResolver(RemoteAddressResolver remoteAddressResolver) {
    98. this.remoteAddressResolver = remoteAddressResolver;
    99. return this;
    100. }
    101. }
    102. }

    11、Weight

            负载均衡中权重:

    1. routes:
    2. - id: service-one
    3. uri: lb://service-one
    4. predicates:
    5. - Weight=group,2
    6. filters: StripPrefix=1
    7. - id: service-two
    8. uri: lb://service-two
    9. predicates:
    10. - Weight=group,8
    11. filters: StripPrefix=1
    1. package org.springframework.cloud.gateway.handler.predicate;
    2. import java.util.Arrays;
    3. import java.util.Collections;
    4. import java.util.List;
    5. import java.util.Map;
    6. import java.util.function.Predicate;
    7. import org.apache.commons.logging.Log;
    8. import org.apache.commons.logging.LogFactory;
    9. import org.springframework.cloud.gateway.event.WeightDefinedEvent;
    10. import org.springframework.cloud.gateway.support.WeightConfig;
    11. import org.springframework.context.ApplicationEventPublisher;
    12. import org.springframework.context.ApplicationEventPublisherAware;
    13. import org.springframework.web.server.ServerWebExchange;
    14. import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR;
    15. import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.WEIGHT_ATTR;
    16. /**
    17. * @author Spencer Gibb
    18. */
    19. // TODO: make this a generic Choose out of group predicate?
    20. public class WeightRoutePredicateFactory extends AbstractRoutePredicateFactory
    21. implements ApplicationEventPublisherAware {
    22. /**
    23. * Weight config group key.
    24. */
    25. public static final String GROUP_KEY = WeightConfig.CONFIG_PREFIX + ".group";
    26. /**
    27. * Weight config weight key.
    28. */
    29. public static final String WEIGHT_KEY = WeightConfig.CONFIG_PREFIX + ".weight";
    30. private static final Log log = LogFactory.getLog(WeightRoutePredicateFactory.class);
    31. private ApplicationEventPublisher publisher;
    32. public WeightRoutePredicateFactory() {
    33. super(WeightConfig.class);
    34. }
    35. @Override
    36. public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
    37. this.publisher = publisher;
    38. }
    39. @Override
    40. public List shortcutFieldOrder() {
    41. return Arrays.asList(GROUP_KEY, WEIGHT_KEY);
    42. }
    43. @Override
    44. public String shortcutFieldPrefix() {
    45. return WeightConfig.CONFIG_PREFIX;
    46. }
    47. @Override
    48. public void beforeApply(WeightConfig config) {
    49. if (publisher != null) {
    50. publisher.publishEvent(new WeightDefinedEvent(this, config));
    51. }
    52. }
    53. @Override
    54. public Predicate apply(WeightConfig config) {
    55. return new GatewayPredicate() {
    56. @Override
    57. public boolean test(ServerWebExchange exchange) {
    58. Map weights = exchange.getAttributeOrDefault(WEIGHT_ATTR, Collections.emptyMap());
    59. String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);
    60. // all calculations and comparison against random num happened in
    61. // WeightCalculatorWebFilter
    62. String group = config.getGroup();
    63. if (weights.containsKey(group)) {
    64. String chosenRoute = weights.get(group);
    65. if (log.isTraceEnabled()) {
    66. log.trace("in group weight: " + group + ", current route: " + routeId + ", chosen route: "
    67. + chosenRoute);
    68. }
    69. return routeId.equals(chosenRoute);
    70. }
    71. else if (log.isTraceEnabled()) {
    72. log.trace("no weights found for group: " + group + ", current route: " + routeId);
    73. }
    74. return false;
    75. }
    76. @Override
    77. public String toString() {
    78. return String.format("Weight: %s %s", config.getGroup(), config.getWeight());
    79. }
    80. };
    81. }
    82. }

  • 相关阅读:
    无法创建 8192 MB 的匿名分页文件: 系统资源不足,无法完成请求的服务。
    C语言之指针详解
    DJYOS物联屏:工业HMI里的显控异构计算的超稳定解决方案
    SpringCloud01
    一张图系列 - “kv cache“
    普中精灵开发板stm32烧录程序失败
    Linux从0到1——Linux第一个小程序:进度条
    Fiori VS code 连接配置本地SDK yaml 文件配置
    HTML易忽略的角落【目录】
    matplotlib图表常用设置(四)
  • 原文地址:https://blog.csdn.net/qq_41061437/article/details/127992541