Java-ontwikkelaarshandleiding voor Azure Functions

Deze handleiding bevat gedetailleerde informatie om u te helpen bij het ontwikkelen van Azure Functions met behulp van Java.

Als java-ontwikkelaar kunt u, als u nog niet eerder met Azure Functions werkt, eerst een van de volgende artikelen lezen:

Aan de slag Concepten Scenario's/voorbeelden

Basisprincipes van Java-functies

Een Java-functie is een public methode, versierd met de aantekening @FunctionName. Deze methode definieert de vermelding voor een Java-functie en moet uniek zijn in een bepaald pakket. Het pakket kan meerdere klassen hebben met meerdere openbare methoden met aantekeningen @FunctionName. Er wordt één pakket geïmplementeerd in een functie-app in Azure. In Azure biedt de functie-app de implementatie-, uitvoerings- en beheercontext voor uw afzonderlijke Java-functies.

Programmeermodel

De concepten van triggers en bindingen zijn fundamenteel voor Azure Functions. Triggers starten de uitvoering van uw code. Met bindingen kunt u gegevens doorgeven aan en retourneren van een functie, zonder dat u aangepaste gegevenstoegangscode hoeft te schrijven.

Java-functies maken

Om het eenvoudiger te maken om Java-functies te maken, zijn er hulpprogramma's en archetypen op basis van Maven die gebruikmaken van vooraf gedefinieerde Java-sjablonen om u te helpen bij het maken van projecten met een specifieke functietrigger.

Hulpprogramma's op basis van Maven

De volgende ontwikkelomgevingen hebben Azure Functions-hulpprogramma's waarmee u Java-functieprojecten kunt maken:

Deze artikelen laten zien hoe u uw eerste functies maakt met behulp van uw IDE van keuze.

Projectbouw

Als u liever opdrachtregelontwikkeling vanuit de Terminal gebruikt, is het gebruik van archetypen de eenvoudigste manier om op Java gebaseerde functieprojecten te gebruiken Apache Maven . Het Java Maven-archetype voor Azure Functions wordt gepubliceerd onder de volgende groupId:artifactId: com.microsoft.azure:azure-functions-archetype.

Met de volgende opdracht wordt een nieuw Java-functieproject gegenereerd met behulp van dit archetype:

mvn archetype:generate \
    -DarchetypeGroupId=com.microsoft.azure \
    -DarchetypeArtifactId=azure-functions-archetype

Zie de Java-quickstart om aan de slag te gaan met dit archetype.

Mapstructuur

Dit is de mapstructuur van een 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

U kunt een gedeeld host.json-bestand gebruiken om de functie-app te configureren. Elke functie heeft een eigen codebestand (.java) en een bindingsconfiguratiebestand (function.json).

U kunt meer dan één functie in een project plaatsen. Vermijd het plaatsen van uw functies in afzonderlijke JAR's. De FunctionApp in de doelmap wordt geïmplementeerd in uw functie-app in Azure.

Triggers en aantekeningen

Functies worden aangeroepen door een trigger, zoals een HTTP-aanvraag, een timer of een update van gegevens. Uw functie moet die trigger en andere invoer verwerken om een of meer uitvoer te produceren.

Gebruik de Java-aantekeningen die zijn opgenomen in het pakket com.microsoft.azure.functions.annotation.* om invoer en uitvoer aan uw methoden te binden. Zie de Java-referentiedocumenten voor meer informatie.

Belangrijk

U moet een Azure Storage-account in uw local.settings.json configureren om Azure Blob Storage, Azure Queue Storage of Azure Table Storage-triggers lokaal uit te voeren.

Voorbeeld:

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

Dit is de gegenereerde overeenkomstige function.json door de azure-functions-maven-plugin:

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

Java-versies

De versie van Java waarop uw app wordt uitgevoerd in Azure, wordt opgegeven in het pom.xml-bestand. Het Maven-archetype genereert momenteel een pom.xml voor Java 8, die u kunt wijzigen voordat u publiceert. De Java-versie in pom.xml moet overeenkomen met de versie waarop u uw app lokaal hebt ontwikkeld en getest.

Ondersteunde versies

In de volgende tabel ziet u de huidige ondersteunde Java-versies voor elke primaire versie van de Functions-runtime, per besturingssysteem:

Functions-versie Java-versies (Windows) Java-versies (Linux)
4.x 17
11
8
21 (preview)
17
11
8
3.x 11
8
11
8
2.x 8 N.v.t.

Tenzij u een Java-versie voor uw implementatie opgeeft, wordt het Maven-archetype standaard ingesteld op Java 8 tijdens de implementatie in Azure.

De implementatieversie opgeven

U kunt de versie van Java beheren waarop het Maven-archetype is gericht met behulp van de -DjavaVersion parameter. De waarde van deze parameter kan 8ofwel , 1117 of 21.

Het Maven-archetype genereert een pom.xml die is gericht op de opgegeven Java-versie. De volgende elementen in pom.xml aangeven welke Java-versie moet worden gebruikt:

Element Java 8-waarde Java 11-waarde Java 17-waarde Java 21-waarde (preview, Linux) Beschrijving
Java.version 1.8 11 17 21 Versie van Java die wordt gebruikt door de maven-compiler-plugin.
JavaVersion 8 11 17 21 Java-versie die wordt gehost door de functie-app in Azure.

In de volgende voorbeelden ziet u de instellingen voor Java 8 in de relevante secties van het bestand pom.xml:

Java.version

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
    <azure.functions.maven.plugin.version>1.6.0</azure.functions.maven.plugin.version>
    <azure.functions.java.library.version>1.3.1</azure.functions.java.library.version>
    <functionAppName>fabrikam-functions-20200718015742191</functionAppName>
    <stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
</properties>

JavaVersion

<runtime>
    <!-- runtime os, could be windows, linux or docker-->
    <os>windows</os>
    <javaVersion>8</javaVersion>
    <!-- for docker function, please set the following parameters -->
    <!-- <image>[hub-user/]repo-name[:tag]</image> -->
    <!-- <serverId></serverId> -->
    <!-- <registryUrl></registryUrl>  -->
</runtime>

Belangrijk

U moet de JAVA_HOME omgevingsvariabele juist hebben ingesteld op de JDK-map die wordt gebruikt tijdens het compileren van code met behulp van Maven. Zorg ervoor dat de versie van de JDK minstens zo hoog is als de Java.version instelling.

Het implementatie-besturingssysteem opgeven

Met Maven kunt u ook het besturingssysteem opgeven waarop uw functie-app wordt uitgevoerd in Azure. Gebruik het os element om het besturingssysteem te kiezen.

Element Windows Linux Docker
os windows linux docker

In het volgende voorbeeld ziet u de besturingssysteeminstelling in de runtime sectie van het pom.xml-bestand:

<runtime>
    <!-- runtime os, could be windows, linux or docker-->
    <os>windows</os>
    <javaVersion>8</javaVersion>
    <!-- for docker function, please set the following parameters -->
    <!-- <image>[hub-user/]repo-name[:tag]</image> -->
    <!-- <serverId></serverId> -->
    <!-- <registryUrl></registryUrl>  -->
</runtime>

Beschikbaarheid en ondersteuning van JDK-runtime

Microsoft- en Adoptium-builds van OpenJDK worden geleverd en ondersteund op Functions voor Java 8 (Adoptium), Java 11, 17 en 21 (MSFT). Deze binaire bestanden worden geleverd als een gratis, multiplatform, productieklare distributie van de OpenJDK voor Azure. Ze bevatten alle onderdelen voor het maken en uitvoeren van Java SE-toepassingen.

Voor lokale ontwikkeling of tests kunt u de Microsoft-build van OpenJDK of Adoptium Temurin gratis downloaden. ondersteuning voor Azure voor problemen met de JDK's en functie-apps is beschikbaar met een gekwalificeerd ondersteuningsplan.

Als u de Zulu voor Binaire Azure-bestanden in uw Functie-app wilt blijven gebruiken, configureert u uw app dienovereenkomstig. U kunt de binaire Azul-bestanden voor uw site blijven gebruiken. Beveiligingspatches of verbeteringen zijn echter alleen beschikbaar in nieuwe versies van de OpenJDK. Daarom moet u deze configuratie uiteindelijk verwijderen, zodat uw apps de nieuwste beschikbare versie van Java gebruiken.

JVM aanpassen

Met Functies kunt u de virtuele Java-machine (JVM) aanpassen die wordt gebruikt om uw Java-functies uit te voeren. De volgende JVM-opties worden standaard gebruikt:

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

U kunt andere argumenten opgeven voor de JVM met behulp van een van de volgende toepassingsinstellingen, afhankelijk van het type plan:

Abonnementtype Naam instelling Opmerking
Verbruiksabonnement languageWorkers__java__arguments Deze instelling verhoogt de koude begintijden voor Java-functies die worden uitgevoerd in een verbruiksabonnement.
Premium-abonnement
Toegewezen abonnement
JAVA_OPTS

In de volgende secties ziet u hoe u deze instellingen toevoegt. Zie de sectie Werken met toepassingsinstellingen voor meer informatie over het werken met toepassingsinstellingen .

Azure Portal

Gebruik in Azure Portal het tabblad Toepassing Instellingen om de languageWorkers__java__arguments of de JAVA_OPTS instelling toe te voegen.

Azure-CLI

U kunt de opdracht az functionapp config appsettings set gebruiken om deze instellingen toe te voegen, zoals wordt weergegeven in het volgende voorbeeld voor de -Djava.awt.headless=true optie:

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

In dit voorbeeld wordt de headless-modus ingeschakeld. Vervang <APP_NAME> door de naam van uw functie-app en <RESOURCE_GROUP> door de resourcegroep.

Bibliotheken van derden

Azure Functions ondersteunt het gebruik van bibliotheken van derden. Standaard worden alle afhankelijkheden die zijn opgegeven in uw projectbestand pom.xml , automatisch gebundeld tijdens het mvn package doel. Voor bibliotheken die niet zijn opgegeven als afhankelijkheden in het pom.xml bestand, plaatst u deze in een lib map in de hoofdmap van de functie. Afhankelijkheden die in de lib map worden geplaatst, worden tijdens runtime toegevoegd aan het systeemklasselaadprogramma.

De com.microsoft.azure.functions:azure-functions-java-library afhankelijkheid is standaard opgegeven in het klassepad en hoeft niet in de lib map te worden opgenomen. Daarnaast voegt azure-functions-java-worker hier vermelde afhankelijkheden toe aan het klassepad.

Ondersteuning voor gegevenstypen

U kunt gewone oude Java-objecten (POJO's), typen die zijn gedefinieerd in azure-functions-java-library, of primitieve gegevenstypen zoals Tekenreeks en Geheel getal gebruiken om te binden aan invoer- of uitvoerbindingen.

POJO's

Voor het converteren van invoergegevens naar POJO maakt azure-functions-java-worker gebruik van de gson-bibliotheek . POJO-typen die worden gebruikt als invoer voor functies moeten zijn public.

Binaire gegevens

Bind binaire invoer of uitvoer aan , door het dataType veld in uw function.json in te byte[]stellen opbinary:

   @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");
    }

Als u null-waarden verwacht, gebruikt u Optional<T>.

Bindingen

Invoer- en uitvoerbindingen bieden een declaratieve manier om vanuit uw code verbinding te maken met gegevens. Een functie kan meerdere invoer- en uitvoerbindingen hebben.

Voorbeeld van invoerbinding

package com.example;

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

public class Function {
    @FunctionName("echo")
    public static String echo(
        @HttpTrigger(name = "req", methods = { HttpMethod.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;
        }
    }
}

U roept deze functie aan met een HTTP-aanvraag.

  • De nettolading van de HTTP-aanvraag wordt doorgegeven als een String voor het argument inputReq.
  • Eén vermelding wordt opgehaald uit Table Storage en wordt doorgegeven als TestInputData aan het argument inputData.

Als u een batch invoer wilt ontvangen, kunt u binden aan String[], POJO[]of List<String>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;
}

Deze functie wordt geactiveerd wanneer er nieuwe gegevens zijn in de geconfigureerde Event Hub. Omdat de cardinality functie is ingesteld op MANY, ontvangt de functie een batch berichten van de Event Hub. EventData van Event Hub wordt geconverteerd naar TestEventData de uitvoering van de functie.

Voorbeeld van uitvoerbinding

U kunt een uitvoerbinding binden aan de retourwaarde met behulp van $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;
    }
}

Als er meerdere uitvoerbindingen zijn, gebruikt u de retourwaarde voor slechts één van deze bindingen.

Als u meerdere uitvoerwaarden wilt verzenden, gebruikt OutputBinding<T> u gedefinieerd in het azure-functions-java-library pakket.

@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;
    }

U roept deze functie aan op een HttpRequest object. Er worden meerdere waarden naar Queue Storage geschreven.

HttpRequestMessage en HttpResponseMessage

Deze worden gedefinieerd in azure-functions-java-library. Ze zijn helpertypen om te werken met HttpTrigger-functies.

Gespecialiseerd type Doel Normaal gebruik
HttpRequestMessage<T> HTTP-trigger Methode, headers of query's opvragen
HttpResponseMessage HTTP-uitvoerbinding Retourneert een andere status dan 200

Metagegevens

Enkele triggers verzenden metagegevens van triggers samen met invoergegevens. U kunt aantekeningen @BindingName gebruiken om te binden om metagegevens te activeren.

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 = { HttpMethod.GET, HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) Optional<String> body,
        @BindingName("name") String queryValue
    ) {
        return body.orElse(queryValue);
    }
}

