AWS Lambda-Funktions-Handler in Java - AWS Lambda

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

AWS Lambda-Funktions-Handler in Java

Der Lambda-Funktionshandler ist die Methode in Ihrem Funktionscode, die Ereignisse verarbeitet. Wenn Ihre Funktion aufgerufen wird, führt Lambda die Handler-Methode aus. Ihre Funktion wird so lange ausgeführt, bis der Handler eine Antwort zurückgibt, beendet wird oder ein Timeout auftritt.

Das GitHub Repo für dieses Handbuch enthält easy-to-deploy Beispielanwendungen, die eine Vielzahl von Handler-Typen demonstrieren. Weitere Informationen finden Sie am Ende dieses Themas.

Beispiel-Handler: Java-17-Laufzeiten

Im folgenden Java-17-Beispiel definiert eine Klasse mit dem Namen HandlerIntegerJava17 eine Handler-Methode mit dem Namen handleRequest. Die Handler-Methode nimmt die folgenden Eingaben auf:

  • Einen IntegerRecord, wobei es sich um einen benutzerdefinierten Java-Datensatz handelt, der Ereignisdaten darstellt. In diesem Beispiel definieren wir IntegerRecord wie folgt:

    record IntegerRecord(int x, int y, String message) { }
  • Ein Kontextobjekt stellt Methoden und Eigenschaften mit Informationen zum Aufruf, zur Funktion und zur Ausführungsumgebung bereit.

Angenommen, wir möchten eine Funktion schreiben, die message aus der Eingabe IntegerRecord protokolliert und die Summe von x und y zurückgibt. Das Folgende ist der Funktionscode:

Beispiel HandlerIntegerJava17.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; // Handler value: example.HandlerInteger public class HandlerIntegerJava17 implements RequestHandler<IntegerRecord, Integer>{ @Override /* * Takes in an InputRecord, which contains two integers and a String. * Logs the String, then returns the sum of the two Integers. */ public Integer handleRequest(IntegerRecord event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("String found: " + event.message()); return event.x() + event.y(); } } record IntegerRecord(int x, int y, String message) { }

Sie geben an, welche Methode Lambda aufrufen soll, indem Sie den Handler-Parameter für die Konfiguration Ihrer Funktion festlegen. Sie können den Hander in den folgenden Formaten ausdrücken:

  • package.Class::method – Vollständiges Format. Beispiel: example.Handler::handleRequest.

  • package.Class – Abgekürztes Format für Funktionen, die eine Handler-Schnittstelle implementieren. Zum Beispiel: example.Handler.

Wenn Lambda Ihren Handler aufruft, empfängt die Lambda-Laufzeit ein Ereignis als JSON-formatierte Zeichenfolge und wandelt es in ein Objekt um. Für das vorherige Beispiel könnte ein Beispielereignis wie folgt aussehen:

Beispiel event.json
{ "x": 1, "y": 20, "message": "Hello World!" }

Sie können diese Datei speichern und Ihre Funktion lokal mit dem folgenden AWS Command Line Interface (CLI)-Befehl testen:

aws lambda invoke --function-name function_name --payload file://event.json out.json

Beispiel-Handler: Java-11-Laufzeiten und darunter

Lambda unterstützt Datensätze in der Laufzeit Java 17 und höher In allen Java-Laufzeiten können Sie eine Klasse verwenden, um Ereignisdaten darzustellen. Das folgende Beispiel verwendet eine Liste von Ganzzahlen und ein Kontextobjekt als Eingabe und gibt die Summe aller Ganzzahlen in der Liste zurück.

Beispiel handler.java

Im folgenden Beispiel definiert eine Klasse mit dem Namen Handler eine Handler-Methode mit dem Namen handleRequest. Die Handler-Methode nimmt ein Ereignis- und ein Kontextobjekt als Eingabe an und gibt eine Zeichenfolge zurück.

Beispiel HandlerList.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.List; // Handler value: example.HandlerList public class HandlerList implements RequestHandler<List<Integer>, Integer>{ @Override /* * Takes a list of Integers and returns its sum. */ public Integer handleRequest(List<Integer> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("EVENT TYPE: " + event.getClass().toString()); return event.stream().mapToInt(Integer::intValue).sum(); } }

Weitere Beispiele finden Sie unter Beispiel-Handler-Code.

Initialisierungscode

Lambda führt Ihren statischen Code und den Klassenkonstruktor während der Initialisierungsphase aus, bevor Ihre Funktion zum ersten Mal aufgerufen wird. Ressourcen, die während der Initialisierung erstellt werden, bleiben zwischen Aufrufen im Speicher und können vom Handler tausende Male wiederverwendet werden. Daher können Sie Initialisierungscode außerhalb Ihrer Haupt-Handler-Methode hinzufügen, um Rechenzeit zu sparen und Ressourcen für mehrere Aufrufe wiederzuverwenden.

