环境:SpringBoot2.7.15 + Spring Cloud 2021.0.8
请先阅读入门篇:《Spring Cloud Function 快速入门》
1. 概述
Spring Cloud Function 旨在通过功能促进业务逻辑的实现。它专注于提供一些与业务无关的函数功能,将业务逻辑的开发生命周期与任何特定的运行时目标分离,以便相同的代码可以作为Web终结点、流处理器或任务运行。它支持跨无服务器提供程序的统一编程模型,以及独立运行(本地或在PaaS中)的能力。
本篇将会介绍Spring Cloud Function 一些进阶的用法。
2. 进阶实例
2.1 http请求参数
在之前的入门篇中,我们都是将参数作为路径变量(即 /{function}/{item})传递给函数。例如,http://localhost:8080/uppercase/pack 将入参 pack 转为大写进行输出。
在Spring Cloud Function中会将 HTTP 请求参数与 HTTP header类似,将其保存在消息header中的 http_request_param(其值为请求参数的映射表)中,因此要访问这些参数,函数输入签名应接受消息类型(例如,Function<Message<String>, String>)。
示例代码:
public Function<Message<String>, String> params() {return message -> {System.out.println(message.getHeaders()) ;return String.format("你输入的参数:%s", message.getHeaders().get(HeaderUtils.HTTP_REQUEST_PARAM)) ;} ;}

控制台输出结果
{http_request_param={name=admin, age=33}, Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7, Connection=keep-alive, User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36, Sec-Fetch-Site=none, Sec-Fetch-Dest=document, Host=localhost:8080, Accept-Encoding=gzip, deflate, br, uri=http://localhost:8080/params?name=admin&age=33, Sec-Fetch-Mode=navigate, sec-ch-ua="Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24", sec-ch-ua-mobile=?0, Upgrade-Insecure-Requests=1, sec-ch-ua-platform="Windows", Sec-Fetch-User=?1, Accept-Language=zh-CN,zh;q=0.9, id=d601b4ea-f693-1788-5d98-98e34730befa, timestamp=1702257350126}
请求参数与请求的header在一起。
2.2 Function映射规则
映射规则中包含了部分组合函数,关于组合函数可以查看《Spring Cloud Function 快速入门》。
在有多个函数的情况下,每个函数都将导出并映射,函数名称是路径的一部分(例如,localhost:8080/uppercase)。在这种情况下,你仍然可以通过提供 spring.cloud.function.definition 属性,将特定函数或函数组合映射到根路径上。
spring:cloud::definition: length|reverse

当你定义了spring.cloud.function.definition后,当访问一个不存在的uri时,也将被映射到该根路径下。

2.3 函数过滤规则
在有多个函数的情况下,可能需要只导出某些函数或函数组合。在这种情况下,可以使用相同的 spring.cloud.function.definition 属性,列出打算导出的以 ; 分隔的函数。请注意,在这种情况下,没有任何内容会被映射到根路径,而且未列出的函数(包括组合)也不会被导出。
现有四个个Funciton:uppercase、reverse、length、split
--spring.cloud.function.definition=uppercase;reverse
通过上面的配置后,你将不能访问length,split函数。
--spring.cloud.function.definition=length|reverse;length
这你将不能访问split函数。
2.4 Functional Bean定义
Spring Cloud Function 支持 "Functional"风格的 Bean 声明,适用于需要快速启动的小型应用程序。functional Bean 声明风格是 Spring Framework 5.0 的一项功能,在 5.1 中得到了显著增强。
public class SpringcloudFunction2Application implements ApplicationContextInitializer<GenericApplicationContext> {public static void main(String[] args) {FunctionalSpringApplication.run(SpringcloudFunction2Application.class, args);}public void initialize(GenericApplicationContext context) {context.registerBean("split", FunctionRegistration.class, () -> {CustomFunction target = new CustomFunction() ;FunctionRegistration<CustomFunction> split = new FunctionRegistration<>(target, "split") ;split.type(CustomFunction.class) ;return split ;}) ;}}
去标准的SpringBoot启动类主要区别:
该类实现了ApplicationContextInitializer
编程的方式注册Bean FunctionRegistration对象
@SpringBootApplication 已被替换为 @SpringBootConfiguration,以表示不使用 Spring Boot 自动配置,但仍将该类标记为 "入口点"(简单说就是还是将当前类作为primarySources)。
Spring Boot 中的SpringApplication 已被 Spring Cloud Function 中的 FunctionalSpringApplication 所取代(这是一个子类)。该子类核心重写了父类的postProcessApplicationContext方法,在该方法中进行了判断source类型是否为ApplicationContextInitializer。
2.5 功能可视化和控制
Spring Cloud Function 支持通过 Actuator 端点和编程方式实现 FunctionCatalog 中可用功能的可视化。
编程方式
private FunctionCatalog functionCatalog ;public Function<Mono<String>, Flux<String>> funs() {return type -> Flux.fromIterable(functionCatalog.getNames(null)) ;}
浏览器输出

Actuator方式
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
开启functions功能
management:endpoints:web:exposure:include:functions
浏览器输出

2.6 Function扫描
Spring Cloud Function 会在一个名为 functions 的包中扫描 Function、Consumer 和 Supplier 的实现(如果存在)。使用此功能,您可以编写不依赖于 Spring 的函数,甚至不需要 @Component 注解。如果想使用不同的包,可以设置 spring.cloud.function.scan.packages。
spring:cloud:function:scan:packages: com.pack.functions
关闭扫描
spring:cloud:function:scan:enabled: false
完毕!!!



