本文介绍如何使用 Spring Cloud Function 开发 Java 函数并将其发布到 Azure Functions。 完成后,你的函数代码将在 Azure 中的 使用计划 上运行,并可使用 HTTP 请求触发。

如果还没有 Azure 订阅 ,可以在开始前创建一个 免费帐户

若要使用 Java 开发函数,必须安装以下软件:

  • Java 开发人员工具包 版本 11
  • Apache Maven 3.0 或更高版本
  • Azure CLI
  • Azure Functions Core Tools 版本 4
  • 若要完成本快速入门, JAVA_HOME 必须将环境变量设置为 JDK 的安装位置。
  • 确保核心工具版本至少为 4.0.5030。
  • 我们将要构建的内容

    我们将生成一个在 Azure Functions 上运行并使用 Spring Cloud 函数配置的经典“Hello, World”函数。

    函数接收包含 User 用户名的 JSON 对象,并发送回对象 Greeting ,该对象包含该用户的欢迎消息。

    GitHub 上 azure-function-java-worker 存储库 的 Azure 中的 Spring Cloud 函数 示例中提供了该项目。 如果想要查看本快速入门中所述的最终工作,可以直接使用该示例。

    创建新的 Maven 项目

    我们将创建一个空的 Maven 项目,然后使用 Spring Cloud Function 和 Azure Functions 进行配置。

    在空文件夹中创建新的 pom.xml 文件,然后复制/粘贴示例项目的 pom.xml 文件中的内容。

    该文件使用 Spring Boot 和 Spring Cloud Function 中的 Maven 依赖项,并配置 Spring Boot 和 Azure Functions Maven 插件。

    需要为应用程序自定义几个属性:

  • <functionAppName> 是 Azure 函数的名称
  • <functionAppRegion> 是部署函数的 Azure 区域的名称
  • <functionResourceGroup> 是正在使用的 Azure 资源组的名称
  • 直接在 pom.xml 文件的顶部附近更改这些属性,如以下示例所示:

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>11</maven.compiler.source>
            <maven.compiler.target>11</maven.compiler.target>
            <azure.functions.maven.plugin.version>1.22.0</azure.functions.maven.plugin.version>
            <azure.functions.java.library.version>3.0.0</azure.functions.java.library.version>
            <!-- customize those two properties. The functionAppName should be unique across Azure -->
            <functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
            <functionAppServicePlanName>my-spring-function-service-plan</functionAppServicePlanName>
            <functionAppName>my-spring-function</functionAppName>
            <functionAppRegion>westeurope</functionAppRegion>
            <start-class>example.Application</start-class>
        </properties>
    

    创建 Azure 配置文件

    创建 src/main/azure 文件夹,向其添加以下 Azure Functions 配置文件。

    host.json

    "version": "2.0", "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" "functionTimeout": "00:10:00"

    local.settings.json

    "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "java", "FUNCTIONS_EXTENSION_VERSION": "~4", "AzureWebJobsDashboard": ""

    创建域对象

    Azure Functions 可以接收和发送 JSON 格式的对象。 我们现在将创建表示域模型的 UserGreeting 对象。 若要自定义本快速入门,使之更有趣,可以创建包含更多属性的更复杂的对象。

    创建 src/main/java/com/example/model 文件夹,添加以下两个文件:

    User.java

    package com.example.model;
    public class User {
        private String name;
        public User() {
        public User(String name) {
            this.name = name;
        public String getName() {
            return name;
        public void setName(String name) {
            this.name = name;
    

    Greeting.java

    package com.example.model;
    public class Greeting {
        private String message;
        public Greeting() {
        public Greeting(String message) {
            this.message = message;
        public String getMessage() {
            return message;
        public void setMessage(String message) {
            this.message = message;
    

    创建 Spring Boot 应用程序

    此应用程序管理所有业务逻辑,并有权访问完整的 Spring Boot 生态系统。 比起标准 Azure 函数,此功能具有两大优势:

  • 它不依赖于 Azure Functions API,因此你可以轻松地将其移植到其他系统。 例如,可以在常规 Spring Boot 应用程序中重复使用它。
  • 可以使用 Spring Boot 中的所有 @Enable 注释来添加新功能。
  • src/main/java/example 文件夹中,创建以下文件,这是一个普通的 Spring Boot 应用程序:

    DemoApplication.java:

    package example;
    import example.uppercase.Config;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(Config.class, args);
    

    现在,在 src/main/java/example/hello 文件夹中创建以下文件。 此代码包含一个 Spring Boot 组件,该组件表示要运行的函数:

    Hello.java:

    package example.hello;
    import example.hello.model.*;
    import org.springframework.stereotype.Component;
    import java.util.function.Function;
    @Component
    public class Hello implements Function<User, Greeting> {
        @Override
        public Greeting apply(User user) {
            return new Greeting("Hello, " + user.getName() + "!\n");
    

    Hello 函数很特别:

  • 它是一个 java.util.function.Function。 它包含业务逻辑,可以使用标准 Java API 将一个对象转换成另一个对象。
  • 由于它具有 @Component 注释,因此是一个 Spring Bean,并且默认情况下其名称与类名相同,但以小写字符 hello 开头。 如果要在应用程序中创建其他函数,请务必遵循此命名约定。 该名称必须与我们将在下一部分中创建的 Azure Functions 名称匹配。
  • 创建 Azure 函数

    为了受益于完整的Azure Functions API,我们现在编写一个 Azure 函数,该函数将其执行委托给上一步中创建的 Spring Cloud 函数。

    src/main/java/com/example/hello 文件夹中,创建以下 Azure 函数类文件:

    HelloHandler.java

    package example.hello;
    import com.microsoft.azure.functions.*;
    import com.microsoft.azure.functions.annotation.AuthorizationLevel;
    import com.microsoft.azure.functions.annotation.FunctionName;
    import com.microsoft.azure.functions.annotation.HttpTrigger;
    import example.hello.model.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import java.util.Optional;
    @Component
    public class HelloHandler {
        @Autowired
        private Hello hello;
        @FunctionName("hello")
        public HttpResponseMessage execute(
            @HttpTrigger(name = "request", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request, ExecutionContext context) {
            User user = request.getBody()
                               .filter(u -> u.getName() != null)
                               .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world")));
            context.getLogger().info("Greeting user name: " + user.getName());
            return request.createResponseBuilder(HttpStatus.OK)
                          .body(hello.apply(user))
                          .header("Content-Type", "application/json")
                          .build();
    

    此 Java 类是一个 Azure 函数,具有下述有趣的功能:

  • 类具有 @Component 注释,因此它是一个 Spring Bean。
  • 根据 @FunctionName("hello") 注释的定义,函数的名称为 hello
  • 类实现真正的 Azure 函数,因此可以使用此处的完整 Azure Functions API。
  • 添加单元测试

    此步骤是可选项,但建议用于验证应用程序是否正常工作。

    创建 src/test/java/com/example 文件夹,添加以下 JUnit 测试:

    HelloTest.java:

    package example.hello;
    import example.hello.model.Greeting;
    import example.hello.model.User;
    import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    public class HelloTest {
        @Test
        public void test() {
            Greeting result = new Hello().apply(new User("foo"));
            assertThat(result.getMessage()).isEqualTo("Hello, foo!\n");
    

    现在可以使用 Maven 测试 Azure 函数:

    mvn clean test
    

    在本地运行函数

    在将应用程序部署到 Azure 函数之前,让我们先在本地测试它。

    首先需将应用程序打包到 Jar 文件中:

    mvn package
    

    将应用程序打包后,即可使用 azure-functions Maven 插件来运行它:

    mvn azure-functions:run
    

    现在应该可以通过端口 7071 在 localhost 上使用 Azure 函数。 可以对此函数进行测试,方法是使用 JSON 格式的 User 对象向其发送 POST 请求。 例如,使用 cURL:

    curl -X POST http://localhost:7071/api/hello -d "{\"name\":\"Azure\"}"
    

    此函数会使用仍为 JSON 格式的 Greeting 对象进行回应:

    "message": "Hello, Azure!\n"

    下面是一个屏幕截图,cURL 请求位于屏幕顶部,本地 Azure 函数位于底部:

    在本地调试函数

    以下各部分介绍了如何调试函数。

    使用 Intellij IDEA 调试

    在 Intellij IDEA 中打开项目,然后创建要附加的“远程 JVM 调试”运行配置。 有关详细信息,请参阅教程:远程调试

    使用以下命令运行应用程序:

    mvn azure-functions:run -DenableDebug
    

    应用程序启动时,会看到以下输出:

    Worker process started and initialized.
    Listening for transport dt_socket at address: 5005
    

    在 IntelliJ IDEA 中启动项目调试。 可以看到以下输出:

    Connected to the target VM, address: 'localhost:5005', transport: 'socket'
    

    标记要调试的断点。 发送请求后,Intellij IDEA 将进入调试模式。

    使用 Visual Studio Code 调试

    在 Visual Studio Code 中打开项目,然后配置以下 launch.json 文件内容:

    "version": "0.2.0", "configurations": [ "type": "java", "name": "Attach to Remote Program", "request": "attach", "hostName": "127.0.0.1", "port": 5005

    使用以下命令运行应用程序:

    mvn azure-functions:run -DenableDebug
    

    应用程序启动时,会看到以下输出:

    Worker process started and initialized.
    Listening for transport dt_socket at address: 5005
    

    在 Visual Studio Code 中启动项目调试,然后标记要调试的断点。 发送请求后,Visual Studio Code将进入调试模式。 有关详细信息,请参阅运行和调试 Java

    将函数部署到 Azure Functions

    现在,你将将 Azure 函数发布到生产环境。 请记住,<functionAppName>pom.xml 文件中定义的 、 <functionAppRegion><functionResourceGroup> 属性用于配置函数。

    Maven 插件需要使用 Azure 进行身份验证。 如果已安装 Azure CLI,请使用 az login,然后再继续。 有关更多验证选项,请参阅 azure-maven-plugins 存储库中的身份验证

    通过运行 Maven 来自动部署函数:

    mvn azure-functions:deploy
    

    现在请转到 Azure 门户,找到已创建的 Function App

    选择函数:

  • 在函数概览中,记下函数的 URL。
  • 选择“平台功能”选项卡,找到“日志流式处理”服务,然后选择该服务来检查正在运行的函数。
  • 现在遵循上一部分的操作使用 cURL 访问正在运行的函数,如以下示例所示。 请确保将 your-function-name 替换为实际的函数名称。

    curl https://your-function-name.azurewebsites.net/api/hello -d "{\"name\":\"Azure\"}"
    

    与上一部分一样,此函数会使用仍为 JSON 格式的 Greeting 对象进行回应:

    "message": "Hello, Azure!\n"

    恭喜,你有了一个在 Azure Functions 上运行的 Spring Cloud Function! 有关 Spring Cloud 函数的详细信息和示例,请参阅以下资源:

  • Spring cloud 函数博客
  • Spring cloud 函数参考文档
  • Spring cloud 函数示例
  • 若要了解有关 Spring 和 Azure 的详细信息,请继续访问“Azure 上的 Spring”文档中心。

    Azure 上的 Spring