1. 概述
Apache Camel 核心是一個集成引擎,簡單來説,它可以用於促進各種技術之間交互。
這些服務和技術之間的橋樑被稱為 路線。路線在引擎(即 CamelContext)上實現,並與稱為“交換消息”的實體進行通信。
2. Maven 依賴
為了開始,我們需要包含 Spring Boot、Camel、帶有 Swagger 和 JSON 的 REST API 的依賴項:
<dependencies>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-servlet-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-swagger-java-starter</artifactId>
<version>3.22.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>Apache Camel 依賴項的最新版本可以在這裏找到:這裏。
3. 主類
首先,讓我們創建一個 Spring Boot 應用程序:
@SpringBootApplication
@ComponentScan(basePackages="com.baeldung.camel")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}4. 使用 Spring Boot 進行 Camel 配置
現在,讓我們使用 Spring Boot 配置我們的應用程序,首先從配置文件(屬性)開始。
例如,讓我們在 <em src/main/resources/application.properties</em> 文件中配置應用程序的日誌記錄:
logging.config=classpath:logback.xml
camel.springboot.name=MyCamel
server.address=0.0.0.0
management.address=0.0.0.0
management.port=8081
endpoints.enabled = true
endpoints.health.enabled = true本示例展示了一個 application.properties 文件,它還設置了 Logback 配置的路徑。通過將 IP 設置為“0.0.0.0”,我們完全限制了 Spring Boot 提供 Web 服務器上的 admin 和 management 訪問。此外,我們還啓用了應用程序端點和健康檢查端點所需的網絡訪問。
另一個配置文件的 application.yml。在此文件中,我們將添加一些屬性,以幫助我們注入應用程序路由的值:
server:
port: 8080
camel:
springboot:
name: ServicesRest
management:
port: 8081
endpoints:
enabled: false
health:
enabled: true
quickstart:
generateOrderPeriod: 10s
processOrderPeriod: 30s5. 設置 Camel Servlet
通過將 Camel 註冊為 Servlet,您可以開始使用 Camel,以便它能夠攔截 HTTP 請求並將其重定向到您的應用程序。
正如之前提到的,在 Camel 的版本 2.18 及以下版本中,我們可以利用 application.yml – 通過為最終 URL 創建一個參數,然後在 Java 代碼中注入該參數:
baeldung:
api:
path: '/camel'回到我們的 Application 類,我們需要在上下文路徑的根目錄下注冊 Camel servlet,這將在應用程序啓動時從引用 baeldung.api.path 在 application.yml 中注入:
@Value("${baeldung.api.path}")
String contextPath;
@Bean
ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean servlet = new ServletRegistrationBean
(new CamelHttpTransportServlet(), contextPath+"/*");
servlet.setName("CamelServlet");
return servlet;
}截至 Camel 2.19 版本,此配置已被棄用,因為 CamelServlet 默認設置為 “/camel”。
6. 構建路由
讓我們通過擴展 Camel 的 RouteBuilder 類並將其設置為 @Component,以便在 Web 服務器初始化期間,組件掃描程序可以定位它,來構建路由。
@Component
class RestApi extends RouteBuilder {
@Override
public void configure() {
CamelContext context = new DefaultCamelContext();
restConfiguration()...
rest("/api/")...
from("direct:remoteService")...
}
}在本課程中,我們覆蓋了 Camel 的 RouteBuilder 類中的 configure() 方法。
Camel 始終需要一個 CamelContext 實例 – 這是消息流入和流出保持的核心組件。
在這個簡單的示例中,DefaultCamelContext 就足夠了,因為它只是將消息綁定並路由到其中,就像我們即將創建的 REST 服務一樣。
6.1. restConfiguration() 路由
接下來,我們在 restConfiguration() 方法中定義 REST 聲明,用於指定我們計劃創建的端點:
restConfiguration()
.contextPath(contextPath)
.port(serverPort)
.enableCORS(true)
.apiContextPath("/api-doc")
.apiProperty("api.title", "Test REST API")
.apiProperty("api.version", "v1")
.apiContextRouteId("doc-api")
.component("servlet")
.bindingMode(RestBindingMode.json)在這裏,我們使用 YAML 文件中注入的屬性註冊了上下文路徑。 同樣的邏輯也應用於我們的應用程序的端口。 CORS 已啓用,允許對此 Web 服務進行跨站使用。 綁定模式允許並將參數轉換為我們的 API。
接下來,我們向 URI、標題和先前設置的版本添加 Swagger 文檔。 隨着我們為 REST Web 服務創建方法/端點,Swagger 文檔將自動更新。
這個 Swagger 上下文本身就是一個 Camel 路由,並且在啓動過程中,可以在服務器日誌中看到一些關於它的技術信息。 我們的示例文檔默認提供於 http://localhost:8080/camel/api-doc。
6.2. rest() 路由
現在,讓我們實現從 configure() 方法中列出的 rest() 方法調用:
rest("/api/")
.id("api-route")
.consumes("application/json")
.post("/bean")
.bindingMode(RestBindingMode.json_xml)
.type(MyBean.class)
.to("direct:remoteService");此方法對於熟悉API的人來説非常直觀。 是在 CamelContext 內部標識路由的 ID。下一行定義 MIME 類型。綁定模式在這裏定義,以表明我們可以設置 的模式。
方法向 API 添加操作,生成 “POST /bean” 端點,而 MyBean(一個標準的 Java Bean,具有 Integer id 和 String name)定義了預期的參數。
同樣,HTTP 操作,如 GET、PUT 和 DELETE 均可用,形式為 、、。
最後, 方法創建一個到另一個路由的橋樑。在這裏,它告訴 Camel 在其上下文/引擎中搜索另一個路由,該路由將被我們創建並由值/ID “direct: …” 命名和檢測,與 方法中定義的路由匹配。
6.3. 使用 <em from() 路由與 <em transform()
當使用 Camel 時,路由接收參數,然後將其轉換為、轉換和處理。之後,它會將這些參數發送到另一個路由,該路由將結果轉發到所需的輸出(例如文件、數據庫、SMTP 服務器或 REST API 響應)。
在本文中,我們僅在 <em configure() 方法中創建另一個路由,該方法正在我們覆蓋。這將是我們的最後一個 <em to() 路由的接收路由:
from("direct:remoteService")
.routeId("direct-route")
.tracing()
.log(">>> ${body.id}")
.log(">>> ${body.name}")
.transform().simple("Hello ${in.body.name}")
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));from() 方法遵循與rest() 方法相同的原則,並具有許多相同的方法,只不過它從 Camel 上下文中消費消息。 這就是參數 “direct-route” 的原因,它與上述方法 rest().to() 建立了鏈接。
還有許多其他轉換可用,包括將其提取為 Java 原始數據類型(或對象),並將其發送到持久化層。 請注意,路由始終從傳入的消息中讀取,因此鏈式路由會忽略傳出消息。
我們的示例已準備就緒,我們可以嘗試一下:
- 運行提示命令:mvn spring-boot:run
- 向 http://localhost:8080/camel/api/bean 發送 POST 請求,帶有以下 HTTP 頭部參數:Content-Type: application/json,以及以下負載:{“id”: 1,”name”: “World”}
- 我們應該收到 201 的返回值以及響應:Hello, World
6.4. SIMPLE 腳本語言
本示例輸出使用 tracing() 方法進行日誌記錄。請注意,我們使用了 ${} 佔位符;這些佔位符是 Camel 腳本語言的一部分,該語言屬於 SIMPLE。它應用於在路由中交換的消息體,例如消息體的內容。
在我們的示例中,我們使用 SIMPLE 來將消息體內的 Bean 屬性輸出到日誌中。
我們還可以使用它進行簡單的轉換,如 transform() 方法所示。
6.5. 使用 <em from() 路由與 <em process() 方法
讓我們做一些更有意義的事情,例如調用服務層以返回經過處理的數據。SIMPLE 不適合進行大量的處理,因此我們應該用 <em process() 方法替換 <em transform() 方法:
from("direct:remoteService")
.routeId("direct-route")
.tracing()
.log(">>> ${body.id}")
.log(">>> ${body.name}")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
MyBean bodyIn = (MyBean) exchange.getIn().getBody();
ExampleServices.example(bodyIn);
exchange.getIn().setBody(bodyIn);
}
})
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));這使得我們能夠將數據提取到一個 Bean 中,該 Bean 與之前在 type()方法中定義的 Bean 相同,並在我們的 ExampleServices層中進行處理。
由於我們之前將 bindingMode()設置為 JSON,因此響應已經是基於我們 POJO 生成的正確 JSON 格式。這意味着對於一個 ExampleServices類而言:
public class ExampleServices {
public static void example(MyBean bodyIn) {
bodyIn.setName( "Hello, " + bodyIn.getName() );
bodyIn.setId(bodyIn.getId() * 10);
}
}相同的 HTTP 請求現在返回,狀態碼為 201,響應體為:“id”: 10,”name”: “Hello, World”}。
7. 結論
通過幾行代碼,我們成功地創建了一個相對完整的應用程序。所有依賴項都已構建、管理和自動運行,只需一個命令即可。此外,我們還可以創建將各種技術連接在一起的 API。
這種方法也非常適合容器化,從而產生了一個輕量級的服務器環境,可以按需輕鬆複製。額外的配置選項可以輕鬆地集成到容器模板配置文件的其中。
最後,除了 filter(), process(), transform(), 和 marshall() API 之外,Camel 還提供了許多其他集成模式和數據操作方法: