

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 在 Java 中定義 Lambda 函數處理常式
<a name="java-handler"></a>

Lambda 函數*處理常式*是您的函數程式碼中處理事件的方法。當有人呼叫您的函數時，Lambda 會執行處理常式方法。函數會執行，直到處理常式傳回回應、結束或逾時為止。

本頁介紹了如何在 Java 中使用 Lambda 函式處理常式，包括專案設定選項、命名慣例及最佳實務。本頁還提供了一個 Java Lambda 函式範例，該函式會取得訂單的相關資訊、產生文字檔案收據，並將該檔案放入 Amazon Simple Storage Service (Amazon S3) 儲存貯體。如需編寫函數後如何部署函數的詳細資訊，請參閱[使用 .zip 或 JAR 封存檔部署 Java Lambda 函數](java-package.md)或[使用容器映像部署 Java Lambda 函數](java-image.md)。

**Topics**
+ [設定 Java 處理常式專案](#java-handler-setup)
+ [Java Lambda 函式程式碼範例](#java-example-code)
+ [Java 處理常式的有效類別定義](#java-handler-signatures)
+ [處理常式命名慣例](#java-example-naming)
+ [定義和存取輸入事件物件](#java-handler-input)
+ [存取和使用 Lambda 內容物件](#java-example-context)
+ [在處理常式中使用適用於 Java v2 的 AWS SDK](#java-example-sdk-usage)
+ [存取環境變數](#java-example-envvars)
+ [使用全域狀態](#java-handler-state)
+ [Java Lambda 函數的程式碼最佳實務](#java-best-practices)

## 設定 Java 處理常式專案
<a name="java-handler-setup"></a>

使用 Java 開發 Lambda 函式時，流程涉及編寫程式碼、編譯程式碼，以及將編譯後的成品部署至 Lambda。可以透過各種方式初始化 Java Lambda 專案。例如，您可以使用下列工具：[適用於 Lambda 函式的 Maven Archetype](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda)、AWS SAM CLI 的[ sam init 命令](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-init.html)，甚或在偏好的 IDE (例如 IntelliJ IDEA 或 Visual Studio Code) 中建立標準 Java 專案設定。或者，您可以手動建立所需的檔案結構。

一個典型的 Java Lambda 函式專案遵循以下一般結構：

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

可以使用 Maven 或 Gradle 建置專案並管理相依項。

函式的主要處理常式邏輯位於 `src/main/java/example` 目錄下的 Java 檔案中。在此頁面上的範例中，我們將該檔案命名為 `OrderHandler.java`。除了該檔案外，您亦可視需要納入其他 Java 類別。將函式部署至 Lambda 時，請務必指定包含 Lambda 在調用期間應調用的主要處理常式方法的 Java 類別。

## Java Lambda 函式程式碼範例
<a name="java-example-code"></a>

以下 Java 21 Lambda 函式程式碼範例會取得訂單的相關資訊、產生文字檔案收據，並將該檔案放入 Amazon S3 儲存貯體。

**Example `OrderHandler.java` Lambda 函數**  

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

此 `OrderHandler.java` 檔案包含以下程式碼區段：
+ `package example`：在 Java 中，此套件名稱可自訂，但必須與專案的目錄結構相符。本處採用 `package example`，原因在於目錄結構為 `src/main/java/example`。
+ `import` 陳述式：用於匯入 Lambda 函式所需的 Java 類別。
+ `public class OrderHandler ...`：此程式碼會定義您的 Java 類別，且必須為[有效的類別定義](#java-handler-signatures)。
+ `private static final S3Client S3_CLIENT ...`：此程式碼在類別的所有方法外部初始化 S3 用戶端。這會使 Lambda 在[初始化階段](lambda-runtime-environment.md#runtimes-lifecycle-ib)執行此程式碼。
+ `public record Order ...`：在此自訂 Java [記錄](https://openjdk.org/jeps/395)中定義預期輸入事件的結構。
+ `public String handleRequest(Order event, Context context)`：這是**主要處理常式方法**，其中包含應用程式的主要邏輯。
+ `private void uploadReceiptToS3(...) {}`：這是主要 `handleRequest` 處理常式方法所參考的協助程式方法。

### build.gradle 與 pom.xml 檔案範例
<a name="java-gradle-maven-example"></a>

此函式附帶下列 `build.gradle` 或 `pom.xml` 檔案。

------
#### [ 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>
```

------

若要讓此函式正常運作，其[執行角色](lambda-intro-execution-role.md)必須允許 `s3:PutObject` 動作。此外，請確保定義 `RECEIPT_BUCKET` 環境變數。成功調用後，Amazon S3 儲存貯體應包含收據檔案。

**注意**  
此函式可能需要額外的組態設定，才能順利執行而不發生逾時。建議設定 256 MB 記憶體以及 10 秒逾時。首次調用可能因[冷啟動](lambda-runtime-environment.md#cold-start-latency)而耗費更長時間。後續調用因執行環境可重複使用，執行速度會大幅提升。

## Java 處理常式的有效類別定義
<a name="java-handler-signatures"></a>

為了定義類別，[aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) 程式庫定義了處理常式方法的兩個介面。透過使用這些預設介面，可簡化處理常式的設定流程，並在編譯階段驗證方法簽章。
+ [ 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)

`RequestHandler` 介面是一個一般類型，它有兩個參數：輸入類型和輸出類型。兩種類型都必須是物件。在此範例中，`OrderHandler` 類別會實作 `RequestHandler<OrderHandler.Order, String>`。輸入類型是我們在類別中定義的 `Order` 記錄，輸出類型是 `String`。

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

當您使用此介面時，Java 執行時期會將事件反序列化為具有輸入類型的物件，並將輸出序列化為文字。當內建序列化與您的輸入和輸出類型一同作業時，請使用此介面。

若要使用自訂序列化，您可以實作 `RequestStreamHandler` 介面。透過此介面，Lambda 會將處理常式傳遞給一個輸入串流和輸出串流。處理常式會從輸入串流讀取位元組，寫入到輸出串流，並傳回 void 值。如需使用 Java 21 執行時期的實作範例，請參閱 [ HandlerStream.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/main/java/example/HandlerStream.java)。

若您的 Java 函式僅使用基本類型與泛型類型 (即 `String`、`Integer`、`List` 或 `Map`)，則無需實作介面。例如，若函式接收一個 `Map<String, String>` 輸入並傳回 `String`，則類別定義和處理常式簽章可能如下所示：

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

此外，如果未實作介面，則[內容](java-context.md)物件是選用項目。例如，類別定義和處理常式簽章可能如下所示：

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

## 處理常式命名慣例
<a name="java-example-naming"></a>

對於 Java 中的 Lambda 函式，如果您實作 `RequestHandler` 或 `RequestStreamHandler` 介面，則主要處理常式方法必須命名為 `handleRequest`。此外，請在 `handleRequest` 方法上方加上 `@Override` 標籤。將函式部署到 Lambda 時，請以下列格式在函式的組態中指定主要處理常式：
+ *<package>*.*<Class>* – 例如 `example.OrderHandler`。

對於 Java 中未實作 `RequestHandler` 或 `RequestStreamHandler` 介面的 Lambda 函式，您可以將處理常式命名為任何名稱。將函式部署到 Lambda 時，請以下列格式在函式的組態中指定主要處理常式：
+ *<package>*.*<Class>*::*<handler\$1method\$1name>* – 例如 `example.Handler::mainHandler`。

## 定義和存取輸入事件物件
<a name="java-handler-input"></a>

JSON 是 Lambda 函數最常見的標準輸入格式。在此範例中，函數預期輸入類似以下內容：

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

使用 Java 17 或更新版本開發 Lambda 函式時，可將預期輸入事件的結構定義為 Java 記錄。在此範例中，我們定義了 `OrderHandler` 類別中的一條記錄來代表 `Order` 物件：

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

該記錄符合預期的輸入結構。定義記錄之後，您即可編寫處理常式簽章，其會接收符合該記錄定義的 JSON 輸入。Java 執行時期會自動將此 JSON 反序列化為 Java 物件。然後，您可以存取該物件的欄位。例如，使用 `orderId` 可以從原始輸入擷取 `event.orderId` 的值。

**注意**  
僅 Java 17 及更新版本的執行時期支援 Java 記錄功能。在所有 Java 執行期中，可以使用類別來表示事件資料。在此類案例中，您可以使用 [jackson](https://github.com/FasterXML/jackson) 之類的程式庫來反序列化 JSON 輸入。

### 其他輸入事件類型
<a name="java-input-event-types"></a>

Java 中的 Lambda 函式支援多種可能的輸入事件：
+ `Integer` `Long`、`Double`、等等 - 事件是沒有其他格式的數字，例如 `3.5`。Java 執行時期會將值轉換為指定類型的物件。
+ `String` - 事件是 JSON 字串，包括引號，例如 。`“My string”`執行時期會將值轉換為不含引號的 `String` 物件。
+ `List<Integer>` `List<String>`、`List<Object>`、等等 - 該事件是一個 JSON 陣列。執行階段會將它還原序列化為指定類型或介面的物件。
+ `InputStream` - 該事件是任何 JSON 類型。執行階段會將文件的位元組串流傳遞給處理常式而不進行修改。您還原序列化輸入和並將輸出寫入輸出串流。
+ 程式庫類型 – 對於由其他 AWS 服務傳送的事件，請使用 [aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events) 程式庫中的類型。例如，若 Amazon Simple Queue Service (SQS) 調用您的 Lambda 函式，則以 `SQSEvent` 物件作為輸入。

## 存取和使用 Lambda 內容物件
<a name="java-example-context"></a>

Lambda [內容物件](java-context.md) 包含有關調用、函數以及執行環境的資訊。在此範例中，內容物件的類型為 `com.amazonaws.services.lambda.runtime.Context`，並且內容物件也是主要處理常式函式的第二個引數。

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

如果您的類別實作了 [ 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) 或 [ 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) 介面，則內容物件為必要引數。否則，內容物件為選用引數。如需有關可接受的有效處理常式簽章的詳細資訊，請參閱 [Java 處理常式的有效類別定義](#java-handler-signatures)。

如果您使用 AWS SDK 呼叫其他服務，則有幾個關鍵區域需要內容物件。例如，若要為 Amazon CloudWatch 生成函式日誌，您可以使用 `context.getLogger()` 方法取得用於記錄的 `LambdaLogger` 物件。在此範例中，如果處理因任何原因失敗，我們可以使用記錄器來記錄錯誤訊息：

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

除了記錄日誌之外，您還可以將內容物件用於函式監控。如需內容物件的詳細資訊，請參閱[使用 Lambda 內容物件擷取 Java 函數資訊](java-context.md)。

## 在處理常式中使用適用於 Java v2 的 AWS SDK
<a name="java-example-sdk-usage"></a>

通常，您會使用 Lambda 函式與其他 AWS 資源互動或對其進行更新。與這些資源互動的最簡單方法便是使用適用於 Java v2 的 AWS SDK。

**注意**  
適用於 Java (v1) 的 AWS SDK 目前處於維護模式，將於 2025 年 12 月 31 日停止支援。建議今後僅使用適用於 Java v2 的 AWS SDK。

若要將 SDK 相依項新增至函式，請在適用於 Gradle 的 `build.gradle` 檔案或適用於 Maven 的 `pom.xml` 檔案中納入這些相依項。建議僅新增函式所需的程式庫。在先前的範例程式碼中，我們使用了 `software.amazon.awssdk.services.s3` 程式庫。在 Gradle 中，您可以透過在 `build.gradle` 的相依項區段中新增以下一行程式碼來新增此相依項：

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

在 Maven 中，在 `pom.xml` 的 `<dependencies>` 區段中新增以下程式碼行：

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

**注意**  
SDK 可能不是最新版本。請為應用程式選擇適當的 SDK 版本。

然後，直接在 Java 類別中匯入相依項：

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

隨後，範例程式碼會初始化 Amazon S3 用戶端，如下所示：

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

在此範例中，我們在主要處理常式函式外部初始化 Amazon S3 用戶端，以免每次調用函式時都必須初始化該用戶端。初始化 SDK 用戶端之後，您即可用其與其他 AWS 服務互動。此範例程式碼會呼叫 Amazon S3 `PutObject` API，如下所示：

```
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)));
```

## 存取環境變數
<a name="java-example-envvars"></a>

在處理常式程式碼中，您可以使用 `System.getenv()` 方法來引用任何[環境變數](configuration-envvars.md)。在此範例中，我們使用以下程式碼來參考定義的 `RECEIPT_BUCKET` 環境變數：

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

## 使用全域狀態
<a name="java-handler-state"></a>

在首次調用函數之前，Lambda 會在[初始化階段](lambda-runtime-environment.md#runtimes-lifecycle-ib)執行靜態程式碼和類別建構函數。在初始化期間建立的資源會在調用間隔期間保留在記憶體中，無需您在每次調用函式時都建立這些資源。

在範例程式碼中，S3 用戶端初始化程式碼位於主要處理常式方法外部。執行時期會在函式處理第一個事件之前初始化用戶端，且用戶端在所有調用中均可供重複使用。

## Java Lambda 函數的程式碼最佳實務
<a name="java-best-practices"></a>

請遵循下列清單中的準則，在建置 Lambda 函數時使用最佳編碼實務：
+ **區隔 Lambda 處理常式與您的核心邏輯。**能允許您製作更多可測單位的函式。
+ **控制函數部署套件內的相依性。**AWS Lambda 執行環境包含多個程式庫。若要啟用最新的一組功能與安全更新，Lambda 會定期更新這些程式庫。這些更新可能會為您的 Lambda 函數行為帶來細微的變更。若要完全掌控您函式所使用的相依性，請利用部署套件封裝您的所有相依性。
+ **最小化依存項目的複雜性。**偏好更簡易的框架，其可快速在[執行環境](lambda-runtime-environment.md)啟動時載入。例如，偏好更簡易的 Java 相依性置入 (IoC) 架構如 [Dagger](https://google.github.io/dagger/) 或 [Guice](https://github.com/google/guice)，勝於複雜的架構如 [Spring Framework](https://github.com/spring-projects/spring-framework)。
+ **將部署套件最小化至執行時期所必要的套件大小。**這能減少您的部署套件被下載與呼叫前解壓縮的時間。對於以 Java 撰寫的函數，請避免上傳整個 AWS SDK 程式庫做為部署套件的一部分。或者，選擇性倚賴取得您需要的軟體開發套件元件的模組 (例如 DynamoDB、Amazon S3 開發套件模組，以及 [Lambda 核心程式庫](https://github.com/aws/aws-lambda-java-libs))。

**請利用執行環境重新使用來改看函式的效能。**在函式處理常式之外初始化 SDK 用戶端和資料庫連線，並在本機快取 `/tmp` 目錄中的靜態資產。由您函式的相同執行個體處理的後續叫用可以重複使用這些資源。這可藉由減少函數執行時間來節省成本。

若要避免叫用間洩漏潛在資料，請不要使用執行環境來儲存使用者資料、事件，或其他牽涉安全性的資訊。如果您的函式依賴無法存放在處理常式內記憶體中的可變狀態，請考慮為每個使用者建立個別函式或個別函式版本。

**使用 Keep-Alive 指令維持持續連線的狀態。**Lambda 會隨著時間的推移清除閒置連線。叫用函數時嘗試重複使用閒置連線將導致連線錯誤。若要維護持續連線，請使用與執行階段相關聯的 keep-alive (保持啟用) 指令。如需範例，請參閱[在 Node.js 中重複使用 Keep-Alive 的連線](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)。

**使用[環境變數](configuration-envvars.md)將操作參數傳遞給您的函數。**例如，如果您正在寫入到 Amazon S3 儲存貯體，而非對您正在寫入的儲存貯體名稱進行硬式編碼，請將儲存貯體名稱設定為環境變數。

**避免在 Lambda 函數中使用遞迴調用**，其中函數會調用自己或啟動可能再次調用函數的程序。這會導致意外的函式呼叫量與升高的成本。若您看到意外的調用數量，當更新程式碼時，請立刻將函數的預留並行設為 `0`，以調節對函數的所有調用。

**請勿在您的 Lambda 函數程式碼中使用未記錄的非公有 API**。對於 AWS Lambda 受管執行時間，Lambda 會定期將安全性和函數更新套用至 Lambda 的內部 API。這些內部 API 更新可能是向後不相容的，這會導致意外結果，例如若您的函數依賴於這些非公有 API，則叫用失敗。請參閱 [API 參考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)查看公開可用 API 的清單。

**撰寫等冪程式碼。**為函數撰寫等冪程式碼可確保採用相同方式來處理重複事件。程式碼應正確驗證事件並正常處理重複的事件。如需詳細資訊，請參閱 [How do I make my Lambda function idempotent?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/) (如何讓 Lambda 函數等冪？)。
+ **避免使用 Java DNS 快取。**Lambda 函數已快取 DNS 回應。如果您使用其他 DNS 快取，則可能會發生連線逾時。

  `java.util.logging.Logger` 類別可以間接啟用 JVM DNS 快取。若要覆寫預設設定，請先將 [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) 設定為 0，再初始化 `logger`。範例：

  ```
  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);
  }
  ```
+ 將相依性 `.jar` 檔案置於不同的 /lib 目錄，**縮短 Lambda 解壓縮以 Java 撰寫之部署套件的時間**。這比將您所有函式程式碼全部放入具大量 `.class` 檔案的單一 jar 更快速。如需說明，請參閱 [使用 .zip 或 JAR 封存檔部署 Java Lambda 函數](java-package.md)。