Funções do Azure guia para programadores Java
Este guia contém informações detalhadas para o ajudar a desenvolver Funções do Azure com Java.
Enquanto programador java, se não estiver familiarizado com Funções do Azure, considere primeiro ler um dos seguintes artigos:
Introdução | Conceitos | Cenários/exemplos |
---|---|---|
Noções básicas da função Java
Uma função Java é um public
método, decorado com a anotação @FunctionName
. Este método define a entrada de uma função Java e tem de ser exclusivo num pacote específico. O pacote pode ter várias classes com vários métodos públicos anotados com @FunctionName
. Um único pacote é implementado numa aplicação de funções no Azure. No Azure, a aplicação de funções fornece o contexto de implementação, execução e gestão para as suas funções Java individuais.
Modelo de programação
Os conceitos de acionadores e enlaces são fundamentais para Funções do Azure. Os acionadores iniciam a execução do código. Os enlaces dão-lhe uma forma de transmitir dados para e devolver dados de uma função, sem ter de escrever código de acesso a dados personalizado.
Criar funções Java
Para facilitar a criação de funções Java, existem ferramentas e arquétipos baseados no Maven que utilizam modelos Java predefinidos para o ajudar a criar projetos com um acionador de função específico.
Ferramentas baseadas no Maven
Os seguintes ambientes de programador têm ferramentas Funções do Azure que lhe permitem criar projetos de funções Java:
Estes artigos mostram-lhe como criar as suas primeiras funções com o seu IDE de eleição.
Estrutura do projeto
Se preferir o desenvolvimento da linha de comandos do Terminal, a forma mais simples de estruturar projetos de funções baseados em Java é utilizar Apache Maven
arquétipos. O arquétipo do Java Maven para Funções do Azure é publicado no seguinte groupId:artifactId: com.microsoft.azure:azure-functions-archetype.
O seguinte comando gera um novo projeto de função Java com este arquétipo:
mvn archetype:generate \
-DarchetypeGroupId=com.microsoft.azure \
-DarchetypeArtifactId=azure-functions-archetype
Para começar a utilizar este arquétipo, veja o início rápido de Java.
Estrutura de pastas
Eis a estrutura de pastas de um projeto Java Funções do Azure:
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
Pode utilizar um ficheiro host.json partilhado para configurar a aplicação de funções. Cada função tem o seu próprio ficheiro de código (.java) e o ficheiro de configuração de enlace (function.json).
Pode colocar mais do que uma função num projeto. Evite colocar as suas funções em jars separados. O FunctionApp
no diretório de destino é o que é implementado na sua aplicação de funções no Azure.
Acionadores e anotações
As funções são invocadas por um acionador, como um pedido HTTP, um temporizador ou uma atualização dos dados. A função tem de processar esse acionador e quaisquer outras entradas para produzir uma ou mais saídas.
Utilize as anotações Java incluídas no pacote com.microsoft.azure.functions.annotation.* para vincular entradas e saídas aos seus métodos. Para obter mais informações, veja os documentos de referência de Java.
Importante
Tem de configurar uma conta de Armazenamento do Azure no local.settings.json para executar o armazenamento de Blobs do Azure, o armazenamento de Filas do Azure ou os acionadores de armazenamento de Tabelas do Azure localmente.
Exemplo:
public class Function {
public String echo(@HttpTrigger(name = "req",
methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
String req, ExecutionContext context) {
return String.format(req);
}
}
Eis o que é gerado correspondente function.json
pelo 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"
}
]
}
Versões java
A versão do Java na qual a sua aplicação é executada no Azure é especificada no ficheiro pom.xml. O arquétipo maven gera atualmente uma pom.xml para Java 8, que pode alterar antes de publicar. A versão Java no pom.xml deve corresponder à versão na qual desenvolveu e testou localmente a sua aplicação.
Versões suportadas
A tabela seguinte mostra as versões Java suportadas atuais para cada versão principal do runtime de Funções, por sistema operativo:
Versão das funções | Versões java (Windows) | Versões java (Linux) |
---|---|---|
4.x | 17 11 8 |
17 11 8 |
3.x | 11 8 |
11 8 |
2.x | 8 | n/a |
A menos que especifique uma versão Java para a sua implementação, o arquétipo maven é predefinido para Java 8 durante a implementação no Azure.
Especificar a versão de implementação
Pode controlar a versão de Java direcionada pelo arquétipo maven com o -DjavaVersion
parâmetro . O valor deste parâmetro pode ser ou 8
11
.
O arquétipo maven gera uma pom.xml que visa a versão java especificada. Os seguintes elementos no pom.xml indicam a versão java a utilizar:
Elemento | Valor java 8 | Valor java 11 | Valor java 17 | Descrição |
---|---|---|---|---|
Java.version |
1.8 | 11 | 17 | Versão do Java utilizada pelo maven-compiler-plugin. |
JavaVersion |
8 | 11 | 17 | Versão java alojada pela aplicação de funções no Azure. |
Os exemplos seguintes mostram as definições do Java 8 nas secções relevantes do ficheiro 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>
Importante
Tem de ter a variável de ambiente JAVA_HOME definida corretamente para o diretório JDK utilizado durante a compilação de código com o Maven. Certifique-se de que a versão do JDK é, pelo menos, tão alta como a Java.version
definição.
Especificar o SO de implementação
O Maven também lhe permite especificar o sistema operativo no qual a sua aplicação de funções é executada no Azure. Utilize o os
elemento para escolher o sistema operativo.
Elemento | Windows | Linux | Docker |
---|---|---|---|
os |
windows |
linux |
docker |
O exemplo seguinte mostra a definição do sistema operativo na runtime
secção do ficheiro de pom.xml:
<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>
Disponibilidade e suporte do runtime do JDK
As compilações Microsoft e Adoptium do OpenJDK são fornecidas e suportadas em Funções para Java 8 (Adoptium), 11 (MSFT) e 17 (MSFT). Estes binários são fornecidos como uma distribuição sem custos, multiplataformas e pronta para produção do OpenJDK para o Azure. Contêm todos os componentes para compilar e executar aplicações Java SE.
Para desenvolvimento ou teste local, pode transferir gratuitamente a compilação da Microsoft dos binários OpenJDK ou Adoptium Temurin . suporte do Azure para problemas com os JDKs e as aplicações de funções está disponível com um plano de suporte qualificado.
Se quiser continuar a utilizar o Zulu para binários do Azure na sua aplicação de Funções, configure a sua aplicação em conformidade. Pode continuar a utilizar os binários Azul para o seu site. No entanto, quaisquer patches ou melhoramentos de segurança só estão disponíveis em novas versões do OpenJDK. Por este motivo, deverá eventualmente remover esta configuração para que as suas aplicações utilizem a versão mais recente disponível do Java.
Personalizar JVM
As funções permitem-lhe personalizar a máquina virtual Java (JVM) utilizada para executar as suas funções Java. As seguintes opções JVM são utilizadas por predefinição:
-XX:+TieredCompilation
-XX:TieredStopAtLevel=1
-noverify
-Djava.net.preferIPv4Stack=true
-jar
Pode fornecer outros argumentos ao JVM através de uma das seguintes definições de aplicação, consoante o tipo de plano:
Tipo de plano | Nome da definição | Comentário |
---|---|---|
Plano de consumo | languageWorkers__java__arguments |
Esta definição aumenta as horas de início frias para as funções Java em execução num plano de Consumo. |
Plano Premium Plano dedicado |
JAVA_OPTS |
As secções seguintes mostram-lhe como adicionar estas definições. Para saber mais sobre como trabalhar com as definições da aplicação, consulte a secção Trabalhar com as definições da aplicação .
Portal do Azure
No portal do Azure, utilize o separador Definições da Aplicação para adicionar a languageWorkers__java__arguments
ou a JAVA_OPTS
definição.
CLI do Azure
Pode utilizar o comando az functionapp config appsettings set para adicionar estas definições, conforme mostrado no exemplo seguinte para a opção -Djava.awt.headless=true
:
az functionapp config appsettings set \
--settings "languageWorkers__java__arguments=-Djava.awt.headless=true" \
--name <APP_NAME> --resource-group <RESOURCE_GROUP>
Este exemplo ativa o modo sem cabeça. Substitua <APP_NAME>
pelo nome da sua aplicação de funções e <RESOURCE_GROUP>
pelo grupo de recursos.
Bibliotecas de terceiros
Funções do Azure suporta a utilização de bibliotecas de terceiros. Por predefinição, todas as dependências especificadas no ficheiro de projeto pom.xml
são automaticamente agrupadas durante o mvn package
objetivo. Para bibliotecas não especificadas como dependências no pom.xml
ficheiro, coloque-as num lib
diretório no diretório de raiz da função. As dependências colocadas no lib
diretório são adicionadas ao carregador de classe do sistema no runtime.
A com.microsoft.azure.functions:azure-functions-java-library
dependência é fornecida no caminho de classe por predefinição e não precisa de ser incluída no lib
diretório. Além disso, azure-functions-java-worker adiciona dependências listadas aqui ao classpath.
Suporte de tipo de dados
Pode utilizar objetos Java antigos simples (POJOs), tipos definidos em azure-functions-java-library
tipos de dados primitivos, como Cadeia e Número Inteiro, para vincular a enlaces de entrada ou saída.
POJOs
Para converter dados de entrada em POJO, azure-functions-java-worker utiliza a biblioteca gson . Os tipos de POJO utilizados como entradas para funções devem ser public
.
Dados binários
Vincular entradas binárias ou saídas a byte[]
, ao definir o dataType
campo em function.json como 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");
}
Se esperar valores nulos, utilize Optional<T>
.
Enlaces
Os enlaces de entrada e saída fornecem uma forma declarativa de ligar aos dados a partir do seu código. Uma função pode ter vários enlaces de entrada e saída.
Exemplo de enlace de entrada
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;
}
}
}
Invoca esta função com um pedido HTTP.
- O payload de pedido HTTP é transmitido como um
String
para o argumentoinputReq
. - Uma entrada é obtida a partir do armazenamento de Tabelas e é transmitida quanto
TestInputData
ao argumentoinputData
.
Para receber um lote de entradas, pode vincular a String[]
, POJO[]
, List<String>
ou 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;
}
Esta função é acionada sempre que existirem novos dados no hub de eventos configurado. Uma vez que o cardinality
está definido como MANY
, a função recebe um lote de mensagens do hub de eventos. EventData
a partir do hub de eventos é convertido para para TestEventData
a execução da função.
Exemplo de enlace de saída
Pode vincular um enlace de saída ao valor devolvido com $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;
}
}
Se existirem vários enlaces de saída, utilize o valor devolvido apenas para um deles.
Para enviar vários valores de saída, utilize OutputBinding<T>
definidos no azure-functions-java-library
pacote.
@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;
}
Invoca esta função num HttpRequest
objeto. Escreve vários valores no Armazenamento de filas.
HttpRequestMessage e HttpResponseMessage
Estes são definidos em azure-functions-java-library
. São tipos auxiliares para trabalhar com funções HttpTrigger.
Tipo especializado | Destino | Utilização típica |
---|---|---|
HttpRequestMessage<T> |
Acionador HTTP | Obtém método, cabeçalhos ou consultas |
HttpResponseMessage |
Enlace de Saída HTTP | Devolve um estado diferente de 200 |
Metadados
Poucos acionadores enviam metadados do acionador juntamente com dados de entrada. Pode utilizar a anotação @BindingName
para vincular para acionar metadados.
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);
}
}
No exemplo anterior, o queryValue
está vinculado ao parâmetro name
da cadeia de consulta no URL do pedido HTTP, http://{example.host}/api/metadata?name=test
. Eis outro exemplo que mostra como vincular aos metadados do acionador Id
de fila.
@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);
}
Nota
O nome indicado na anotação tem de corresponder à propriedade de metadados.
Contexto de execução
ExecutionContext
, definido no azure-functions-java-library
, contém métodos auxiliares para comunicar com o runtime de funções. Para obter mais informações, veja o artigo ExecutionContext reference (Referência executionContext).
Logger
Utilize getLogger
, definido em ExecutionContext
, para escrever registos a partir do código de função.
Exemplo:
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);
}
}
Ver registos e rastreio
Pode utilizar a CLI do Azure para transmitir em fluxo registos de stdout e stderr java e outros registos de aplicações.
Eis como configurar a aplicação de funções para escrever o registo de aplicações com a CLI do Azure:
az webapp log config --name functionname --resource-group myResourceGroup --application-logging true
Para transmitir em fluxo a saída do registo para a sua aplicação de funções com a CLI do Azure, abra uma nova linha de comandos, Bash ou sessão de Terminal e introduza o seguinte comando:
O comando az webapp log tail tem opções para filtrar a saída com a opção --provider
.
Para transferir os ficheiros de registo como um único ficheiro ZIP com a CLI do Azure, abra uma nova linha de comandos, Bash ou sessão de Terminal e introduza o seguinte comando:
az webapp log download --resource-group resourcegroupname --name functionappname
Tem de ter ativado o registo do sistema de ficheiros no portal do Azure ou na CLI do Azure antes de executar este comando.
Variáveis de ambiente
Em Funções, as definições da aplicação, como cadeias de ligação de serviço, são expostas como variáveis de ambiente durante a execução. Pode aceder a estas definições com, System.getenv("AzureWebJobsStorage")
.
O exemplo seguinte obtém a definição da aplicação, com a chave denominada myAppSetting
:
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);
}
}
Passos seguintes
Para obter mais informações sobre Funções do Azure desenvolvimento Java, veja os seguintes recursos:
- Best Practices for Azure Functions (Melhores Práticas para as Funções do Azure)
- Referência para programadores das Funções do Azure
- Funções do Azure acionadores e enlaces
- Desenvolvimento local e depuração com o Visual Studio Code, IntelliJ e Eclipse
- Funções Java de Depuração Remota com o Visual Studio Code
- Plug-in do Maven para Funções do Azure
- Simplifique a criação de funções através do
azure-functions:add
objetivo e prepare um diretório de teste para a implementação de ficheiros ZIP.