<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>integration-complete</artifactId> <version>0.0.1-SNAPSHOT</version> <name>integration-complete</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-feed</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-file</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
整合資料
本指南將引導您完成使用 Spring Integration 建立一個簡單應用程式的過程,該應用程式從 RSS Feed (Spring Blog) 中檢索資料,對資料進行處理,然後將其寫入檔案。本指南使用傳統的 Spring Integration XML 配置。其他指南將介紹如何使用 Java 配置和 DSL(帶或不帶 Lambda 表示式)進行配置。
您將構建什麼
您將使用傳統的 XML 配置透過 Spring Integration 建立一個流程。
你需要什麼
-
大約 15 分鐘
-
一個喜歡的文字編輯器或 IDE
-
Java 17 或更高版本
-
您還可以將程式碼直接匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,也可以跳過您已熟悉的基本設定步驟。無論哪種方式,您最終都會得到可工作的程式碼。
要從頭開始,請轉到從 Spring Initializr 開始。
要跳過基礎知識,請執行以下操作
-
下載 並解壓本指南的原始碼庫,或使用 Git 克隆它:
git clone https://github.com/spring-guides/gs-integration.git -
cd 進入
gs-integration/initial -
跳到 定義整合流程。
完成後,您可以將您的結果與 gs-integration/complete 中的程式碼進行對照。
從 Spring Initializr 開始
您可以使用這個 預初始化專案 並點選生成下載 ZIP 檔案。此專案已配置為符合本教程中的示例。
手動初始化專案
-
導航到 https://start.spring.io。此服務會為您拉取應用程式所需的所有依賴項,併為您完成大部分設定。
-
選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇了 Java。
-
點選 Dependencies 並選擇 Spring Integration。
-
單擊生成。
-
下載生成的 ZIP 檔案,這是一個已根據您的選擇配置好的 Web 應用程式存檔。
| 如果您的 IDE 集成了 Spring Initializr,您可以從 IDE 中完成此過程。 |
| 您還可以從 Github fork 該專案並在您的 IDE 或其他編輯器中開啟它。 |
新增到構建檔案
對於此示例,您需要新增兩個依賴項。
-
spring-integration-feed -
spring-integration-file
以下列表顯示了最終的 pom.xml 檔案
以下列表顯示了最終的 build.gradle 檔案
plugins {
id 'org.springframework.boot' version '3.3.0'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-integration'
implementation 'org.springframework.integration:spring-integration-feed'
implementation 'org.springframework.integration:spring-integration-file'
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation 'org.springframework.integration:spring-integration-test'
}
test {
useJUnitPlatform()
}
定義整合流程
對於本指南的示例應用程式,您將定義一個 Spring Integration 流程,該流程將:
-
從 spring.io 的 RSS feed 讀取部落格文章。
-
將它們轉換為易於閱讀的
String,其中包含文章標題和文章的 URL。 -
將該
String追加到檔案末尾(/tmp/si/SpringBlog)。
要定義整合流程,您可以建立一個 Spring XML 配置檔案,其中包含 Spring Integration 的 XML 名稱空間中的一些元素。具體來說,對於所需的整合流程,您將使用以下 Spring Integration 名稱空間中的元素:core、feed 和 file。(獲取後兩個是我們需要修改 Spring Initializr 提供的構建檔案的原因。)
以下 XML 配置檔案(來自 src/main/resources/integration/integration.xml)定義了整合流程:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:file="http://www.springframework.org/schema/integration/file"
xmlns:feed="http://www.springframework.org/schema/integration/feed"
xsi:schemaLocation="http://www.springframework.org/schema/integration/feed https://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/file https://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd">
<feed:inbound-channel-adapter id="news" url="https://springframework.tw/blog.atom" auto-startup="${auto.startup:true}">
<int:poller fixed-rate="5000"/>
</feed:inbound-channel-adapter>
<int:transformer
input-channel="news"
expression="payload.title + ' @ ' + payload.link + '#{systemProperties['line.separator']}'"
output-channel="file"/>
<file:outbound-channel-adapter id="file"
mode="APPEND"
charset="UTF-8"
directory="/tmp/si"
filename-generator-expression="'${feed.file.name:SpringBlog}'"/>
</beans>
這裡有三個整合元素在起作用:
-
<feed:inbound-channel-adapter>:一個入站介面卡,每隔輪詢一次檢索帖子。在此配置中,它每五秒輪詢一次。帖子被放入一個名為news的通道(對應於介面卡的 ID)。 -
<int:transformer>:轉換news通道中的條目(com.rometools.rome.feed.synd.SyndEntry),提取條目的標題(payload.title)和連結(payload.link),並將它們連線成一個易於閱讀的String(並新增換行符)。然後將String傳送到名為file的輸出通道。 -
<file:outbound-channel-adapter>:一個出站通道介面卡,它將內容從其通道(名為file)寫入檔案。具體來說,在此配置中,它將file通道中的任何內容追加到位於/tmp/si/SpringBlog的檔案中。
下圖顯示了這個簡單的流程:
暫時忽略 auto-startup 屬性。我們稍後在討論測試時會重新討論它。目前,請注意它預設設定為 true,這意味著在應用程式啟動時就會獲取帖子。還要注意 filename-generator-expression 中的屬性佔位符。這意味著預設值是 SpringBlog,但可以透過屬性覆蓋。
使應用程式可執行
雖然通常在一個更大的應用程式(甚至可能是 Web 應用程式)中配置 Spring Integration 流程,但沒有理由不能在一個更簡單的獨立應用程式中定義它。接下來您將要做的是:建立一個主類來啟動整合流程,並宣告一些 bean 來支援整合流程。您還將把應用程式構建成一個獨立的、可執行的 JAR 檔案。我們使用 Spring Boot 的 @SpringBootApplication 註解來建立應用程式上下文。由於本指南使用 XML 名稱空間來定義整合流程,因此您必須使用 @ImportResource 註解將其載入到應用程式上下文中。以下列表(來自 src/main/java/com/example/integration/IntegrationApplication.java)顯示了應用程式檔案:
package com.example.integration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("/integration/integration.xml")
public class IntegrationApplication {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = new SpringApplication(IntegrationApplication.class).run(args);
System.out.println("Hit Enter to terminate");
System.in.read();
ctx.close();
}
}
構建可執行 JAR
您可以使用 Gradle 或 Maven 從命令列執行應用程式。您還可以構建一個包含所有必要依賴項、類和資源並執行的單個可執行 JAR 檔案。構建可執行 JAR 使在整個開發生命週期中,跨不同環境等,輕鬆交付、版本化和部署服務作為應用程式。
如果您使用 Gradle,您可以透過使用 ./gradlew bootRun 執行應用程式。或者,您可以透過使用 ./gradlew build 構建 JAR 檔案,然後按如下方式執行 JAR 檔案
如果您使用 Maven,您可以透過使用 ./mvnw spring-boot:run 執行應用程式。或者,您可以使用 ./mvnw clean package 構建 JAR 檔案,然後按如下方式執行 JAR 檔案
| 這裡描述的步驟建立了一個可執行的 JAR。您還可以構建一個經典的 WAR 檔案。 |
執行應用程式
現在,您可以執行該應用程式的 jar 檔案,執行以下命令:
java -jar build/libs/{project_id}-0.1.0.jar
... app starts up ...
應用程式啟動後,它會連線到 RSS feed 並開始獲取部落格文章。應用程式透過您定義的整合流程處理這些文章,最終將文章資訊追加到 /tmp/si/SpringBlog 的檔案中。
應用程式執行一段時間後,您應該能夠檢視 /tmp/si/SpringBlog 中的檔案,檢視一些帖子的資料。在類 UNIX 作業系統上,您也可以使用 tail 命令即時檢視寫入的資料,執行以下命令:
tail -f /tmp/si/SpringBlog
您應該會看到類似以下的示例輸出(但實際新聞會有所不同):
Spring Integration Java DSL 1.0 GA Released @ https://springframework.tw/blog/2014/11/24/spring-integration-java-dsl-1-0-ga-released
This Week in Spring - November 25th, 2014 @ https://springframework.tw/blog/2014/11/25/this-week-in-spring-november-25th-2014
Spring Integration Java DSL: Line by line tutorial @ https://springframework.tw/blog/2014/11/25/spring-integration-java-dsl-line-by-line-tutorial
Spring for Apache Hadoop 2.1.0.M2 Released @ https://springframework.tw/blog/2014/11/14/spring-for-apache-hadoop-2-1-0-m2-released
測試
檢查 complete 專案,您會在 src/test/java/com/example/integration/FlowTests.java 中看到一個測試用例。
package com.example.integration;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import com.rometools.rome.feed.synd.SyndEntryImpl;
@SpringBootTest({ "auto.startup=false", // we don't want to start the real feed
"feed.file.name=Test" }) // use a different file
public class FlowTests {
@Autowired
private SourcePollingChannelAdapter newsAdapter;
@Autowired
private MessageChannel news;
@Test
public void test() throws Exception {
assertThat(this.newsAdapter.isRunning()).isFalse();
SyndEntryImpl syndEntry = new SyndEntryImpl();
syndEntry.setTitle("Test Title");
syndEntry.setLink("http://characters/frodo");
File out = new File("/tmp/si/Test");
out.delete();
assertThat(out.exists()).isFalse();
this.news.send(MessageBuilder.withPayload(syndEntry).build());
assertThat(out.exists()).isTrue();
BufferedReader br = new BufferedReader(new FileReader(out));
String line = br.readLine();
assertThat(line).isEqualTo("Test Title @ http://characters/frodo");
br.close();
out.delete();
}
}
此測試使用 Spring Boot 的測試支援將名為 auto.startup 的屬性設定為 false。依賴網路連線進行測試通常不是一個好主意,尤其是在 CI 環境中。相反,我們阻止 feed 介面卡啟動,並將一個 SyndEntry 注入到 news 通道中,以便其餘流程處理。該測試還設定了 feed.file.name,以便測試寫入不同的檔案。然後它:
-
驗證介面卡已停止。
-
建立測試
SyndEntry。 -
刪除測試輸出檔案(如果存在)。
-
傳送訊息。
-
驗證檔案是否存在。
-
讀取檔案並驗證資料是否符合預期。
總結
恭喜!您已經開發了一個簡單的應用程式,該應用程式使用 Spring Integration 從 spring.io 獲取部落格文章,進行處理,然後將其寫入檔案。