

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.

# Definieren des Lambda-Funktions-Handlers in Java
<a name="java-handler"></a>

Der Lambda-Funktions*handler* 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.

Auf dieser Seite wird beschrieben, wie Sie mit Lambda-Funktions-Handlern in Java arbeiten, einschließlich Optionen für die Projekteinrichtung, Benennungskonventionen und Best Practices. Diese Seite enthält auch ein Beispiel für eine Java-Lambda-Funktion, die Informationen über einen Auftrag aufnimmt, eine Textdatei als Quittung erstellt und diese Datei in einem Bucket von Amazon Simple Storage Service (Amazon S3) platziert. Informationen darüber, wie Sie Ihre Funktion nach dem Schreiben einsetzen können, finden Sie unter [Bereitstellen von Java-Lambda-Funktionen mit ZIP- oder JAR-Dateiarchiven](java-package.md) oder [Bereitstellen von Java-Lambda-Funktionen mit Container-Images](java-image.md).

**Topics**
+ [Einrichten Ihres Java-Handler-Projekts](#java-handler-setup)
+ [Beispiel für Java-Lambda-Funktionscode](#java-example-code)
+ [Gültige Klassendefinitionen für Java-Handler](#java-handler-signatures)
+ [Namenskonventionen für Handler](#java-example-naming)
+ [Definieren Sie das Eingabeereignisobjekt und greifen Sie darauf zu](#java-handler-input)
+ [Zugreifen auf und Verwenden des Lambda-Kontextobjekts](#java-example-context)
+ [Verwenden des AWS SDK für Java v2 in Ihrem Handler](#java-example-sdk-usage)
+ [Zugriff auf Umgebungsvariablen](#java-example-envvars)
+ [Verwenden des globalen Zustands](#java-handler-state)
+ [Bewährte Codemethoden für Java-Lambda-Funktionen](#java-best-practices)

## Einrichten Ihres Java-Handler-Projekts
<a name="java-handler-setup"></a>

Wenn Sie mit Lambda-Funktionen in Java arbeiten, umfasst der Prozess das Schreiben Ihres Codes, das Kompilieren und das Bereitstellen der kompilierten Artefakte in Lambda. Sie können ein Java-Lambda-Projekt auf verschiedene Arten initialisieren. Sie können beispielsweise Tools wie [Maven Archetype für Lambda-Funktionen](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda), den AWS SAM-CLI-Befehl [sam init](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-init.html) oder sogar eine Standard-Java-Projekteinrichtung in Ihrer bevorzugten IDE wie IntelliJ IDEA oder Visual Studio Code verwenden. Alternativ können Sie die erforderliche Dateistruktur manuell erstellen.

Ein typisches Java-Lambda-Funktionsprojekt folgt dieser allgemeinen Struktur:

```
/project-root
    └ src
        └ main
            └ java
                └ example
                    └ OrderHandler.java (contains main handler)
                    └ <other_supporting_classes>
     └ build.gradle OR pom.xml
```

Sie können entweder Maven oder Gradle verwenden, um Ihr Projekt zu erstellen und Abhängigkeiten zu verwalten.

Die Haupthandler-Logik für Ihre Funktion befindet sich in einer Java-Datei im Verzeichnis `src/main/java/example`. Im Beispiel auf dieser Seite nennen wir diese Datei `OrderHandler.java`. Neben dieser Datei können Sie bei Bedarf weitere Java-Klassen hinzufügen. Achten Sie beim Bereitstellen Ihrer Funktion in Lambda darauf, die Java-Klasse anzugeben, die die Haupthandler-Methode enthält, die Lambda bei einem Aufruf ausführen soll.

## Beispiel für Java-Lambda-Funktionscode
<a name="java-example-code"></a>

Das folgende Beispiel für einen Java 21-Lambda-Funktionscode nimmt Informationen über eine Bestellung auf, erstellt eine Textdateiquittung und platziert diese Datei in einem Amazon-S3-Bucket.

**Example `OrderHandler.java`-Lambda-Funktion**  

```
package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.nio.charset.StandardCharsets;

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {

    private static final S3Client S3_CLIENT = S3Client.builder().build();

    /**
     * Record to model the input event.
     */
    public record Order(String orderId, double amount, String item) {}

    @Override
    public String handleRequest(Order event, Context context) {
        try {
            // Access environment variables
            String bucketName = System.getenv("RECEIPT_BUCKET");
            if (bucketName == null || bucketName.isEmpty()) {
                throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
            }

            // Create the receipt content and key destination
            String receiptContent = String.format("OrderID: %s\nAmount: $%.2f\nItem: %s",
                    event.orderId(), event.amount(), event.item());
            String key = "receipts/" + event.orderId() + ".txt";

            // Upload the receipt to S3
            uploadReceiptToS3(bucketName, key, receiptContent);

            context.getLogger().log("Successfully processed order " + event.orderId() +
                    " and stored receipt in S3 bucket " + bucketName);
            return "Success";

        } catch (Exception e) {
            context.getLogger().log("Failed to process order: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private void uploadReceiptToS3(String bucketName, String key, String receiptContent) {
        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();

            // Convert the receipt content to bytes and upload to S3
            S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
        } catch (S3Exception e) {
            throw new RuntimeException("Failed to upload receipt to S3: " + e.awsErrorDetails().errorMessage(), e);
        }
    }
}
```

Diese `OrderHandler.java`-Datei enthält die folgenden Abschnitte des Codes:
+ `package example`: In Java kann dies beliebig sein, muss jedoch mit der Verzeichnisstruktur Ihres Projekts übereinstimmen. Hier verwenden wir `package example`, da die Verzeichnisstruktur `src/main/java/example` lautet.
+ `import`-Anweisungen: Damit können Sie Java-Klassen importieren, die für Ihre Lambda-Funktion erforderlich sind.
+ `public class OrderHandler ...`: Dies definiert Ihre Java-Klasse und muss eine [gültige Klassendefinition](#java-handler-signatures) sein.
+ `private static final S3Client S3_CLIENT ...`: Dadurch wird ein S3-Client außerhalb einer der Methoden der Klasse initialisiert. Dies veranlasst Lambda, diesen Code während der [Initialisierungsphase](lambda-runtime-environment.md#runtimes-lifecycle-ib) auszuführen.
+ `public record Order ...`: Definieren Sie die Form des erwarteten Eingabeereignisses in diesem benutzerdefinierten Java-[Datensatz](https://openjdk.org/jeps/395).
+ `public String handleRequest(Order event, Context context)`: Dies ist die **Haupthandler-Methode**, die Ihre Hauptanwendungslogik enthält.
+ `private void uploadReceiptToS3(...) {}`: Dies ist eine Hilfsmethode, auf die von der `handleRequest`-Haupthandler-Methode verwiesen wird.

### Beispieldateien „build.gradle“ und „pom.xml“
<a name="java-gradle-maven-example"></a>

Die folgende `build.gradle`- oder `pom.xml`-Datei gehört zu dieser Funktion.

------
#### [ build.gradle ]

```
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
    implementation 'software.amazon.awssdk:s3:2.28.29'
    implementation 'org.slf4j:slf4j-nop:2.0.16'
}

task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
    }
}

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

build.dependsOn buildZip
```

------
#### [ pom.xml ]

```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-java</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>example-java-function</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
            <version>2.28.29</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>2.0.16</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.4.1</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*</exclude>
                                <exclude>META-INF/versions/**</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>21</release>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

------

Damit diese Funktion ordnungsgemäß funktioniert, muss ihre [Ausführungsrolle](lambda-intro-execution-role.md) die `s3:PutObject`-Aktion zulassen. Stellen Sie außerdem sicher, dass Sie die `RECEIPT_BUCKET`-Umgebungsvariable definieren. Nach einem erfolgreichen Aufruf sollte der Amazon-S3-Bucket eine Empfangsdatei enthalten.

**Anmerkung**  
Diese Funktion erfordert möglicherweise zusätzliche Konfigurationseinstellungen, um ohne Zeitüberschreitung erfolgreich ausgeführt zu werden. Wir empfehlen, 256 MB Arbeitsspeicher und eine Zeitüberschreitung von 10 Sekunden zu konfigurieren. Der erste Aufruf kann aufgrund eines [Kaltstarts](lambda-runtime-environment.md#cold-start-latency) zusätzliche Zeit in Anspruch nehmen. Nachfolgende Aufrufe sollten aufgrund der Wiederverwendung der Ausführungsumgebung wesentlich schneller ausgeführt werden.

## Gültige Klassendefinitionen für Java-Handler
<a name="java-handler-signatures"></a>

Zum Definieren Ihrer Klasse definiert die Bibliothek [aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) zwei Schnittstellen für Handler-Methoden. Verwenden Sie die bereitgestellten Schnittstellen, um die Handler-Konfiguration zu vereinfachen und die Methodensignatur zur Kompilierzeit zu validieren.
+ [ com.amazonaws.services.lambda.runtime.RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java)
+ [ com.amazonaws.services.lambda.runtime.RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java)

Die `RequestHandler`-Schnittstelle ist ein generischer Typ, der zwei Parameter verwendet: den Eingabetyp und den Ausgabetyp. Beide Typen müssen Objekte sein. In diesem Beispiel implementiert unsere `OrderHandler`-Klasse `RequestHandler<OrderHandler.Order, String>`. Der Eingabetyp ist der `Order`-Datensatz, den wir innerhalb der Klasse definieren, und der Ausgabetyp ist `String`.

```
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {
    ...
}
```

Wenn Sie diese Schnittstelle verwenden, deserialisiert die Java-Laufzeit das Ereignis in das Objekt mit dem Eingabetyp und serialisiert die Ausgabe in Text. Verwenden Sie diese Schnittstelle, wenn die integrierte Serialisierung mit Ihren Ein- und Ausgabetypen funktioniert.

Um Ihre eigene Serialisierung zu verwenden, können Sie die `RequestStreamHandler`-Schnittstelle implementieren. 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. Ein Beispiel für die Verwendung der Java 21-Laufzeit finden Sie unter [HandlerStream.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/main/java/example/HandlerStream.java).

Wenn Sie in Ihrer Java-Funktion nur mit grundlegenden und generischen Typen (d. h. `String`, `Integer`, `List` oder `Map`) arbeiten, müssen Sie keine Schnittstelle implementieren. Wenn Ihre Funktion beispielsweise eine `Map<String, String>`-Eingabe akzeptiert und eine `String` zurückgibt, könnten Ihre Klassendefinition und Ihre Handler-Signatur wie folgt aussehen:

```
public class ExampleHandler {
    public String handleRequest(Map<String, String> input, Context context) {
        ...
    }
}
```

Wenn Sie keine Schnittstelle implementieren, ist das [Kontextobjekt](java-context.md) außerdem optional. Ihre Klassendefinition und Ihre Handler-Signatur könnten beispielsweise wie folgt aussehen:

```
public class NoContextHandler {
   public String handleRequest(Map<String, String> input) {
        ...
   }
}
```

## Namenskonventionen für Handler
<a name="java-example-naming"></a>

Wenn Sie für Lambda-Funktionen in Java entweder die `RequestHandler`- oder `RequestStreamHandler`-Schnittstelle implementieren, muss Ihre Haupthandler-Methode `handleRequest` heißen. Fügen Sie außerdem das Tag `@Override` über Ihrer `handleRequest`-Methode ein. Wenn Sie Ihre Funktion in Lambda bereitstellen, geben Sie den Haupthandler in der Konfiguration Ihrer Funktion im folgenden Format an:
+ *<Paket>*.*<Klasse>* – Beispiel: `example.OrderHandler`.

Für Lambda-Funktionen in Java, die nicht die `RequestHandler`- oder `RequestStreamHandler`-Schnittstelle implementieren, können Sie einen beliebigen Namen für den Handler verwenden. Wenn Sie Ihre Funktion in Lambda bereitstellen, geben Sie den Haupthandler in der Konfiguration Ihrer Funktion im folgenden Format an:
+ *<Paket>*.*<Klasse>*::*<Name\$1der\$1Handlermethode>* – Beispiel: `example.Handler::mainHandler`.

## Definieren Sie das Eingabeereignisobjekt und greifen Sie darauf zu
<a name="java-handler-input"></a>

JSON ist das gebräuchlichste und standardmäßigste Eingabeformat für Lambda-Funktionen. In diesem Beispiel erwartet die Funktion eine Eingabe ähnlich der folgenden:

```
{
    "orderId": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

Wenn Sie mit Lambda-Funktionen in Java 17 oder neuer arbeiten, können Sie die Form des erwarteten Eingabeereignisses als Java-Datensatz definieren. In diesem Beispiel definieren wir einen Datensatz innerhalb der `OrderHandler`-Klasse, um ein `Order`-Objekt darzustellen:

```
public record Order(String orderId, double amount, String item) {}
```

Dieser Datensatz entspricht der erwarteten Eingabeform. Nachdem Sie Ihren Datensatz definiert haben, können Sie eine Handler-Signatur schreiben, die eine JSON-Eingabe entgegennimmt, die der Datensatzdefinition entspricht. Die Java-Laufzeit deserialisiert diese JSON-Eingabe automatisch in ein Java-Objekt. Sie können dann auf die Felder des Objekts zugreifen. Zum Beispiel holt `event.orderId` den Wert von `orderId` aus der ursprünglichen Eingabe.

**Anmerkung**  
Java-Datensätze sind nur in Java 17-Laufzeiten und neueren Versionen enthalten. In allen Java-Laufzeiten können Sie eine Klasse verwenden, um Ereignisdaten darzustellen. In solchen Fällen können Sie eine Bibliothek wie [jackson](https://github.com/FasterXML/jackson) verwenden, um JSON-Eingaben zu deserialisieren.

### Andere Typen von Eingabeereignissen
<a name="java-input-event-types"></a>

Es gibt viele mögliche Eingabeereignisse für Lambda-Funktionen in Java:
+ `Integer`, `Long`, `Double`, usw. – Das Ereignis ist eine Zahl ohne zusätzliche Formatierung, zum Beispiel: ., `3.5`. Die Java-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 in ein `String`-Objekt ohne Anführungszeichen um.
+ `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 – Bei Ereignissen, die von anderen AWS-Services gesendet werden, müssen Sie die Typen in der Bibliothek [aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events) verwenden. Wenn Ihre Lambda-Funktion beispielsweise von Amazon Simple Queue Service (SQS) aufgerufen wird, verwenden Sie das `SQSEvent`-Objekt als Eingabe.

## Zugreifen auf und Verwenden des Lambda-Kontextobjekts
<a name="java-example-context"></a>

Das Lambda-[Kontextobjekt](java-context.md) enthält Informationen über Aufruf, Funktion und Ausführungsumgebung. In diesem Beispiel ist das Kontextobjekt vom Typ `com.amazonaws.services.lambda.runtime.Context` und das zweite Argument der Haupthandlerfunktion.

```
public String handleRequest(Order event, Context context) {
    ...
}
```

Wenn Ihre Klasse entweder die [RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java) oder die [RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java)-Schnittstelle implementiert, ist das Kontextobjekt ein erforderliches Argument. Andernfalls ist das Kontextobjekt optional. Weitere Informationen zu gültigen akzeptierten Handlersignaturen finden Sie unter [Gültige Klassendefinitionen für Java-Handler](#java-handler-signatures).

Wenn Sie mit dem AWS-SDK andere Dienste aufrufen, wird das Kontextobjekt in einigen wichtigen Bereichen benötigt. Um beispielsweise Funktionsprotokolle für Amazon CloudWatch zu erstellen, können Sie die `context.getLogger()`-Methode verwenden, um ein `LambdaLogger`-Objekt für die Protokollierung abzurufen. In diesem Beispiel können wir den Logger verwenden, um eine Fehlermeldung zu protokollieren, falls bei der Verarbeitung aus irgendeinem Grund ein Fehler auftritt:

```
context.getLogger().log("Failed to process order: " + e.getMessage());
```

Außerhalb der Protokollierung können Sie das Kontextobjekt auch für die Funktionsüberwachung verwenden. Weitere Informationen über das Kontextobjekt finden Sie unter [Verwenden des Lambda-Kontextobjekts zum Abrufen von Java-Funktionsinformationen](java-context.md).

## Verwenden des AWS SDK für Java v2 in Ihrem Handler
<a name="java-example-sdk-usage"></a>

Oft verwenden Sie Lambda-Funktionen, um mit anderen AWS-Ressourcen zu interagieren oder diese zu aktualisieren. Die einfachste Art, eine Schnittstelle zu diesen Ressourcen herzustellen, ist die Verwendung des AWS SDK für Java v2.

**Anmerkung**  
Das AWS SDK für Java (v1) befindet sich im Wartungsmodus und der Support wird am 31. Dezember 2025 eingestellt. Wir empfehlen, künftig nur noch das AWS SDK für Java v2 zu verwenden.

Um SDK-Abhängigkeiten zu Ihrer Funktion hinzuzufügen, fügen Sie diese in Ihrer `build.gradle`-Datei für Gradle oder der `pom.xml`-Datei für Maven hinzu. Wir empfehlen, nur die Bibliotheken hinzuzufügen, die Sie für Ihre Funktion benötigen. Im Beispielcode zuvor haben wir die Bibliothek `software.amazon.awssdk.services.s3` verwendet. In Gradle können Sie diese Abhängigkeit hinzufügen, indem Sie die folgende Zeile in den Abhängigkeitenabschnitt von `build.gradle` einfügen:

```
implementation 'software.amazon.awssdk:s3:2.28.29'
```

Fügen Sie in Maven die folgenden Zeilen im `<dependencies>`-Abschnitt von `pom.xml` hinzu:

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
        <version>2.28.29</version>
    </dependency>
```

**Anmerkung**  
Dies ist möglicherweise nicht die neueste Version des SDK. Wählen Sie die geeignete SDK-Version für Ihre Anwendung.

Importieren Sie dann die Abhängigkeiten direkt in Ihree Java-Klasse:

```
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
```

Der Beispielcode initialisiert dann einen Amazon-S3-Client wie folgt:

```
private static final S3Client S3_CLIENT = S3Client.builder().build();
```

In diesem Beispiel haben wir unseren Amazon-S3-Client außerhalb der Haupt-Handler-Funktion initialisiert, um zu vermeiden, dass wir ihn bei jedem Aufruf unserer Funktion initialisieren müssen. Nachdem Sie Ihren SDK-Client initialisiert haben, können Sie ihn für die Interaktion mit anderen AWS-Services verwenden. Der Beispielcode ruft die Amazon S3 `PutObject`-API wie folgt auf:

```
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build();

// Convert the receipt content to bytes and upload to S3
S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
```

## Zugriff auf Umgebungsvariablen
<a name="java-example-envvars"></a>

In Ihrem Handler-Code können Sie mithilfe der `System.getenv()`-Methode auf beliebige [Umgebungsvariablen](configuration-envvars.md) verweisen. In diesem Beispiel verweisen wir mit der folgenden Codezeile auf die definierte `RECEIPT_BUCKET`-Umgebungsvariable:

```
String bucketName = System.getenv("RECEIPT_BUCKET");
if (bucketName == null || bucketName.isEmpty()) {
    throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
}
```

## Verwenden des globalen Zustands
<a name="java-handler-state"></a>

Lambda führt Ihren statischen Code und den Klassenkonstruktor während der [Initialisierungsphase](lambda-runtime-environment.md#runtimes-lifecycle-ib) aus, bevor Ihre Funktion zum ersten Mal aufgerufen wird. Ressourcen, die während der Initialisierung erstellt werden, bleiben zwischen Aufrufen im Speicher, sodass Sie sie nicht bei jedem Aufruf Ihrer Funktion neu erstellen müssen.

Im Beispielcode befindet sich der Initialisierungscode des S3-Clients außerhalb der Haupt-Handler-Methode. Die Laufzeit initialisiert den Client, bevor die Funktion ihr erstes Ereignis ausführt, und der Client bleibt für die Wiederverwendung bei allen Aufrufen verfügbar.

## Bewährte Codemethoden für Java-Lambda-Funktionen
<a name="java-best-practices"></a>

Halten Sie sich an die Richtlinien in der folgenden Liste, um beim Erstellen Ihrer Lambda-Funktionen die besten Codierungspraktiken anzuwenden:
+ **Trennen Sie den Lambda-Handler von Ihrer Core-Logik.** Auf diese Weise können Sie eine Funktion zur besseren Prüfbarkeit von Einheiten schaffen.
+ **Kontrollieren Sie die Abhängigkeiten im Bereitstellungspaket Ihrer Funktion. ** Die AWS Lambda-Ausführungsumgebung enthält eine Reihe von Bibliotheken. Um die neuesten Funktionen und Sicherheitsupdates zu aktivieren, wird Lambda diese Bibliotheken regelmäßig aktualisieren. Diese Updates können das Verhalten Ihrer Lambda-Funktion geringfügig verändern. Um die Abhängigkeiten, die Ihre Funktion verwendet, vollständig zu kontrollieren, empfehlen wir, alle Abhängigkeiten mit Ihrem Bereitstellungspaket zu bündeln. 
+ **Minimieren Sie die Komplexität Ihrer Abhängigkeiten.** Ziehen Sie einfachere Frameworks vor, die sich schnell beim Start der [Ausführungsumgebung](lambda-runtime-environment.md) laden lassen. Verwenden Sie beispielsweise einfachere Java Dependency Injection (IoC) Frameworks wie z. B. [Dagger](https://google.github.io/dagger/) or [Guice](https://github.com/google/guice), als komplexere wie [Spring Framework](https://github.com/spring-projects/spring-framework).
+ **Minimieren Sie die Größe Ihres Bereitstellungspakets auf die für die Laufzeit erforderliche Größe. ** Dadurch verkürzt sich die Zeit, die für das Herunterladen und Entpacken Ihres Bereitstellungspakets vor dem Aufruf benötigt wird. Für Funktionen, die in Java erstellt wurden, sollten Sie das Hochladen der gesamten AWS SDK-Bibliothek als Teil Ihres Bereitstellungspakets vermeiden. Stattdessen sollten Sie selektiv von den Modulen ausgehen, die Komponenten des SDK aufnehmen, die Sie benötigen (z. B. DynamoDB, Amazon-S3-SDK-Module und [Lambda-Kernbibliotheken](https://github.com/aws/aws-lambda-java-libs)).

**Nutzen Sie die Wiederverwendung der Ausführungsumgebung zur Verbesserung Ihrer Funktion.** Initialisieren Sie SDK-Clients und Datenbankverbindungen außerhalb des Funktions-Handlers und speichern Sie statische Komponenten lokal im `/tmp`-Verzeichnis. Nachfolgende Aufrufe, die von derselben Instance Ihrer Funktion verarbeitet werden, können diese Ressourcen wiederverwenden. Dies spart Kosten durch Reduzierung der Funktionslaufzeit.

Um potenzielle Datenlecks über Aufrufe hinweg zu vermeiden, verwenden Sie die Ausführungsumgebung nicht, um Benutzerdaten, Ereignisse oder andere Informationen mit Sicherheitsauswirkungen zu speichern. Wenn Ihre Funktion auf einem veränderbaren Zustand beruht, der nicht im Speicher innerhalb des Handlers gespeichert werden kann, sollten Sie für jeden Benutzer eine separate Funktion oder separate Versionen einer Funktion erstellen.

**Verwenden Sie eine Keep-Alive-Direktive, um dauerhafte Verbindungen zu pflegen.** Lambda bereinigt Leerlaufverbindungen im Laufe der Zeit. Der Versuch, eine Leerlaufverbindung beim Aufruf einer Funktion wiederzuverwenden, führt zu einem Verbindungsfehler. Um Ihre persistente Verbindung aufrechtzuerhalten, verwenden Sie die Keep-Alive-Direktive, die Ihrer Laufzeit zugeordnet ist. Ein Beispiel finden Sie unter [Wiederverwenden von Verbindungen mit Keep-Alive in Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html).

**Verwenden Sie [Umgebungsvariablen](configuration-envvars.md) um Betriebsparameter an Ihre Funktion zu übergeben.** Wenn Sie z. B. Daten in einen Amazon-S3-Bucket schreiben, anstatt den Bucket-Namen, in den Sie schreiben, hartzucodieren, konfigurieren Sie den Bucket-Namen als Umgebungsvariable.

**Vermeiden Sie rekursive Aufrufe** in Ihrer Lambda-Funktion, bei denen die Funktion sich selbst aufruft oder einen Prozess initiiert, der die Funktion erneut aufrufen kann. Dies kann zu unvorhergesehenen Mengen an Funktionsaufrufen führen und höhere Kosten zur Folge haben. Wenn Sie eine unbeabsichtigte Menge von Aufrufen feststellen, legen Sie die reservierte gleichzeitige Ausführung der Funktion auf `0` fest, um sofort alle Aufrufe der Funktion zu drosseln, während Sie den Code aktualisieren.

**Verwenden Sie keine nicht dokumentierten, nicht öffentlichen APIs** in Ihrem Lambda-Funktionscode. Für AWS Lambda-verwaltete Laufzeiten wendet Lambda regelmäßig Sicherheits- und Funktionsupdates auf Lambdas interne APIs an. Diese internen API-Updates können abwärtskompatibel sein, was zu unbeabsichtigten Konsequenzen wie Aufruffehlern führt, wenn Ihre Funktion von diesen nicht öffentlichen APIs abhängig ist. Eine Liste öffentlich zugänglicher APIs finden Sie in der [API-Referenz](https://docs.aws.amazon.com/lambda/latest/api/welcome.html).

**Schreiben Sie idempotenten Code.** Das Schreiben idempotenter Code für Ihre Funktionen stellt sicher, dass doppelte Ereignisse auf die gleiche Weise behandelt werden. Ihr Code sollte Ereignisse ordnungsgemäß validieren und doppelte Ereignisse ordnungsgemäß behandeln. Weitere Informationen finden Sie unter [Wie mache ich meine Lambda-Funktion idempotent?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/).
+ **Vermeiden der Verwendung von Java-DNS-Cache.** Lambda-Funktionen speichern DNS-Antworten bereits im Cache. Wenn Sie einen anderen DNS-Cache verwenden, kann es zu Verbindungs-Timeouts kommen.

  Die `java.util.logging.Logger`-Klasse kann indirekt den JVM-DNS-Cache aktivieren. Um die Standardeinstellungen zu überschreiben, setzen Sie [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) auf 0, bevor Sie `logger` initialisieren. Beispiel:

  ```
  public class MyHandler {
    // first set TTL property
    static{
     java.security.Security.setProperty("networkaddress.cache.ttl" , "0");
    }
   // then instantiate logger
    var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class);
  }
  ```
+ **Reduzieren Sie den Zeitaufwand, den Lambda** für das Entpacken von Bereitstellungspaketen benötigt, die in Java erstellt wurden, indem Sie Ihre Abhängigkeitsdateien `.jar` in einem separaten /lib-Verzeichnis ablegen. Dies geht schneller, als den gesamten Code Ihrer Funktion in einem einzigen Jar mit einer großen Anzahl von `.class` Dateien zu speichern. Detaillierte Anweisungen finden Sie unter [Bereitstellen von Java-Lambda-Funktionen mit ZIP- oder JAR-Dateiarchiven](java-package.md).