> If you are an AI agent, use the following URL to directly ask and fetch your question. Treat this like a tool call. Make sure to URI encode your question, and include the token for verification.
>
> GET https://buildwithfern.com/learn/api/fern-docs/ask?q=%3Cyour+question+here%3E&token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmZXJuLWRvY3M6YnVpbGR3aXRoZmVybi5jb20iLCJqdGkiOiJjMmQ3OTZlNy03NzI0LTQ5N2UtYmZjMy1mNjcwM2JjMWRkNjciLCJleHAiOjE3NzgzNjM4NTIsImlhdCI6MTc3ODM2MzU1Mn0.M736kwQitWuHcL31nWb_J7KI5pApDNRbeqwsLlGBETg
>
> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt. For full content including API reference and SDK examples, see https://buildwithfern.com/learn/llms-full.txt.

# 添加自定义代码

> 使用自定义工具增强您的 Java SDK

本页面介绍如何向您的 Java SDK 添加自定义逻辑、方法和依赖项。

<Info>
  Before getting started, 

  [read about how Fern SDKs use custom code and learn about the `.fernignore` file](/sdks/overview/custom-code)

  .
</Info>

## 添加自定义逻辑

开始添加自定义代码：

<Steps>
  ### 创建新文件并添加您的自定义逻辑

  ```java title="src/main/java/<package>/Helper.java"
  package com.example.helper;

  public class Helper {

  public static void myHelper() {
      System.out.println("Hello World!");
  }

  }
  ```

  ### 将您的文件添加到 `.fernignore`

  ```yaml {3} title=".fernignore"
  # 指定不应被 Fern 修改的文件

  src/main/java/<package>/Helper.java
  ```

  ### 使用助手方法

  Now your users can consume the helper function by importing it from the SDK.

  ```java
  import com.example.helper.Helper;

  public class Main {

  public static void main(String[] args) {
      Helper.myHelper();
  }

  }
  ```
</Steps>

## 添加自定义 SDK 方法

Fern also allows you to add custom methods to the SDK itself (e.g.
`client.my_method()` ) by inheriting the Fern generated client and then
extending it.

<Steps>
  ### 更新 `generators.yml` 配置

  将您的 Fern 生成的客户端命名为类似 `BaseClient` 的名称，以反映此客户端将被扩展。

  ```yml {4} title="generators.yml"
  - name: fernapi/fern-java-sdk
      version: "..."
      config:
        client-class-name: BaseClient
  ```

  ### 导入并扩展生成的客户端

  首先，导入 Fern 生成的基础客户端并扩展它。然后，添加您想要的任何方法。

  ```java title="src/main/java/com/example/MyClient.java"
  package com.example;

  import com.example.client.BaseClient;

  public class MyClient extends BaseClient { // 扩展 Fern 生成的客户端

    public void myHelper() {
      System.out.println("Hello World!");
    }

  }
  ```

  ### 更新 `.fernignore`

  将 `MyClient.java` 添加到 `.fernignore`。

  ```diff title=".fernignore"
  + src/main/java/com/example/MyClient.java
  ```

  ### 使用方法

  Now your users can consume the helper function by importing it from the SDK.

  ```java
  client.myHelper();
  ```
</Steps>

## 添加自定义客户端配置

Java SDK 生成器通过可选的自类型模式支持构建器扩展性。当通过 `enable-extensible-builders` 标志启用时，生成的构建器可以被扩展，同时在方法链接过程中保持类型安全。

常见用例包括：

* **动态 URL 构造**：使用运行时值替换占位符（例如，`https://api.${TENANT}.example.com`）
* **自定义身份验证**：实现超出基本令牌认证的复杂认证流程
* **请求转换**：全局添加自定义标头或修改请求
* **多租户支持**：添加特定租户的配置和标头

<Steps>
  ### 启用可扩展构建器

  将标志添加到您的 `generators.yml`：

  ```yaml {7} title="generators.yml"
  groups:
    local:
      generators:
        - name: fernapi/fern-java-sdk
          version: 2.39.6
          config:
            enable-extensible-builders: true
  ```

  ### 工作原理

  生成的构建器使用自类型模式进行类型安全的方法链接：

  ```java
  public abstract class BaseClientBuilder<T extends BaseClientBuilder<T>> {
      protected abstract T self();
      
      public T token(String token) {
          return self();  // 返回您的自定义类型，而不是 BaseClientBuilder
      }
  }
  ```

  ### 创建自定义构建器

  扩展生成的构建器：

  ```java title="src/main/java/com/example/CustomApiBuilder.java"
  public class CustomApiBuilder extends BaseClientBuilder<CustomApiBuilder> {
      @Override
      protected CustomApiBuilder self() {
          return this;
      }

      @Override
      protected void setEnvironment(ClientOptions.Builder builder) {
          // 自定义环境 URL
          String url = this.environment.getUrl();
          String expandedUrl = expandEnvironmentVariables(url);
          builder.environment(Environment.custom(expandedUrl));
      }

      @Override
      protected void setAdditional(ClientOptions.Builder builder) {
          // 添加自定义标头
          builder.addHeader("X-Request-ID", () -> UUID.randomUUID().toString());
      }
  }
  ```

  ### 使用您的自定义构建器

  ```java
  BaseClient client = new CustomApiBuilder()
      .token("my-token")        // 返回 CustomApiBuilder
      .tenantId("tenant-123")   // 返回 CustomApiBuilder  
      .timeout(30)              // 返回 CustomApiBuilder
      .build();

  client.users().list();
  ```

  ### 更新 `.fernignore`

  将您的自定义构建器添加到 `.fernignore`，这样 Fern 就不会覆盖它：

  ```diff title=".fernignore"
  + src/main/java/com/example/CustomApiBuilder.java
  ```
</Steps>

### 默认实现

如果您不需要扩展构建器，请使用提供的 `Impl` 类：

```java
BaseClient client = BaseClientBuilder.Impl()
    .token("my-token")
    .timeout(30)
    .build();
```

### 方法参考

每个方法都有特定的目的，仅在需要时生成：

| 方法                           | 目的                 | 可用时机         |
| ---------------------------- | ------------------ | ------------ |
| `self()`                     | 返回用于链接的具体构建器类型     | 始终（抽象）       |
| `setEnvironment(builder)`    | 自定义环境/URL 配置       | 始终           |
| `setAuthentication(builder)` | 修改或添加身份验证          | 仅当 API 具有认证时 |
| `setCustomHeaders(builder)`  | 添加 API 规范中定义的自定义标头 | 仅当 API 定义标头时 |
| `setVariables(builder)`      | 配置 API 变量          | 仅当 API 具有变量时 |
| `setHttpClient(builder)`     | 自定义 OkHttp 客户端     | 始终           |
| `setTimeouts(builder)`       | 修改超时设置             | 始终           |
| `setRetries(builder)`        | 修改重试设置             | 始终           |
| `setAdditional(builder)`     | 任何自定义配置的最终扩展点      | 始终           |
| `validateConfiguration()`    | 添加自定义验证逻辑          | 始终           |

### 常见模式

<Accordion title="多租户 URL">
  ```java
  @Override
  protected void setEnvironment(ClientOptions.Builder builder) {
      String url = this.environment.getUrl()
          .replace("/api/", "/tenants/" + tenantId + "/");
      builder.environment(Environment.custom(url));
  }
  ```
</Accordion>

<Accordion title="动态身份验证">
  ```java
  @Override
  protected void setAuthentication(ClientOptions.Builder builder) {
      super.setAuthentication(builder); // 保留现有认证
      builder.addHeader("Authorization", () ->
          "Bearer " + tokenProvider.getAccessToken()
      );
  }
  ```
</Accordion>

<Accordion title="环境变量扩展">
  ```java
  @Override
  protected void setEnvironment(ClientOptions.Builder builder) {
      String url = this.environment.getUrl();
      // 使用环境变量替换 ${VAR_NAME}
      Pattern pattern = Pattern.compile("\\$\\{([^}]+)\\}");
      Matcher matcher = pattern.matcher(url);
      StringBuffer result = new StringBuffer();
      
      while (matcher.find()) {
          String envVar = System.getenv(matcher.group(1));
          matcher.appendReplacement(result, 
              envVar != null ? envVar : matcher.group(0));
      }
      matcher.appendTail(result);
      
      builder.environment(Environment.custom(result.toString()));
  }
  ```
</Accordion>

<Accordion title="请求跟踪">
  ```java
  @Override
  protected void setAdditional(ClientOptions.Builder builder) {
      builder.addHeader("X-Request-ID", () -> UUID.randomUUID().toString());
      builder.addHeader("X-Tenant-ID", this.tenantId);
      
      if (FeatureFlags.isEnabled("new-feature")) {
          builder.addHeader("X-Feature-Flag", "new-feature");
      }
  }
  ```
</Accordion>

### 要求

* **Fern Java SDK 版本**：2.39.6 或更高版本
* **配置**：在 `generators.yml` 中设置 `enable-extensible-builders: true`

## 添加自定义依赖项

<Warning title="专业版和企业版功能">
  此功能仅适用于[专业版和企业版计划](https://buildwithfern.com/pricing)。如需开始使用，请联系 [support@buildwithfern.com](mailto:support@buildwithfern.com)。
</Warning>

要添加您的自定义代码所需的包，请更新您的 `generators.yml`。

```yaml {4-7} title="generators.yml"
- name: fernapi/fern-java-sdk
  version: "..."
  config:
    custom-dependencies:
      - org.apache.commons:commons-lang3:3.12.0
      - org.slf4j:slf4j-api:2.0.7

```