您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

Azure Functions Java 开发人员指南Azure Functions Java developer guide

Azure Functions 运行时支持 Java SE 8 LTS (zulu8.31.0.2-jre8.0.181-win_x64)The Azure Functions runtime supports Java SE 8 LTS (zulu8.31.0.2-jre8.0.181-win_x64). 本指南包含有关使用 Java 编写 Azure Functions 的复杂性的信息。This guide contains information about the intricacies of writing Azure Functions with Java.

Java 函数是public方法,带有批注修饰@FunctionNameA Java function is a public method, decorated with the annotation @FunctionName. 此方法定义对于 Java 函数,条目,并在特定包中必须唯一。This method defines the entry for a Java function, and must be unique in a particular package.

本文假定你已阅读 Azure Functions 开发人员参考This article assumes that you have already read the Azure Functions developer reference. 您还应当完成函数快速入门,以创建第一个函数,通过使用Visual Studio CodeMavenYou should also complete the Functions quickstart to create your first function, by using Visual Studio Code or Maven.

编程模型Programming model

触发器和绑定是 Azure Functions 的基本概念。The concepts of triggers and bindings are fundamental to Azure Functions. 触发器启动代码的执行。Triggers start the execution of your code. 绑定可让你向函数传递数据以及从函数返回数据,而无需编写自定义的数据访问代码。Bindings give you a way to pass data to and return data from a function, without having to write custom data access code.

文件夹结构Folder structure

下面是 Azure Functions Java 项目的文件夹结构:Here is the folder structure of an Azure Functions Java project:

FunctionsProject
 | - src
 | | - main
 | | | - java
 | | | | - FunctionApp
 | | | | | - MyFirstFunction.java
 | | | | | - MySecondFunction.java
 | - target
 | | - azure-functions
 | | | - FunctionApp
 | | | | - FunctionApp.jar
 | | | | - host.json
 | | | | - MyFirstFunction
 | | | | | - function.json
 | | | | - MySecondFunction
 | | | | | - function.json
 | | | | - bin
 | | | | - lib
 | - pom.xml

您可以使用一个共享host.json文件来配置函数应用。You can use a shared host.json file to configure the function app. 每个函数都有自己的代码文件 (.Java) 和绑定配置文件 (function.json)。Each function has its own code file (.java) and binding configuration file (function.json).

可在项目中放置多个函数。You can put more than one function in a project. 不要将函数放入单独的 jar 中。Avoid putting your functions into separate jars. FunctionApp在目标目录是部署到 Azure 中的函数应用获取的内容。The FunctionApp in the target directory is what gets deployed to your function app in Azure.

触发器和注释Triggers and annotations

函数调用由触发器,如 HTTP 请求、 一个计时器或对数据的更新。Functions are invoked by a trigger, such as an HTTP request, a timer, or an update to data. 函数需要处理该触发器,以及任何其他输入,生成一个或多个输出。Your function needs to process that trigger, and any other inputs, to produce one or more outputs.

使用 com.microsoft.azure.functions.annotation.* 包中附带的 Java 注释将输入和输出绑定到方法。Use the Java annotations included in the com.microsoft.azure.functions.annotation.* package to bind input and outputs to your methods. 有关详细信息,请参阅Java 参考文档For more information, see the Java reference docs.

重要

必须配置 Azure 存储帐户中的您local.settings.json本地运行 Azure Blob 存储、 Azure 队列存储或 Azure 表存储触发器。You must configure an Azure Storage account in your local.settings.json to run Azure Blob storage, Azure Queue storage, or Azure Table storage triggers locally.

示例:Example:

public class Function {
    public String echo(@HttpTrigger(name = "req", 
      methods = {"post"},  authLevel = AuthorizationLevel.ANONYMOUS) 
        String req, ExecutionContext context) {
        return String.format(req);
    }
}

下面是生成相应function.jsonazure 函数的 maven 插件:Here is the generated corresponding function.json by the azure-functions-maven-plugin:

{
  "scriptFile": "azure-functions-example.jar",
  "entryPoint": "com.example.Function.echo",
  "bindings": [
    {
      "type": "httpTrigger",
      "name": "req",
      "direction": "in",
      "authLevel": "anonymous",
      "methods": [ "post" ]
    },
    {
      "type": "http",
      "name": "$return",
      "direction": "out"
    }
  ]
}

JDK 运行时的可用性与支持JDK runtime availability and support

对于 Java 函数应用在本地开发,下载并使用适用于 Azure 的 Azul Zulu 企业从 Java 8 Jdk Azul SystemsFor local development of Java function apps, download and use the Azul Zulu Enterprise for Azure Java 8 JDKs from Azul Systems. 将函数应用部署到云时,Azure Functions 使用 Azul Java 8 JDK 运行时。Azure Functions uses the Azul Java 8 JDK runtime when you deploy your function apps to the cloud.

Azure 支持Jdk 和函数的问题的应用可提供与限定的支持计划Azure support for issues with the JDKs and function apps is available with a qualified support plan.

自定义 JVMCustomize JVM

Functions 可自定义 Java 虚拟机 (JVM) 用于运行 Java 函数。Functions lets you customize the Java virtual machine (JVM) used to run your Java functions. 以下 JVM 选项默认情况下使用:The following JVM options are used by default:

  • -XX:+TieredCompilation
  • -XX:TieredStopAtLevel=1
  • -noverify
  • -Djava.net.preferIPv4Stack=true
  • -jar

您可以提供其他参数中的应用设置命名JAVA_OPTSYou can provide additional arguments in an app setting named JAVA_OPTS. 可以将应用设置添加到函数应用在 Azure 门户或 Azure CLI 部署到 Azure。You can add app settings to your function app deployed to Azure in the Azure portal or the Azure CLI.

Azure 门户Azure portal

在中Azure 门户,使用应用程序设置选项卡若要添加JAVA_OPTS设置。In the Azure portal, use the Application Settings tab to add the JAVA_OPTS setting.

Azure CLIAzure CLI

可以使用az functionapp config appsettings set命令设置JAVA_OPTS,如下面的示例:You can use the az functionapp config appsettings set command to set JAVA_OPTS, as in the following example:

az functionapp config appsettings set --name <APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings "JAVA_OPTS=-Djava.awt.headless=true"

此示例将启用无外设模式。This example enables headless mode. 替换<APP_NAME>的 function app 中,名称和<RESOURCE_GROUP>与资源组。Replace <APP_NAME> with the name of your function app, and <RESOURCE_GROUP> with the resource group.

警告

消耗计划,则必须添加WEBSITE_USE_PLACEHOLDER设置的值为0In the Consumption plan, you must add the WEBSITE_USE_PLACEHOLDER setting with a value of 0.
此设置也会增加 Java 函数的冷启动时间。This setting does increase the cold start times for Java functions.

第三方库Third-party libraries

Azure Functions 支持使用第三方库。Azure Functions supports the use of third-party libraries. 默认情况下,指定在项目中所有依赖项pom.xml文件将自动捆绑在过程 mvn package 目标。By default, all dependencies specified in your project pom.xml file are automatically bundled during the mvn package goal. 对于未在 pom.xml 文件中指定为依赖项的库,请将它们放在函数根目录的 lib 目录中。For libraries not specified as dependencies in the pom.xml file, place them in a lib directory in the function's root directory. 依赖项放置在lib目录添加到系统类加载程序在运行时。Dependencies placed in the lib directory are added to the system class loader at runtime.

com.microsoft.azure.functions:azure-functions-java-library依赖项默认情况下提供的类路径上,无需将其纳入lib目录。The com.microsoft.azure.functions:azure-functions-java-library dependency is provided on the classpath by default, and doesn't need to be included in the lib directory. 此外, azure functions 的 java 辅助角色添加列出的依赖项此处到类路径。Also, azure-functions-java-worker adds dependencies listed here to the classpath.

数据类型支持Data type support

你可以使用普通旧 Java 对象 (Pojo),在定义类型azure-functions-java-library,或基元数据类型,如字符串和整数绑定输入或输出绑定。You can use Plain old Java objects (POJOs), types defined in azure-functions-java-library, or primitive data types such as String and Integer to bind to input or output bindings.

PojoPOJOs

用于将输入的数据转换为 POJO, azure functions 的 java 辅助角色使用gson库。For converting input data to POJO, azure-functions-java-worker uses the gson library. 用作函数输入的 POJO 类型应是 publicPOJO types used as inputs to functions should be public.

二进制数据Binary data

将二进制输入或输出到绑定byte[],通过设置dataType字段中为将 function.json binary:Bind binary inputs or outputs to byte[], by setting the dataType field in your function.json to binary:

   @FunctionName("BlobTrigger")
    @StorageAccount("AzureWebJobsStorage")
     public void blobTrigger(
        @BlobTrigger(name = "content", path = "myblob/{fileName}", dataType = "binary") byte[] content,
        @BindingName("fileName") String fileName,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java Blob trigger function processed a blob.\n Name: " + fileName + "\n Size: " + content.length + " Bytes");
    }

如果您期望的 null 值,使用Optional<T>If you expect null values, use Optional<T>.

绑定Bindings

输入和输出绑定提供从代码内连接到数据的声明性方式。Input and output bindings provide a declarative way to connect to data from within your code. 一个函数可以有多个输入和输出绑定。A function can have multiple input and output bindings.

输入的绑定示例Input binding example

package com.example;

import com.microsoft.azure.functions.annotation.*;