In het voorgaande voorbeeld is de queryValue waarde gebonden aan de querytekenreeksparameter name in de URL van de HTTP-aanvraag. http://{example.host}/api/metadata?name=test Hier volgt een ander voorbeeld, waarin wordt getoond hoe u verbinding kunt maken Id met metagegevens van wachtrijtriggers.

 @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);
    }

Notitie

De naam in de aantekening moet overeenkomen met de eigenschap metagegevens.

Context voor uitvoering

ExecutionContext, gedefinieerd in de azure-functions-java-library, bevat helpermethoden om te communiceren met de functions-runtime. Zie het naslagartikel ExecutionContext voor meer informatie.

Logger

Gebruik getLogger, gedefinieerd in ExecutionContext, om logboeken te schrijven uit functiecode.

Voorbeeld:


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

public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {HttpMethod.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);
    }
}

Logboeken en tracering weergeven

U kunt de Azure CLI gebruiken om logboekregistratie van Java stdout en stderr te streamen, en andere toepassingslogboeken.

U kunt als volgt uw functie-app configureren voor het schrijven van toepassingslogboeken met behulp van de Azure CLI:

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

Als u de uitvoer van logboekregistratie voor uw functie-app wilt streamen met behulp van de Azure CLI, opent u een nieuwe opdrachtprompt, Bash of Terminal-sessie en voert u de volgende opdracht in:

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

De opdracht az webapp log tail bevat opties om uitvoer te filteren met behulp van de --provider optie.

Als u de logboekbestanden wilt downloaden als één ZIP-bestand met behulp van de Azure CLI, opent u een nieuwe opdrachtprompt, Bash of Terminal-sessie en voert u de volgende opdracht in:

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

U moet logboekregistratie van het bestandssysteem hebben ingeschakeld in Azure Portal of de Azure CLI voordat u deze opdracht uitvoert.

Omgevingsvariabelen

In Functions worden app-instellingen, zoals service-verbindingsreeks s, tijdens de uitvoering weergegeven als omgevingsvariabelen. U hebt toegang tot deze instellingen met behulp van. System.getenv("AzureWebJobsStorage")

In het volgende voorbeeld wordt de toepassingsinstelling ophaalt, met de sleutel met de naammyAppSetting:


public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) {
        context.getLogger().info("My app setting value: "+ System.getenv("myAppSetting"));
        return String.format(req);
    }
}

Afhankelijkheidsinjectie gebruiken in Java Functions

Azure Functions Java ondersteunt het ontwerppatroon voor afhankelijkheidsinjectie (DI), een techniek voor het bereiken van Inversion of Control (IoC) tussen klassen en hun afhankelijkheden. Java Azure Functions biedt een hook om te integreren met populaire frameworks voor afhankelijkheidsinjectie in uw Functions-apps. Azure Functions Java SPI bevat een interface FunctionInstanceInjector. Door deze interface te implementeren, kunt u een exemplaar van uw functieklasse retourneren en worden uw functies aangeroepen op dit exemplaar. Dit biedt frameworks zoals Spring, Quarkus, Google Guice, Dagger, enzovoort, de mogelijkheid om het functie-exemplaar te maken en te registreren in hun IOC-container. Dit betekent dat u deze frameworks voor afhankelijkheidsinjectie kunt gebruiken om uw functies op natuurlijke wijze te beheren.

Notitie

Microsoft Azure Functions Java SPI Types (azure-function-java-spi) is een pakket met alle SPI-interfaces voor derden om te communiceren met Microsoft Azure Functions Runtime.

Injector van functie-exemplaar voor afhankelijkheidsinjectie

azure-function-java-spi bevat een interface FunctionInstanceInjector

package com.microsoft.azure.functions.spi.inject; 

/** 

 * The instance factory used by DI framework to initialize function instance. 

 * 

 * @since 1.0.0 

 */ 

public interface FunctionInstanceInjector { 

    /** 

     * This method is used by DI framework to initialize the function instance. This method takes in the customer class and returns 

     * an instance create by the DI framework, later customer functions will be invoked on this instance. 

     * @param functionClass the class that contains customer functions 

     * @param <T> customer functions class type 

     * @return the instance that will be invoked on by azure functions java worker 

     * @throws Exception any exception that is thrown by the DI framework during instance creation 

     */ 

    <T> T getInstance(Class<T> functionClass) throws Exception; 

} 

Raadpleeg deze opslagplaats voor meer voorbeelden die FunctionInstanceInjector gebruiken om te integreren met frameworks voor afhankelijkheidsinjectie.

Volgende stappen

Zie de volgende resources voor meer informatie over azure Functions Java-ontwikkeling: