Spring Cloud-funktion i Azure

Den här artikeln vägleder dig genom att använda Spring Cloud Functions för att utveckla en Java-funktion och publicera den till Azure Functions. När du är klar körs funktionskoden på förbrukningsplanen i Azure och kan utlösas med hjälp av en HTTP-begäran.

Om du inte har en Azure-prenumeration kan du skapa ettkostnadsfritt konto innan du börjar.

Förutsättningar

För att kunna utveckla funktioner med hjälp av Java måste du ha följande installerat:

Viktigt!

  1. Du måste ange JAVA_HOME miljövariabeln till installationsplatsen för JDK för att slutföra den här snabbstarten.
  2. Kontrollera att huvudverktygsversionen är minst 4.0.5455.

Vad vi ska bygga

Vi ska skapa en klassisk "Hello, World"-funktion som körs på Azure Functions och är konfigurerad med Spring Cloud Function.

Funktionen tar emot ett User JSON-objekt som innehåller ett användarnamn och skickar tillbaka ett Greeting objekt som innehåller välkomstmeddelandet till användaren.

Projektet är tillgängligt i Spring Cloud Function i Azure-exempletlagringsplatsen azure-function-java-worker på GitHub. Du kan använda exemplet direkt om du vill se det slutliga arbetet som beskrivs i den här snabbstarten.

Skapa ett nytt Maven-projekt

Vi ska skapa ett tomt Maven-projekt och konfigurera det med Spring Cloud Function och Azure Functions.

I en tom mapp skapar du en ny pom.xml-fil och kopierar/klistrar in innehållet från exempelprojektets pom.xml-fil .

Kommentar

Den här filen använder Maven-beroenden från både Spring Boot och Spring Cloud Function och konfigurerar Maven-pluginen för Spring Boot och Azure Functions.

Du måste anpassa några egenskaper för ditt program:

  • <functionAppName> är namnet på din Azure-funktion
  • <functionAppRegion> är namnet på den Azure-region där din funktion har distribuerats
  • <functionResourceGroup> är namnet på den Azure-resursgrupp som du använder

Ändra dessa egenskaper direkt överst i pom.xml-filen , som du ser i följande exempel:

    <properties>
        <java.version>11</java.version>

        <!-- Spring Boot start class. WARNING: correct class must be set -->
        <start-class>com.example.DemoApplication</start-class>

        <!-- customize those properties. WARNING: the functionAppName should be unique across Azure -->
        <azure.functions.maven.plugin.version>1.29.0</azure.functions.maven.plugin.version>
        <functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
        <functionAppServicePlanName>my-spring-function-service-plan</functionAppServicePlanName>
        <functionAppName>my-spring-function</functionAppName>
        <functionPricingTier>Y1</functionPricingTier>
        <functionAppRegion>eastus</functionAppRegion>
    </properties>

Skapa Azure-konfigurationsfiler

Skapa en src/main/resources-mapp och lägg till följande Azure Functions-konfigurationsfiler i den.

host.json:

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

local.settings.json:

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

Skapa domänobjekt

Azure Functions kan ta emot och skicka objekt i JSON-format. Nu ska vi skapa våra User objekt och Greeting objekt som representerar vår domänmodell. Du kan skapa mer komplexa objekt, med fler egenskaper, om du vill anpassa den här snabbstarten och göra den mer intressant för dig.

Skapa en src/main/java/com/example/model-mapp och lägg följande två filer:

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

Skapa Spring Boot-programmet

Det här programmet hanterar all affärslogik och har åtkomst till hela Spring Boot-ekosystemet. Den här funktionen ger dig två huvudsakliga fördelar jämfört med en Azure-standardfunktion:

  • Den förlitar sig inte på Azure Functions-API:er, så du kan enkelt portera den till andra system. Du kan till exempel återanvända den i ett vanligt Spring Boot-program.
  • Du kan använda alla @Enable anteckningar från Spring Boot för att lägga till nya funktioner.

I src/main/java/com/example-mappen skapar du följande fil som är ett normalt Spring Boot-program:

DemoApplication.java:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Skapa nu följande fil i mappen src/main/java/com/example/hello . Den här koden innehåller en Spring Boot-komponent som representerar den funktion som vi vill köra:

Hello.java:

package com.example.hello;

import com.example.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");
    }
}

Kommentar

Funktionen Hello är ganska specifik:

  • Det är en java.util.function.Function. Den innehåller affärslogik och använder ett Java-standard-API för att omvandla ett objekt till ett annat.
  • Eftersom den har anteckningen @Component är det en Spring Bean och som standard är namnet samma som klassen, men börjar med ett gemener: hello. Att följa den här namngivningskonventionen är viktigt om du vill skapa andra funktioner i ditt program. Namnet måste matcha det Azure Functions-namn som vi skapar i nästa avsnitt.

