领先一步
VMware 提供培训和认证,助力您加速发展。
了解更多我们很高兴宣布 Spring Cloud Function 3.0.0.M2 的第二个里程碑版本发布。
注意:Spring Cloud Function 3.0.0.M1 主要用于建立与 Spring Boot 2.2.x 的兼容性,因此未发布公告。
Spring Cloud Function 3.0.0.M2 模块可在 Spring Milestone 仓库中使用。
这个里程碑版本引入的最重要的特性之一是支持具有多个输入和输出的函数。需要强调的是,此功能仅在响应式场景下才有意义,在这种场景下,您可能希望将多个流传递给函数,以便对此类流执行某种聚合/合并操作。对于传统用例,您始终可以使用某种类型的 Collection 发送多个参数。
为了以类型安全的方式表示多个输入/输出,以便受益于类型转换和前面提到的其他特性,我们选择了来自 project reactor 的 Tuple
库,考虑到 spring-cloud-function 从一开始就将其作为核心依赖。然而,未来我们也打算支持 BiFunction
等类型以及 POJO 风格的函数,前提是我们能够通过某种约定来确定输入和输出的元数和类型。
虽然此功能是新的且正在不断增强中,但一些内部项目已经在使用它,您也可以尝试一下。这是一个例子
假设有以下函数
@Bean
public Function<Tuple2<Flux<String>, Flux<Integer>>, Flux<?>[]> repeater() {
return tuple -> {
Flux<String> stringFlux = tuple.getT1();
Flux<Integer> integerFlux = tuple.getT2();
Flux<Integer> sharedIntFlux = integerFlux.publish().autoConnect(2);
Flux<String> repeated = stringFlux
.zipWith(sharedIntFlux)
.flatMap(t ->
Flux.fromIterable(Collections.nCopies(t.getT2(), t.getT1())));
Flux<Integer> sum = sharedIntFlux
.buffer(3, 1)
.map(l -> l.stream().mapToInt(Integer::intValue).sum());
return new Flux[] { repeated, sum };
};
}
您可以按如下方式调用它
Function<Tuple2<Flux<String>, Flux<Integer>>, Flux<?>[]> repeater = catalog.lookup("repeater");
Flux<String> stringStream = Flux.just("one", "two", "three");
Flux<Integer> intStream = Flux.just(3, 2, 1);
Flux<?>[] result = repeater.apply(Tuples.of(stringStream, intStream));
result[0].subscribe(System.out::println);
result[1].subscribe(System.out::println);
未来将会有关于此主题的单独博客文章。
和以前一样,函数可以通过 project reactor 实现为命令式或响应式风格。然而,在以前的版本中,我们总是对使用命令式风格实现的函数应用响应式转换。例如,Function<Foo, Foo>
会变成 Function<Flux<Foo>, Flux<Foo>>
。在此版本中,情况不再如此。以命令式方式实现的函数可以被查找并按原样(命令式)或响应式调用。例如,假设有以下配置
@Bean
public Function<String, String> uppercase() {
return v -> v.toUpperCase();
}
您可以按其编写方式访问此函数
Function<String, String> function = functionCatalog.lookup("uppercase");
或作为响应式等效形式
Function<Flux<String>, Flux<String>> reactiveFunction = functionCatalog.lookup("uppercase");
Spring Cloud Function 将自动适配。
此里程碑版本带来的新功能之一是函数核心的透明类型转换,虽然其中一部分已在 web 适配器中存在,但现在它在函数调用级别可用,允许任何类型的函数消费者(不仅是 web)从中受益。此功能的主要好处之一体现在函数组合时(稍后会详细介绍)。例如,假设有以下函数:Function<Foo, Foo> foo()
和 Function<Bar, Bar> bar()
组合为 foo|bar
。虽然在以前的版本中由于一个函数的输出与另一个函数的输入类型不兼容而无法工作,但现在只要提供了适当的转换策略,就可以支持这种组合。这些转换策略是标准的 Spring ConversionService
和 MessageConverters
。虽然我们仍在完善此功能并提供详细文档,但适用于大多数情况(例如 JSON)的 ConversionService
和 MessageConverters
已经默认初始化。
例如,假设有以下函数配置
@Bean
public Function<Person, Person> uppercasePerson() {
return person -> {
return new Person(person.getName().toUpperCase(), person.getId());
};
}
为了利用 MessageConverters
,我们可以将此函数调用为 Function<Message<String>, Person>
(或将 byte[] 作为 payload),从而使用可用的 JSON MessageConverter
将 String
转换为 Person
(见下文)。
Function<Message<String>, Person> uppercasePerson = catalog.lookup("uppercasePerson");
Person person = uppercasePerson.apply(MessageBuilder.withPayload("{\"name\":\"bill\",\"id\":2}").build());
请记住,对于使用响应式风格编写的函数,没有任何变化,并应用相同的转换策略。
虽然函数组合对 Spring Cloud Function 来说并非新功能,但在该里程碑版本中得到了改进。
和以前一样,您可以通过 "|" 或 "," 字符来组合函数。
另一个额外的好处是,您可以组合不同编程风格的函数(例如,响应式和命令式),您可以组合 Supplier 与 Function,Supplier 与 Consumer,Function 与 Consumer 等等——我们将进行适配。您可以组合生产者函数的输出与消费者函数的输入不匹配的函数——我们将进行转换。未来将会有关于此主题的单独博客文章,我们也在完善文档中。
一如既往,我们欢迎反馈和贡献,请通过以下方式联系我们:Stackoverflow 或 GitHub 。