Im folgenden Beispiel befindet sich der Client-Initialisierungscode außerhalb der Haupt-Handler-Methode. Die Laufzeit initialisiert den Client, bevor die Funktion ihr erstes Ereignis ausführt. Nachfolgende Ereignisse sind viel schneller, da Lambda den Client nicht erneut initialisieren muss.

Beispiel handler.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; import software.amazon.awssdk.services.lambda.LambdaClient; import software.amazon.awssdk.services.lambda.model.GetAccountSettingsResponse; import software.amazon.awssdk.services.lambda.model.LambdaException; // Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String> { private static final LambdaClient lambdaClient = LambdaClient.builder().build(); @Override public String handleRequest(Map<String,String> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("Handler invoked"); GetAccountSettingsResponse response = null; try { response = lambdaClient.getAccountSettings(); } catch(LambdaException e) { logger.log(e.getMessage()); } return response != null ? "Total code size for your account is " + response.accountLimit().totalCodeSize() + " bytes" : "Error"; } }

Auswählen von Ein- und Ausgabetypen

In der Signatur der Handler-Methode geben Sie den Objekttyp an, dem das Ereignis zugeordnet wird. Im vorangegangenen Beispiel deserialisiert die Java-Laufzeitumgebung das Ereignis in einen Typ, der die Map<String,String>-Schnittstelle implementiert. S tring-to-string Maps funktionieren für flache Ereignisse wie die folgenden:

Beispiel Event.json – Wetterdaten
{ "temperatureK": 281, "windKmh": -3, "humidityPct": 0.55, "pressureHPa": 1020 }

Der Wert jedes Feldes muss jedoch eine Zeichenfolge oder eine Zahl sein. Wenn das Ereignis ein Feld mit einem Objekt als Wert enthält, kann es von der Laufzeit nicht deserialisiert werden und gibt einen Fehler zurück.

Wählen Sie einen Eingabetyp aus, der mit den Ereignisdaten arbeitet, die Ihre Funktion verarbeitet. Sie können einen Basistyp, einen generischen Typ oder einen gut definierten Typ verwenden.

Eingabetypen
  • Integer, Long, Double, usw. – Das Ereignis ist eine Zahl ohne zusätzliche Formatierung, zum Beispiel: 3.5. Die Laufzeit wandelt den Wert in ein Objekt des angegebenen Typs um.

  • String – Das Ereignis ist eine JSON-Zeichenfolge mit Anführungszeichen, z. B.: "My string.". Die Laufzeit wandelt den Wert (ohne Anführungszeichen) in ein String-Objekt um.

  • Type, Map<String,Type> usw. – Das Ereignis ist ein JSON-Objekt. Die Laufzeitumgebung deserialisiert sie in ein Objekt des angegebenen Typs oder der angegebenen Schnittstelle.

  • List<Integer>, List<String>, List<Object>, usw. – Das Ereignis ist ein JSON-Array. Die Laufzeitumgebung deserialisiert sie in ein Objekt des angegebenen Typs oder der angegebenen Schnittstelle.

  • InputStream – Das Ereignis ist ein beliebiger JSON-Typ. Die Laufzeit übergibt einen Bytestream des Dokuments ohne Änderung an den Handler. Sie deserialisieren die Eingabe und schreiben Ausgabe in einen Ausgabestream.

  • Bibliothekstyp – Verwenden Sie für Ereignisse, die von -AWSServices gesendet werden, die Typen in der aws-lambda-java-events Bibliothek.

Wenn Sie Ihren eigenen Eingabetyp definieren, sollte es sich um ein deserialisierbares, veränderbares einfaches altes Java-Objekt (POJO) mit einem Standardkonstruktor und Eigenschaften für jedes Feld im Ereignis handeln. Schlüssel für das Ereignis, die nicht einer Eigenschaft zugeordnet werden, sowie Eigenschaften, die nicht im Ereignis enthalten sind, werden fehlerfrei gelöscht.

Der Ausgabetyp kann ein Objekt oder sei void. Die Laufzeit serialisiert Rückgabewerte in Text. Wenn es sich bei der Ausgabe um ein Objekt mit Feldern handelt, wird dies von der Laufzeitumgebung in ein JSON-Dokument serialisiert. Wenn es sich um einen Typ handelt, der einen primitiven Wert umschließt, gibt die Laufzeit eine Textdarstellung dieses Wertes zurück.

Handler-Schnittstellen

Die aws-lambda-java-core-Bibliothek definiert zwei Schnittstellen für Handler-Methoden. Verwenden Sie die bereitgestellten Schnittstellen, um die Handler-Konfiguration zu vereinfachen und die Handler-Methodensignatur zur Kompilierzeit zu validieren.

Die RequestHandler-Schnittstelle ist ein generischer Typ, der zwei Parameter verwendet: den Eingabetyp und den Ausgabetyp. Beide Typen müssen Objekte sein. Wenn Sie diese Schnittstelle verwenden, deserialisiert die Java-Laufzeitumgebung das Ereignis in ein Objekt mit dem Eingabetyp und serialisiert die Ausgabe in Text. Verwenden Sie diese Schnittstelle, wenn die integrierte Serialisierung mit Ihren Ein- und Ausgabetypen funktioniert.

Beispiel Handler.java – Handler-Schnittstelle
// Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String>{ @Override public String handleRequest(Map<String,String> event, Context context)

Um Ihre eigene Serialisierung zu verwenden, implementieren Sie die RequestStreamHandler-Schnittstelle. Mit dieser Schnittstelle übergibt Lamda Ihrem Handler einen Eingabestream und einen Ausgabestream. Der Handler liest Bytes aus dem Eingabestream, schreibt in den Ausgabestream und gibt „void“ zurück.

Im folgenden Beispiel werden gepufferte Lese- und Schreibtypen verwendet, um mit den Eingabe- und Ausgabestreams zu arbeiten.

Beispiel HandlerStream.java
import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.LambdaLogger import com.amazonaws.services.lambda.runtime.RequestStreamHandler ... // Handler value: example.HandlerStream public class HandlerStream implements RequestStreamHandler { @Override /* * Takes an InputStream and an OutputStream. Reads from the InputStream, * and copies all characters to the OutputStream. */ public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { LambdaLogger logger = context.getLogger(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("US-ASCII"))); PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, Charset.forName("US-ASCII")))); int nextChar; try { while ((nextChar = reader.read()) != -1) { outputStream.write(nextChar); } } catch (IOException e) { e.printStackTrace(); } finally { reader.close(); String finalString = writer.toString(); logger.log("Final string result: " + finalString); writer.close(); } } }

Beispiel-Handler-Code

Das GitHub Repository für dieses Handbuch enthält Beispielanwendungen, die die Verwendung verschiedener Handler-Typen und Schnittstellen demonstrieren. Jede Beispielanwendung enthält Skripts für die einfache Bereitstellung und Bereinigung, eine AWS SAM-Vorlage und unterstützende Ressourcen.

Lambda-Beispielanwendungen in Java
  • java17-examples – Eine Java-Funktion, die demonstriert, wie ein Java-Datensatz verwendet wird, um ein Eingabeereignis-Datenobjekt darzustellen.

  • Java-Basis – Eine Sammlung minimaler Java-Funktionen mit Einheitentests und variabler Protokollierungskonfiguration.

  • Java-Ereignisse – Eine Sammlung von Java-Funktionen, die Grundcode für den Umgang mit Ereignissen aus verschiedenen Services wie Amazon API Gateway, Amazon SQS und Amazon Kinesis enthalten. Diese Funktionen verwenden die neueste Version der aws-lambda-java-events Bibliothek (3.0.0 und neuer). Für diese Beispiele ist das AWS SDK nicht als Abhängigkeit erforderlich.

  • s3-java – Eine Java-Funktion die Benachrichtigungsereignisse aus Amazon S3 verarbeitet und die Java Class Library (JCL) verwendet, um Miniaturansichten aus hochgeladenen Image-Dateien zu erstellen.

  • Verwenden von API Gateway zum Aufrufen einer Lambda-Funktion – Eine Java-Funktion, die eine Amazon-DynamoDB-Tabelle durchsucht, die Mitarbeiterinformationen enthält. Anschließend verwendet es Amazon Simple Notification Service, um eine Textnachricht an Mitarbeiter zu senden, die ihr Betriebsjubiläum feiern. In diesem Beispiel wird API Gateway verwendet, um die Funktion aufzurufen.

Die Anwendungen java-events und s3-java nehmen ein AWS-Service-Ereignis als Eingabe an und geben eine Zeichenfolge zurück. Die java-basic-Anwendung umfasst verschiedene Arten von Handlern:

Um verschiedene Handler-Typen zu testen, ändern Sie einfach den Handler-Wert in der AWS SAM-Vorlage. Ausführliche Anweisungen finden Sie in der Liesmich-Datei der Beispielanwendung.