Skapa Azure-funktionen

För att dra nytta av det fullständiga Azure Functions-API:et kodar vi nu en Azure-funktion som delegerar dess körning till springmolnfunktionen som skapades i föregående steg.

I mappen src/main/java/com/example/hello skapar du följande Azure Function-klassfil:

HelloHandler.java:

package com.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 com.example.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();
    }
}

Den här Java-klassen är en Azure-funktion med följande intressanta funktioner:

  • Klassen har anteckningen @Component , så det är en Spring Bean.
  • Namnet på funktionen, som definieras av kommentaren @FunctionName("hello") , är hello.
  • Klassen implementerar en riktig Azure-funktion så att du kan använda det fullständiga Azure Functions-API:et här.

Lägg till enhetstester

Det här steget är valfritt men rekommenderas för att verifiera att programmet fungerar korrekt.

Skapa en src/test/java/com/example-mapp och lägg till följande JUnit-tester:

HelloTest.java:

package com.example;

import com.example.hello.Hello;
import com.example.model.Greeting;
import com.example.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");
    }
}

Nu kan du testa din Azure-funktion med Maven:

mvn clean test

Kör funktionen lokalt

Innan du distribuerar ditt program till Azure Function ska vi testa det lokalt.

Först måste du paketera ditt program i en Jar-fil:

mvn package

Nu när programmet är paketerat kan du köra det med hjälp av Maven-pluginet azure-functions:

mvn azure-functions:run

Azure-funktionen bör nu vara tillgänglig på din localhost via port 7071. Du kan testa funktionen genom att skicka en POST-begäran med ett User-objekt i JSON-format. Till exempel med cURL:

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

Funktionen ska besvara dig med ett Greeting-objekt, fortfarande i JSON-format:

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

Här är en skärmbild av cURL-begäran överst på skärmen och den lokala Azure-funktionen längst ned:

Azure Function running locally

Felsök funktionen lokalt

I följande avsnitt beskrivs hur du felsöker funktionen.

Felsöka med Intellij IDEA

Öppna projektet i Intellij IDEA och skapa sedan en fjärrkonfiguration för JVM-felsökningskörning som ska kopplas. Mer information finns i Självstudie: Fjärrfelsökning.

Create a Remote JVM Debug run configuration

Kör programmet med följande kommando:

mvn azure-functions:run -DenableDebug

När programmet startar visas följande utdata:

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

Starta projektfelsökning i IntelliJ IDEA. Du ser följande utdata:

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

Markera de brytpunkter som du vill felsöka. Intellij IDEA går in i felsökningsläge när en begäran har skickats.

Felsöka med Visual Studio Code

Öppna projektet i Visual Studio Code och konfigurera sedan följande launch.json-filinnehåll :

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

Kör programmet med följande kommando:

mvn azure-functions:run -DenableDebug

När programmet startar visas följande utdata:

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

Starta projektfelsökning i Visual Studio Code och markera sedan de brytpunkter som du vill felsöka. Visual Studio Code går in i felsökningsläge när en begäran har skickats. Mer information finns i Köra och felsöka Java.

Distribuera funktionen till Azure Functions

Nu ska du publicera Azure-funktionen till produktion. Kom ihåg att egenskaperna <functionAppName>, och som <functionResourceGroup> du har definierat i pom.xml-filen används för <functionAppRegion>att konfigurera funktionen.

Kommentar

Maven-plugin-programmet måste autentiseras med Azure. Om du har Installerat Azure CLI kan du använda az login innan du fortsätter. Fler autentiseringsalternativ finns i Autentiseringlagringsplatsen azure-maven-plugins .

Kör Maven för att distribuera din funktion automatiskt:

mvn azure-functions:deploy

Gå nu till Azure Portal för att hitta Function App som har skapats.

Välj funktionen:

  • I funktionsöversikten noterar du funktionens URL.
  • Om du vill kontrollera funktionen som körs väljer du Logga direktuppspelning på navigeringsmenyn.

Som du gjorde i föregående avsnitt använder du nu cURL för att komma åt funktionen som körs, som du ser i följande exempel. Se till att ersätta your-function-name med ditt riktiga funktionsnamn.

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

Precis som i föregående sektion, ska funktionen svara dig med ett Greeting-objekt, fortfarande i JSON-format:

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

Grattis, du har en Spring Cloud Function som körs på Azure Functions! Mer information och exempel på Spring Cloud-funktioner finns i följande resurser:

Nästa steg

Om du vill veta mer om Spring och Azure kan du fortsätta till dokumentationscentret för Spring i Azure.