领先一步
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 仓库中使用。
此里程碑版本引入的最大特性之一是支持具有多个输入和输出的函数。需要注意的是,此特性仅在响应式环境中才有意义,您可能希望将多个流传递给函数,以便对这些流进行某种类型的聚合/合并操作。对于常规情况,您可以始终使用某种类型的集合发送多个参数。
为了以*类型安全的方式*表示多个输入/输出,从而受益于类型转换和前面提到的其他特性,我们选择了来自 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[]),从而使用可用的 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 与我们联系。