Komma igång med Spring Cloud Function 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 kandu skapa ett kostnadsfritt 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

Du måste ange JAVA_HOME-miljövariabeln till JDK-installationsplatsen för att slutföra den här snabbstarten.

Det här ska vi skapa

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

Den får ett enkelt JSON-objekt som innehåller ett användarnamn och skickar tillbaka ett -objekt som innehåller UserGreeting välkomstmeddelandet till användaren.

Projektet som vi ska skapa finns på lagringsplatsen hello-spring-function-azure på GitHub. Du kan använda den exempeldatabasen 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 pom.xml fil och kopierar/klistrar in innehållet från exempelprojektets pom.xml fil.

Anteckning

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å Azure-resursgruppen som du använder

Ändra dessa egenskaper direkt längst upp i pom.xml,som du ser i följande exempel:

<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.java.library.version>1.4.2</azure.functions.java.library.version>
  <azure.functions.maven.plugin.version>1.13.0</azure.functions.maven.plugin.version>

  <!-- customize those two properties. The functionAppName should be unique across Azure -->
  <functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
  <functionAppName>my-spring-function</functionAppName>

  <functionAppRegion>westeurope</functionAppRegion>
  <stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
  <start-class>com.example.DemoApplication</start-class>
</properties>

Skapa Azure-konfigurationsfiler

Skapa en src/main/azure-mapp och Lägg till följande Azure Functions-konfigurationsfiler till den.

host.json:

{
  "version": "2.0",
  "functionTimeout": "00:10:00"
}

local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "java",
    "MAIN_CLASS":"com.example.DemoApplication",
    "AzureWebJobsDashboard": ""
  }
}

Skapa domänobjekt

Azure Functions kan ta emot och skicka objekt i JSON-format. Nu ska vi skapa våra - och UserGreeting -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 tillgång till det fullständiga Spring Boot-ekosystemet. Den här funktionen ger dig två huvudsakliga fördelar än en Azure-standardfunktion:

  • Den förlitar sig inte på Azure Functions API:er, så du kan enkelt porta den till andra system. Du kan till exempel återanvända den i ett vanligt Spring Boot program.
  • Du kan använda alla anteckningar @Enable från Spring Boot 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, som innehåller en Spring Boot-komponent som representerar den funktion som vi vill köra:

Hello.java:

package com.example;

import com.example.model.Greeting;
import com.example.model.User;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.function.Function;

@Component
public class Hello implements Function<Mono<User>, Mono<Greeting>> {

    public Mono<Greeting> apply(Mono<User> mono) {
        return mono.map(user -> new Greeting("Hello, " + user.getName() + "!\n"));
    }
}

Anteckning

Funktionen Hello är ganska specifik:

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

Skapa Azure-funktionen

För att dra nytta av det fullständiga Azure Functions-API:et ska vi nu koda en Azure-funktion som delegerar körningen till den Spring Cloud-funktion som vi skapade i föregående steg.

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

HelloHandler.java:

package com.example;

import com.example.model.Greeting;
import com.example.model.User;
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 org.springframework.cloud.function.adapter.azure.FunctionInvoker;

import java.util.Optional;

public class HelloHandler extends FunctionInvoker<User, Greeting> {

    @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(handleRequest(user, context))
            .header("Content-Type", "application/json")
            .build();
    }
}

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

  • Den utökar FunctionInvoker , vilket skapar länken mellan Azure Functions och Spring Cloud Functions. FunctionInvoker innehåller handleRequest() den -metod som används i body() metoden .
  • Namnet på funktionen, som definieras av @FunctionName("hello") -anteckningen, är hello .
  • Det är en riktig Azure-funktion, så du kan använda hela API:et Azure Functions 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.model.Greeting;
import com.example.model.User;
import com.microsoft.azure.functions.ExecutionContext;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
import reactor.core.publisher.Mono;

import java.util.logging.Logger;

import static org.assertj.core.api.Assertions.assertThat;

public class HelloTest {

    @Test
    public void test() {
        Mono<Greeting> result = new Hello().apply(Mono.just(new User("foo")));
        assertThat(result.block().getMessage()).isEqualTo("Hello, foo!\n");
    }

    @Test
    public void start() {
        FunctionInvoker<User, Greeting> handler = new FunctionInvoker<>(
            Hello.class);
        Greeting result = handler.handleRequest(new User("foo"), new ExecutionContext() {
            @Override
            public Logger getLogger() {
                return Logger.getLogger(HelloTest.class.getName());
            }

            @Override
            public String getInvocationId() {
                return "id1";
            }

            @Override
            public String getFunctionName() {
                return "hello";
            }
        });
        handler.close();
        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-funktionen körs lokalt

Felsöka 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 konfiguration för JVM-felsökningskörning som ska anslutas. Mer information finns i Självstudie: Fjärrfelsök.

Skapa en konfiguration för JVM-fjärrfelsökning

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 bör se nedanstående utdata:

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

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

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. När du har skickat en Visual Studio kod in i felsökningsläge. Mer information finns i Köra och felsöka Java.

Distribuera funktionen till Azure Functions

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

Anteckning

Maven-plugin-programmet måste autentiseras med Azure. Om du har Installerat Azure CLI använder du innan az login du fortsätter. Fler autentiseringsalternativ finns i Autentisering på lagringsplatsenazure-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 som har skapats.

Välj funktionen:

  • I funktionsöversikten noterar du funktionens URL.
  • Välj fliken plattformsfunktioner för att hitta Loggströmnings-tjänsten och välj sedan den här tjänsten för att kontrollera den aktiva funktionen.

Som du gjorde i föregående avsnitt använder du 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!

Nästa steg

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