public class Function {
    @FunctionName("echo")
    public static String echo(
        @HttpTrigger(name = "req", methods = { "put" }, authLevel = AuthorizationLevel.ANONYMOUS, route = "items/{id}") String inputReq,
        @TableInput(name = "item", tableName = "items", partitionKey = "Example", rowKey = "{id}", connection = "AzureWebJobsStorage") TestInputData inputData
        @TableOutput(name = "myOutputTable", tableName = "Person", connection = "AzureWebJobsStorage") OutputBinding<Person> testOutputData,
    ) {
        testOutputData.setValue(new Person(httpbody + "Partition", httpbody + "Row", httpbody + "Name"));
        return "Hello, " + inputReq + " and " + inputData.getKey() + ".";
    }

    public static class TestInputData {
        public String getKey() { return this.RowKey; }
        private String RowKey;
    }
    public static class Person {
        public String PartitionKey;
        public String RowKey;
        public String Name;

        public Person(String p, String r, String n) {
            this.PartitionKey = p;
            this.RowKey = r;
            this.Name = n;
        }
    }
}

调用此函数使用 HTTP 请求。You invoke this function with an HTTP request.

  • HTTP 请求有效负载传递作为String自变量inputReqHTTP request payload is passed as a String for the argument inputReq.
  • 一个条目将检索从表存储,作为传递TestInputData的参数inputDataOne entry is retrieved from Table storage, and is passed as TestInputData to the argument inputData.

若要接收一批的输入,可以将绑定到String[]POJO[]List<String>,或List<POJO>To receive a batch of inputs, you can bind to String[], POJO[], List<String>, or List<POJO>.

@FunctionName("ProcessIotMessages")
    public void processIotMessages(
        @EventHubTrigger(name = "message", eventHubName = "%AzureWebJobsEventHubPath%", connection = "AzureWebJobsEventHubSender", cardinality = Cardinality.MANY) List<TestEventData> messages,
        final ExecutionContext context)
    {
        context.getLogger().info("Java Event Hub trigger received messages. Batch size: " + messages.size());
    }
    
    public class TestEventData {
    public String id;
}

每当配置的事件中心内出现新数据时,就会触发此函数。This function gets triggered whenever there is new data in the configured event hub. 因为cardinality设置为MANY,该函数从事件中心接收一批消息。Because the cardinality is set to MANY, the function receives a batch of messages from the event hub. EventData 从事件中心将转换为TestEventData函数执行。EventData from event hub gets converted to TestEventData for the function execution.

输出绑定示例Output binding example

您可以通过使用输出绑定绑定到的返回值$returnYou can bind an output binding to the return value by using $return.

package com.example;

import com.microsoft.azure.functions.annotation.*;

public class Function {
    @FunctionName("copy")
    @StorageAccount("AzureWebJobsStorage")
    @BlobOutput(name = "$return", path = "samples-output-java/{name}")
    public static String copy(@BlobTrigger(name = "blob", path = "samples-input-java/{name}") String content) {
        return content;
    }
}

如果有多个输出绑定,请只使用其中一个绑定的返回值。If there are multiple output bindings, use the return value for only one of them.

若要发送多个输出值,请使用 azure-functions-java-library 包中定义的 OutputBinding<T>To send multiple output values, use OutputBinding<T> defined in the azure-functions-java-library package.

@FunctionName("QueueOutputPOJOList")
    public HttpResponseMessage QueueOutputPOJOList(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
            HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            @QueueOutput(name = "itemsOut", queueName = "test-output-java-pojo", connection = "AzureWebJobsStorage") OutputBinding<List<TestData>> itemsOut, 
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");
       
        String query = request.getQueryParameters().get("queueMessageId");
        String queueMessageId = request.getBody().orElse(query);
        itemsOut.setValue(new ArrayList<TestData>());
        if (queueMessageId != null) {
            TestData testData1 = new TestData();
            testData1.id = "msg1"+queueMessageId;
            TestData testData2 = new TestData();
            testData2.id = "msg2"+queueMessageId;

            itemsOut.getValue().add(testData1);
            itemsOut.getValue().add(testData2);

            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + queueMessageId).build();
        } else {
            return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("Did not find expected items in CosmosDB input list").build();
        }
    }

     public static class TestData {
        public String id;
    }

调用此函数在 HttpRequest。You invoke this function on an HttpRequest. 它将写入队列存储的多个值。It writes multiple values to Queue storage.

HttpRequestMessage 和 HttpResponseMessageHttpRequestMessage and HttpResponseMessage

这些定义在azure-functions-java-libraryThese are defined in azure-functions-java-library. 它们是能够使用 HttpTrigger 函数的帮助器类型。They are helper types to work with HttpTrigger functions.

