领先一步
VMware 提供培训和认证,助力您快速提升。
了解更多Spring Cloud Function 是一个基于 SpringBoot 的框架,它允许用户将业务逻辑实现为 Java Function(即 Supplier、Function、Consumer),从而专注于业务逻辑本身。该框架提供了必要的抽象层,以便在各种环境(例如 REST、Streaming)以及诸如 AWS Lambda 或 Azure Functions 等无服务器环境中执行这些函数,而无需担心底层特定于平台的细节。这使得开发者可以专注于编写业务逻辑,而将其他事情交给框架处理。
Spring Cloud Function 使用 java.util.function.Function/Supplier/Consumer
接口作为构建块来定义函数的结构,包括输入和输出类型。
下面是一个简单的 Spring Cloud Function 示例,它接收一个字符串并返回该字符串的大写形式
首先,我们定义函数接口
public interface UppercaseFunction extends Function<String, String> { }
接下来,我们将函数注册为一个 Bean
@Bean
public UppercaseFunction uppercase() {
return value -> value.toUpperCase();
}
这只是 Spring Cloud Function 的一个基本示例,您可以将其用于更复杂的用例,例如连接到数据库、消费消息队列中的消息等等。函数本身只是一段实现为 Java 函数并注册为 Spring Bean 的代码。然而,借助 Spring Cloud Function,这个函数可以成为 REST 请求的处理器,或者由 Kafka 等消息系统触发的消息处理器。同一个函数也可以在 AWS Lambda 或 Microsoft Azure 等无服务器环境中执行,而无需修改其实现。这正是本文的主旨所在,特别是 Spring Cloud Function 与 Microsoft Azure 的集成。
Azure Java Functions 是一项服务,它允许您编写基于 Java 的无服务器函数,并在 Azure 基础设施上运行它们,同时能够与 Spring Boot 等其他 Azure 服务和框架集成。
Azure Functions 运行时负责函数应用的伸缩、安全和监控,并提供与其他 Azure 服务的轻松集成。您可以在此处阅读更多关于 Azure Java Functions 的信息。
Spring Cloud Function 提供了一个 Azure 适配器,用于将 Java 函数部署并作为 Azure Java Functions 运行。
为了将 Spring Cloud Function 与 Azure Java Functions 一起使用,您需要在 classpath 中包含 spring-cloud-function-adapter-azure
依赖项
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
<version>4.0.4</version>
</dependency>
值得注意的是,使用 Spring Cloud Function 使您能够在 Azure Java Functions 上使用简单的 Java Function 编程模型,但底层基础设施仍然是 Azure Functions,您仍然需要管理 Azure Function 应用的伸缩、安全和监控,以及与其他 Azure 服务的集成。
让我们来看一个例子。为此,我们需要将业务逻辑(即,将字符串转换为大写)提取到一个名为 uppercase
的专用函数中
import java.util.function.Function;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class HttpTriggerDemoApplication {
@Bean
public Function<String, String> uppercase() {
return payload -> {
String output = payload.toUpperCase();
return String.format("Input: %s", output);
}
}
@Bean
public Function<String, String> reverse() {
return payload -> new StringBuilder(payload).reverse().toString();
}
public static void main(String[] args) {
SpringApplication.run(HttpTriggerDemoApplication.class, args);
}
}
这个示例使用 @SpringBootApplication
注解配置 Spring Boot 应用程序,并使用 @Bean
注解定义一个函数 Bean。然后,要在 Azure Java Function 上运行此函数,您需要在 Azure 上创建一个新的函数应用并配置它以使用 Java 运行时。
import java.util.Optional;
import java.util.function.Function;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.stereotype.Component;
@Component
public class AzureJavaExampleFunctionWithSpring {
/**
* Plain Spring bean (not Spring Cloud Functions!)
*/
@Autowired
private Function<String, String> uppercase;
/**
* The FunctionCatalog leverages the Spring Cloud Function framework.
*/
@Autowired
private FunctionCatalog functionCatalog;
@FunctionName("bean")
public String plainBeans(
@HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
// Use plain Spring Beans.
return uppercase.apply(request.getBody().orElse("Hello World"));
}
@FunctionName("scf")
public String springCloudFunction(
@HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
// Use SCF composition.
Function composed = this.functionCatalog.lookup("reverse|uppercase");
return (String) composed.apply(request.getBody().orElse("Hello World"));
}
}
AzureJavaExampleFunctionWithSpring
类使用标准的 Azure 注解(例如 @FunctionName 和 @HttpTrigger
)进行注解,并且在内部调用 HttpTriggerDemoApplication
中定义的 uppercase
函数。@Component
注解使得这个 Azure 应用程序同时也是一个 Spring 应用程序,从而通过 Spring 依赖注入(例如自动装配 uppercase
或 functionCatalog
Bean)提供了与 Spring Cloud Function 和其他 Spring 管理组件的集成点。请注意,AzureJavaExampleFunctionWithSpring
是一个完整的 Spring 组件,因此您可以自动装配任何 Spring Bean(不仅是函数),使用属性配置和任何其他 Spring Framework 功能。
请注意,plainBeans
函数使用普通的 Spring Bean,而 springCloudFunctin
利用 FunctionCatalog
组合多个 Spring Cloud Function。
您需要将函数打包成一个 fat jar,然后将其部署到您的 Azure Function App。部署后,您可以通过 HTTP 请求或来自 Event Hub、Service Bus 等 Azure 服务的事件来触发您的函数。
您还可以使用 maven 插件 com.microsoft.azure:azure-functions-maven-plugin
将函数部署到 Azure Function,可以通过将以下内容添加到 pom.xml 中来配置该 maven 插件
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<version>1.22.0</version>
<configuration>
<appName>scf-samples</appName>
<resourceGroup>java-functions-group</resourceGroup>
<region>westus</region>
<appServicePlanName>java-functions-app-service-plan</appServicePlanName>
<pricingTier>EP1</pricingTier>
<hostJson>${project.basedir}/src/main/resources/host.json</hostJson>
<runtime>
<os>linux</os>
<javaVersion>17</javaVersion>
</runtime>
<funcPort>7072</funcPort>
<appSettings>
<property>
<name>FUNCTIONS_EXTENSION_VERSION</name>
<value>~4</value>
</property>
</appSettings>
</configuration>
<executions>
<execution>
<id>package-functions</id>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
这将使您的 Azure Java Function 与 Spring Cloud Function 集成,并且您可以利用 Spring Cloud Function 的强大功能,例如函数组合、基于 POJO 的开发等等。
更多信息请查阅更新的 Azure 适配器参考文档,各种示例可以在这里找到。
任何使用 FunctionInvoker 的现有应用程序都可以轻松转换为新的 DI Azure Function 集成风格。
例如,让我们转换以下使用传统 FunctionInvoker 风格的示例应用程序。
Spring Boot 定义了 boot 应用程序和一个名为 uppercase 的 Spring Cloud Function
import java.util.Map;
import java.util.function.Function;
import com.microsoft.azure.functions.ExecutionContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.Message;
@SpringBootApplication
public class Config {
public static void main(String[] args) throws Exception {
SpringApplication.run(Config.class, args);
}
@Bean
public Function<Message<String>, String> uppercase(JsonMapper mapper) {
return message -> {
String value = message.getPayload();
try {
Map<String, String> map = mapper.fromJson(value, Map.class);
if(map != null)
map.forEach((k, v) -> map.put(k, v != null ? v.toUpperCase() : null));
return mapper.toString(map);
} catch (Exception e) {
e.printStackTrace();
return ("Function error: - bad request");
}
};
}
}
而将 uppercase 函数用作 Azure Function 的 FunctionInvoker 将如下所示
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import java.util.Optional;
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
public class UppercaseHandler extends FunctionInvoker<Message<String>, String> {
@FunctionName("uppercase")
public String execute(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context
) {
context.getLogger().warning("Using Java (" + System.getProperty("java.version") + ")");
Message<String> message = MessageBuilder.withPayload(request.getBody().get())
.copyHeaders(request.getHeaders()).build();
return handleRequest(message, context);
}
}
请注意,按照约定,@FunctionName
必须与 @Bean 函数名(在 Config 类中)匹配。
重构 UppercaseHandler 类非常简单,我们可以像这样用 DI 替换传统的 FunctionInvoker
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import java.util.Optional;
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
@Component
public class UppercaseHandler {
@Autowired
private Function<Message<String>, String> uppercase;
@FunctionName("uppercase")
public String execute(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context
) {
context.getLogger().warning("Using Java (" + System.getProperty("java.version") + ")");
Message<String> message = MessageBuilder.withPayload(request.getBody().get())
.copyHeaders(request.getHeaders()).build();
return uppercase.apply(message);
}
}
@Component
类注解。FunctionInvoke
类继承。handleRequest
方法调用替换为显式的函数调用。现在,您就可以构建并部署您的应用程序了。