領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多Spring Cloud Function 是一個基於 Spring Boot 的框架,它允許使用者透過實現 Java 函式(即 Supplier、Function、Consumer)來專注於他們的業務邏輯。反過來,該框架提供了必要的抽象,使其能夠在各種環境中(例如 REST、流式處理)以及 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。
為了在 Azure Java Functions 中使用 Spring Cloud Function,您需要在類路徑中包含 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 函式程式設計模型,但底層基礎設施仍然是 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 請求、Azure 服務(如 Event Hub、Service Bus 等)的事件來觸發您的函式。
您還可以使用 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 定義了啟動應用程式和一個名為 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 必須與 Config 類中的 @Bean 函式名匹配。
重構 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 方法呼叫替換為顯式函式呼叫。至此,您就可以構建和部署您的應用程式了。