专用的类型Specialized type 确定目标Target 典型的使用情况Typical usage
HttpRequestMessage<T> HTTP 触发器HTTP Trigger 获取方法、 标头或查询Gets method, headers, or queries
HttpResponseMessage HTTP 输出绑定HTTP Output Binding 返回非 200 状态Returns status other than 200

元数据Metadata

少量的触发器会连同输入数据一起发送触发器元数据Few triggers send trigger metadata along with input data. 可以使用批注@BindingName地绑定到触发器元数据。You can use annotation @BindingName to bind to trigger metadata.

package com.example;

import java.util.Optional;
import com.microsoft.azure.functions.annotation.*;


public class Function {
    @FunctionName("metadata")
    public static String metadata(
        @HttpTrigger(name = "req", methods = { "get", "post" }, authLevel = AuthorizationLevel.ANONYMOUS) Optional<String> body,
        @BindingName("name") String queryValue
    ) {
        return body.orElse(queryValue);
    }
}

在前面的示例中,queryValue绑定到查询字符串参数name在 http 请求 URL 中, http://{example.host}/api/metadata?name=testIn the preceding example, the queryValue is bound to the query string parameter name in the http request URL, http://{example.host}/api/metadata?name=test. 下面是另一个示例,演示如何将绑定到Id从队列触发器元数据。Here's another example, showing how to bind to Id from queue trigger metadata.

 @FunctionName("QueueTriggerMetadata")
    public void QueueTriggerMetadata(
        @QueueTrigger(name = "message", queueName = "test-input-java-metadata", connection = "AzureWebJobsStorage") String message,@BindingName("Id") String metadataId,
        @QueueOutput(name = "output", queueName = "test-output-java-metadata", connection = "AzureWebJobsStorage") OutputBinding<TestData> output,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java Queue trigger function processed a message: " + message + " with metadaId:" + metadataId );
        TestData testData = new TestData();
        testData.id = metadataId;
        output.setValue(testData);
    }

备注

在批注中提供的名称必须与匹配的元数据属性。The name provided in the annotation needs to match the metadata property.

执行上下文Execution context

ExecutionContext定义在azure-functions-java-library,包含帮助器方法与 functions 运行时进行通信。ExecutionContext, defined in the azure-functions-java-library, contains helper methods to communicate with the functions runtime.

记录器Logger

使用getLogger中定义ExecutionContext,以将日志写入到函数代码中。Use getLogger, defined in ExecutionContext, to write logs from function code.

示例:Example:


import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.*;

public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {"post"}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) {
        if (req.isEmpty()) {
            context.getLogger().warning("Empty request body received by function " + context.getFunctionName() + " with invocation " + context.getInvocationId());
        }
        return String.format(req);
    }
}

查看日志和跟踪View logs and trace

可以使用 Azure CLI 将流 Java stdout 和 stderr 日志记录,以及其他应用程序日志记录。You can use the Azure CLI to stream Java stdout and stderr logging, as well as other application logging.

下面介绍了如何将函数应用配置为使用 Azure CLI 编写应用程序日志记录:Here's how to configure your function app to write application logging by using the Azure CLI:

az webapp log config --name functionname --resource-group myResourceGroup --application-logging true

通过使用 Azure CLI 流日志记录输出的 function app,请打开新的命令提示符、 Bash 或终端会话中,并输入以下命令:To stream logging output for your function app by using the Azure CLI, open a new command prompt, Bash, or Terminal session, and enter the following command:

az webapp log tail --name webappname --resource-group myResourceGroup

Az webapp log tail命令的选项,通过筛选输出--provider选项。The az webapp log tail command has options to filter output by using the --provider option.

若要使用 Azure CLI 为单个 ZIP 文件下载日志文件,打开新的命令提示符、 Bash 或终端会话中,并输入以下命令:To download the log files as a single ZIP file by using the Azure CLI, open a new command prompt, Bash, or Terminal session, and enter the following command:

az webapp log download --resource-group resourcegroupname --name functionappname

你必须启用了 Azure 门户或 Azure CLI 中运行此命令之前记录的文件系统。You must have enabled file system logging in the Azure portal or the Azure CLI before running this command.

环境变量Environment variables

在 Functions 中,服务连接字符串等应用设置在执行过程中将公开为环境变量。In Functions, app settings, such as service connection strings, are exposed as environment variables during execution. 可以通过使用,访问这些设置System.getenv("AzureWebJobsStorage")You can access these settings by using, System.getenv("AzureWebJobsStorage").

例如,您可以添加AppSetting,具有名称testAppSetting和值testAppSettingValue:For example, you can add AppSetting, with the name testAppSetting and the value testAppSettingValue:


public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {"post"}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) {
        context.getLogger().info("testAppSetting "+ System.getenv("testAppSettingValue"));
        return String.format(req);
    }
}

后续步骤Next steps

有关 Azure Functions Java 开发的详细信息,请参阅以下资源:For more information about Azure Functions Java development, see the following resources: