知識庫 / Spring / Spring Boot RSS 訂閱

與 Spring Boot 集成 Pkl 文件

Spring Boot
HongKong
5
10:50 AM · Dec 06 ,2025

1. 概述

在本教程中,我們將學習如何使用 Pkl(發音為“Pickle”,即醃製),一種配置為代碼(Configuration-as-Code)語言,用於定義 Spring Boot 應用程序中的配置。

傳統上,我們可能使用 YAML、JSON 或基於鍵值對的屬性文件來定義應用程序配置。然而,這些格式是靜態的,驗證屬性具有挑戰性。 此外,隨着配置屬性數量的增加,定義更復雜的層次結構配置變得越來越困難。

因此,通過使用配置為代碼(CaC),如 Pkl、HCL(Hashicorp 配置語言)Dhal 配置語言,可以幫助我們克服靜態屬性文件帶來的挑戰。

2. Pkl 簡介

配置即代碼 (Configuration-as-Code) 是一種流行的概念,它提倡“避免重複” (Don’t Repeat Yourself, DRY) 原則,並有助於簡化配置管理。它採用聲明式編碼風格,提供了一種結構化和高效的方法來定義配置模板。它還提高了配置的可讀性。

Pkl 能夠定義各種元素,例如對象類型、集合、映射和廣泛的基本數據類型。 這種靈活性使其可擴展,並有助於以清晰簡潔的方式輕鬆地對複雜配置進行建模。 此外,其類型和驗證機制有助於在應用程序部署之前捕獲配置錯誤。

此外,Pkl 提供強大的工具支持,以促進易於採用。 它具有用於生成 Java、Kotlin、Go 和 Swift 等不同語言的代碼的工具。 這對於在基於這些編程語言構建的應用程序中嵌入和讀取 Pickle 配置至關重要。

此外,IntelliJVS Code 這樣的 IDE 具有插件,以促進使用 Pkl 進行配置開發。 Pkl 還附帶一個命令行工具 (CLI) 稱為 pkl,可用於評估 Pickle 模塊。 其一項功能是將 .pkl 配置轉換為 JSON、YAML 和 XML 格式。

3. Spring 配置 Java Bean 綁定

定義 Spring 配置最常見的方法是創建屬性文件並使用 @Value 標註注入它們。然而,這種方法通常會導致過多的冗餘代碼。

幸運的是,Spring Framework 簡化了此過程,藉助 @ConfigurationProperties 標註,使配置能夠無縫地綁定到 Java Bean 上

但是,採用這種方法,我們仍然必須手動創建 Java Bean 並對成員字段進行必要的驗證。因此,配置漂移難以檢測,並且經常會導致應用程序中的關鍵錯誤。因此,像 Pkl 這樣的配置定義語言,以及自動化的 Java 代碼生成支持,是一種更健壯的方式來集成應用程序的配置。

4. Spring Boot 集成

Pkl 提供庫來從 Pickle 文件生成 POJO。稍後在運行時,pkl-spring 庫可以將 Pickle 配置填充到 POJO 中。下面我們將學習如何將其集成到 Spring Boot 應用程序中。

4.1. prerequisites

首先,我們將包含用於 pkl-spring 庫的 Maven 依賴項:

<dependency>
    <groupId>org.pkl-lang</groupId>
    <artifactId>pkl-spring</artifactId>
    <version>0.16.0</version>
</dependency>

此外,我們還將使用 exec-maven-plugin 從 Pickle 配置文件的生成 POJO:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>gen-pkl-java-bind</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>java</goal>
            </goals>
            <configuration>
                <mainClass>org.pkl.codegen.java.Main</mainClass>
                <includeProjectDependencies>false</includeProjectDependencies>
                <additionalClasspathElements>
                    <classpathElement>${pkl-tools-filepath}/pkl-tools-0.27.2.jar</classpathElement>
                </additionalClasspathElements>
                <arguments>
                    <argument>${project.basedir}/src/main/resources/ToolIntegrationTemplate.pkl</argument>
                    <argument>-o</argument>
                    <argument>${project.build.directory}/generated-sources</argument>
                    <argument>--generate-spring-boot</argument>
                    <argument>--generate-getters</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

Maven 插件執行 Java 代碼生成工具 pkl-tools:

java -cp pkl-tools-0.27.2.jar org.pkl.codegen.java.Main \
src/main/resources/ToolIntegration.pkl \ 
-o ${project.basedir}/src/main --generate-spring-boot

假設存在一個名為 ToolIntegrationTemplate.pkl 的 Pickle 文件,工具會在 target/generated-sources 文件夾中生成與 Pickle 文件對應的源代碼。

–generate-spring-boot 參數會將必要的 Spring Boot 類級別的 @ConfigurationProperties 註解包含到 Java Bean 中。 此外,–generate-getters 參數聲明屬性鍵為 private。

對於 Gradle 用户來説,pkl-gladle 插件 提供了一鍵生成 POJO 的支持。

4.2. 創建配置(pkl 格式)

讓我們考慮一個數據集成應用程序,它從源系統(如 Git 和 Jira)中獲取數據,並將它們分發到其他目標系統。

讓我們首先定義 Pickle 模板 ToolIntegrationTemplate.pkl 以存儲連接屬性:

module com.baeldung.spring.pkl.ToolIntegrationProperties

class Connection {
  url:String
  name:String
  credential:Credential
}

class Credential {
  user:String
  password:String
}

gitConnection: Connection
jiraConnection: Connection

總而言之,我們定義了兩個 Pkl 類 ConnectionCredential,並聲明瞭兩個對象 gitConnectionjiraConnection,它們都是 Connection 類型的對象。

接下來,讓我們在 application.pkl 文件中定義 gitConnectionjiraConnection

amends "ToolIntegrationTemplate.pkl"
gitConnection {
  url = "https://api.github.com"
  name = "GitHub"
  credential {
    user = "gituser"
    password = read("env:GITHUB_PASSWORD")
  }
}
jiraConnection {
  url = "https://jira.atlassian.com"
  name = "Jira"
  credential {
    user = "jirauser"
    password = read("env:JIRA_PASSWORD")
  }
}

我們已將模板填充了數據源的連接屬性。值得注意的是,我們沒有在配置文件中硬編碼密碼。相反,我們使用 Pkl 的 read() 函數從環境變量中檢索密碼,這是一種更安全的方法。

4.3. 將 Pkl 模板轉換為 POJO

在 Pickle 文件中定義配置後,可以通過執行 exec:java Maven 目標(在 pom.xml 文件中定義)來生成 POJO:

mvn exec:java@gen-pkl-java-bind

最終,pkl-tools庫會生成一個POJO和一個屬性文件:

ToolIntegrationProperties類包含兩個內部類,ConnectionCredential。它還使用了@ConfigurationProperties註解,這有助於將application.pkl中的屬性綁定到ToolIntegrationProperties對象。

4.4. 將 Pickle 配置綁定到 POJO

讓我們首先定義與源系統集成的服務類 JiraServiceGitHubService

public class JiraService {
    private final ToolIntegrationProperties.Connection jiraConnection;

    public JiraService(ToolIntegrationProperties.Connection connection) {
        this.jiraConnection = connection;
    }
   // ...methods getting data from Jira
}
public class GitHubService {
    private final ToolIntegrationProperties.Connection gitConnection;

    public GitHubService(ToolIntegrationProperties.Connection connection) {
        this.gitConnection = connection;
    }
    // ...methods getting data from GitHub
}

兩個服務都具有接受 ToolIntegrationProperties 作為參數的構造函數。隨後,參數中的連接詳情會被分配給類型為 ToolIntegrationProperties.Connection 的類級屬性。

接下來,我們將定義一個配置類,該類實例化服務並將其聲明為 Spring 框架中的 Bean。

@Configuration
public class ToolConfiguration {
    @Bean
    public GitHubService getGitHubService(ToolIntegrationProperties toolIntegration) {
        return new GitHubService(toolIntegration.getGitConnection());
    }

    @Bean
    public JiraService getJiraService(ToolIntegrationProperties toolIntegration) {
        return new JiraService(toolIntegration.getJiraConnection());
    }
}

在應用程序啓動期間,Spring 框架會將方法參數與來自 application.pkl 文件的配置綁定。最終,通過調用服務構造函數來實例化 Bean。

4.5. 服務注入與執行

最後,我們可以使用 <em @Autowired> 註解在其他 Spring 組件中注入服務 Bean。

使用 <em @SpringBootTest>,我們將驗證應用程序是否能夠從 Pickle 文件中加載 Jira 連接配置:

@SpringBootTest
public class SpringPklUnitTest {
    @Autowired
    private JiraService jiraService;

    @Test
    void whenJiraConfigsDefined_thenLoadFromApplicationPklFile() {
        ToolIntegrationProperties.Connection jiraConnection = jiraService.getJiraConnection();
        ToolIntegrationProperties.Credential jiraCredential = jiraConnection.getCredential();

        assertAll(
          () -> assertEquals("Jira", jiraConnection.getName()),
          () -> assertEquals("https://jira.atlassian.com", jiraConnection.getUrl()),
          () -> assertEquals("jirauser", jiraCredential.getUser()),
          () -> assertEquals("jirapassword", jiraCredential.getPassword()),
          () -> assertEquals("Reading issues from Jira URL https://jira.atlassian.com", 
            jiraService.readIssues())
        );
    }
}

為了演示,我們通過 pom.xml文件將Git和JIRA密碼設置在環境變量中。運行測試後,我們確認JIRA連接和憑據詳情與application.pkl文件中定義的的值相匹配。 此外,我們還假設如果正確實施,JiraService#readIssues()方法將成功執行。 目前,該方法僅返回一個佔位字符串。

同樣,讓我們檢查啓動應用程序後,是否從Pickle文件加載GitHub連接配置:

@SpringBootTest
public class SpringPklUnitTest {
    @Autowired
    private GitHubService gitHubService;

    @Test
    void whenGitHubConfigsDefined_thenLoadFromApplicationPklFile() {
        ToolIntegrationProperties.Connection gitHubConnection = gitHubService.getGitConnection();
        ToolIntegrationProperties.Credential gitHubCredential = gitHubConnection.getCredential();

        assertAll(
          () -> assertEquals("GitHub", gitHubConnection.getName()),
          () -> assertEquals("https://api.github.com", gitHubConnection.getUrl())
          () -> assertEquals("gituser", gitHubCredential.getUser()),
          () -> assertEquals("gitpassword", gitHubCredential.getPassword()),

          () -> assertEquals("Reading issues from GitHub URL https://api.github.com", 
            gitHubService.readIssues())
        );
    }
}

正如預期的那樣,本次連接和 GitHub 憑據信息也與 application.pkl 文件中定義的相同。因此,憑藉正確的連接信息,我們可以推斷,如果 GitHubServiceService#readIssues() 正確實現,它將連接到 GitHub 並檢索問題。 類似於 JiraService#readIssues(),該方法目前僅返回一個佔位符字符串。

5. 結論

在本文中,我們學習瞭如何利用 Pickle 文件定義 Spring Boot 應用程序的配置及其優勢。然而,掌握 Pkl 語言的概念對於設計可擴展且易於維護的複雜配置同樣至關重要。 此外,瞭解 Spring 框架將外部屬性綁定到 POJO 的功能也至關重要。

發佈 評論

Some HTML is okay.