Spring Cloud / Alibaba 微服务架构

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

上篇文章创建了网关子模块并介绍了Predicate的test方法,本篇文章将继续举例说明一下Predicate中and、negate、or、isEqual方法,简略解读一下PathRoutePredicateFactory.apply方法的源码。

Predicate 的 and 方法

and方法等同于我们的逻辑与(&&),存在短路特性,需要所有的条件都满足,代码如下:

1
2
3
4
5
6
7
8
9
10
ini复制代码@Test
public void testPredicateAnd() {

Predicate<String> letterLengthLimit = s -> s.length() > 5;
Predicate<String> letterStartWith = s -> s.startsWith("gate");

MICRO_SERVICE.stream().filter(
letterLengthLimit.and(letterStartWith)
).forEach(System.out::println);
}

Predicate 的 or 方法

or等同于我们的逻辑或(||),多个条件只要一个满足即可。 代码如下:

1
2
3
4
5
6
7
8
9
10
ini复制代码@Test
public void testPredicateOr() {

Predicate<String> letterLengthLimit = s -> s.length() > 5;
Predicate<String> letterStartWith = s -> s.startsWith("gate");

MICRO_SERVICE.stream().filter(
letterLengthLimit.or(letterStartWith)
).forEach(System.out::println);
}

Predicate 的 negate 方法

negate 等同于我们的逻辑非(!)。 代码如下:

1
2
3
4
5
6
typescript复制代码@Test
public void testPredicateNegate() {

Predicate<String> letterStartWith = s -> s.startsWith("gate");
MICRO_SERVICE.stream().filter(letterStartWith.negate()).forEach(System.out::println);
}

Predicate 的 isEqual 方法

isEqual 类似于 equals(),区别在于,isEqual 会先判断对象是否为 NULL,不为 NULL 再使用 equals 进行比较。 代码如下:

1
2
3
4
5
scss复制代码@Test
public void testPredicateIsEqual() {
Predicate<String> equalGateway = s -> Predicate.isEqual("gateway").test(s);
MICRO_SERVICE.stream().filter(equalGateway).forEach(System.out::println);
}

PathRoutePredicateFactory.apply方法的源码

以上就大体介绍完了Predicate的方法,可以查看PathRoutePredicateFactory.apply方法的源码,apply方法最终是返回了一个new GatewayPredicate(),它继承了java8的Predicate,里面就有实现test方法。

先通过parsePath方法去获取到当前请求的路径信息,然后再去判断一下这个路径信息与我们传进来的配置是否相关,通过filter进行一个matches正则表达式的判断是否匹配,然后用findFirst返回第一个满足条件的。isPresent方法是判断查询的类对象是否存在。大家也可以去了解一下Java8引入的一个类————Optional,它的存在很好地解决了空指针异常的问题。

以下是两个比较常用的方法:

1、ofNullable

1
2
3
4
5
6
7
8
9
10
11
12
php复制代码/**
* Returns an {@code Optional} describing the specified value, if non-null,
* otherwise returns an empty {@code Optional}.
*
* @param <T> the class of the value
* @param value the possibly-null value to describe
* @return an {@code Optional} with a present value if the specified value
* is non-null, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}

2、orElse

1
2
3
4
5
6
7
8
9
10
typescript复制代码/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
* be null
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}

匹配就代表当前的请求被路由到当前定义的route中,否则就没有匹配再去寻找完成其他匹配。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
arduino复制代码public Predicate<ServerWebExchange> apply(PathRoutePredicateFactory.Config config) {
final ArrayList<PathPattern> pathPatterns = new ArrayList();
synchronized(this.pathPatternParser) {
this.pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchOptionalTrailingSeparator());
config.getPatterns().forEach((pattern) -> {
PathPattern pathPattern = this.pathPatternParser.parse(pattern);
pathPatterns.add(pathPattern);
});
}

return new GatewayPredicate() {
public boolean test(ServerWebExchange exchange) {
PathContainer path = PathContainer.parsePath(exchange.getRequest().getURI().getRawPath());
Optional<PathPattern> optionalPathPattern = pathPatterns.stream().filter((pattern) -> {
return pattern.matches(path);
}).findFirst();
if (optionalPathPattern.isPresent()) {
PathPattern pathPattern = (PathPattern)optionalPathPattern.get();
PathRoutePredicateFactory.traceMatch("Pattern", pathPattern.getPatternString(), path, true);
PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
ServerWebExchangeUtils.putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
return true;
} else {
PathRoutePredicateFactory.traceMatch("Pattern", config.getPatterns(), path, false);
return false;
}
}

public String toString() {
return String.format("Paths: %s, match trailing slash: %b", config.getPatterns(), config.isMatchOptionalTrailingSeparator());
}
};
}

那么对于Predicate我们就介绍到这边,下一篇文章我们将介绍一下集成Alibaba Nacos实现动态路由配置。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%