用 IBM WebSphere DataStage 進行數據整合:第 3 部分: 實時數據整合

 

【轉載】用 IBM WebSphere DataStage 進行數據整合:第 3 部分: 實時數據整合

原文地址:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0611zhoudp/index.html

 

本系列的第 1 部分和第 2 部分詳細介紹瞭如何利用 DataStage 開發 ETL Job。 在本文中,我們將引入 RTI Job 的概念,並詳細講述如何利用 DataStage 開發 RTI Job 並將 RTI Job 發佈成 Web Service 以供其他應用程序調用。

 

本文主要包含以下幾部分內容:

1. RTI Job特性介紹

2. 開發一個RTI Job

3. 將RTI Job發佈成Web Service

4. 利用Java客戶端調用發佈好的Web Service

RTI Job特性介紹

RTI Job是 ETL Job的一種特殊形式,它可以被髮布成RTI 服務(RTI Service),RTI服務分成三種,分別是Web service,EJB和JMS。在本文中我們只介紹如何發佈成Web service。正是因爲RTI Job可以以服務的形式被髮布出來,這就使得企業數據整合和企業的面向服務的架構(SOA)無縫的整合在了一起。下面我們通過圖一來看一下RTI Job被髮布成RTI服務後整個應用程序的架構。


圖一:RTI 架構
圖一:RTI 架構  

從這張圖中,我們可以清楚地看出RTI的架構,首先開發好的RTI Job的實例運行在DataStage Server上,這些RTI Job以RTI Service的形式發佈在RTI Server上。RTI Server和DataStage Server之間通過RTI Agent進行通信。其實RTI Server本身也是作爲一個Web應用程序運行在Web應用程序服務器上的,可以是IBM Websphere 應用程序服務器或者BEA WebLogic應用程序服務器等。RTI Server和DataStage Server可以不放在同一臺機器上,但是RTI Agent和DataStage Server必須放在同一臺機器上面。這樣,在RTI Server上部署好的Web Service就可以被各種客戶端來調用,比如Java, dot NET等。

RTI Job的種類

RTI Job分成三種,第一種和普通的ETL Job沒什麼區別,既不含有RTI輸入組件(RTI Input Stage)也不含有RTI 輸出組件(RTI Output Stage)。第二種只含有RTI輸出組件,第三種既含有RTI 輸入組件又含有RTI輸出組件。下面我們分別來介紹一下這三種類型的RTI Job

1. 既不含RTI輸入組件也不含RTI輸出組件

前面提到,這種RTI Job和普通的ETL Job沒有什麼區別,那麼它怎麼同調用它的客戶端進行交互呢,這分兩種情況,第一種情況是客戶端只是希望調用一個ETL Job來執行數據的抽取,轉換和加載的工作,不需要對該ETL Job有輸入也無需從該ETL Job中得到輸出。第二種情況是通過對該ETL Job設置參數來獲得從客戶端的輸入,在這種情況下,該ETL Job有輸入但沒有輸出。大家注意到,在這兩種情況下,客戶端都不能從該ETL Job中獲得返回值,也就是說該ETL Job沒有輸出。爲什麼會這樣呢,因爲RTI Job若想有輸出,那麼它必須含有RTI 輸出組件。圖2顯示了這種既不含RTI輸入組件也不含RTI輸出組件的RTI Job的一個例子。


圖2:RTI Job示例1
圖2:RTI Job示例1  

2. 只含有RTI輸出組件

這種RTI Job含有RTI輸出組件但不含有RTI輸入組件,這種RTI Job能通過RTI輸出組件向調用它的客戶端返回需要的值,可以是一個整型數據,一個結構化的數據或者一個結構化的數組,具體返回什麼,可以在部署成Web Service的過程中設置,這會在文章的第三部分進行介紹。當然,這種類型的RIT Job也是通過設置Job的參數來接收從客戶端傳過來的參數的。圖3顯示了一個只含有RTI輸出組件的一個例子。


圖3:RTI Job示例2
圖3:RTI Job示例2  

3. 既含RTI輸入組件又含RTI輸出組件

這種RTI Job既能通過RTI輸入組件接受從客戶端傳過來的參數,又能通過RTI輸出組件來向客戶端返回結果。這種RTI Job與前兩種RTI Job的另外一個不同點是,當這種RTI Job編譯後,會產生一個或者多個實例一直運行,這些事例會維持着和數據庫的連接,因此當客戶端進行調用的時候,相應速度就會非常快,而前面兩種RTI Job的響應速度則相對會比較慢一些。圖4是一個既含RTI輸入組件又含RTI輸出組件的RTI Job的例子。


圖4:RTI Job示例3
圖4:RTI Job示例3  

在介紹了各種不同的RTI Job之後,我們接下來進入如何開發一個RTI Job的階段。



開發一個RTI Job

在這一部分中,我們將詳細講解如何開發一個既含RTI輸入組件又含RTI輸出組件的RTI Job。首先我們來介紹一下我們即將開發的RTI Job的功能:我們的數據庫系統中預先建立了一張表,表明爲Student,這張表由兩個字段,分別是ID和Name,我們即將開發的RTI Job就是通過接受從客戶端傳進來的ID來查找對應的Name,然後將查詢結果返回到客戶端去。

1. 打開DataStage Designer, 系統會自動彈出一個創建新的DataStage Job的對話框來,如圖5所示,選擇Server Job,然後單擊OK按鈕;


圖5:新建Server Job
圖5:新建Server Job  

2. 這時候系統創建的Server Job如圖6所示, 這時候這個Server Job上還沒有放任何DataStage組件,注意我們現在還沒有保存這個Server Job,單擊左上角的保存按鈕或者直接用Ctrl+S對Server Job進行保存;


圖6:創建的Server Job
圖6:創建的Server Job  

3. 如圖7所示,在彈出的保存對話框中,輸入Server Job的名稱以及要保存的路徑,在我們的例子中,我們以RTIJob爲Server Job的名稱,保存在文件夾RTISample中;


圖7:保存Server Job
圖7:保存Server Job  

4. 保存好後,我們把需要的DataStage的組件從左邊的組件面板拖入到右邊的設計器中,如圖8所示,我們需要一個RTI 輸入組件,一個RTI輸出組件,一個Transformer組件和一個DB2 UDB組件。選擇好組件後,按照圖8所示的邏輯進行連接,並分別爲每個組件賦上一個有意義的名字;


圖8:選擇需要的組件
圖8:選擇需要的組件  

5. 在各個組件都準備好之後,我們需要對每個組件的屬性進行設置。由於對屬性進行設置的時候需要用到我們之前提到的Student表的表結構,我們首先需要從數據庫中導入Student表的表結構,我們接下來的幾個步驟就是進行表結構導入工作。在DataStage Designer中,如圖9所示,右鍵單擊Table Definition,然後選擇Import ' Plug-in Meta Data Definition;


圖9:導入表結構
圖9:導入表結構  

6.如圖10所示,在彈出的對話框中,選擇DSDB2,然後單擊OK按鈕;


圖10:選擇數據庫類型
圖10:選擇數據庫類型  

7.然後在Server Name下拉列表中選擇SAMPLE,我們創建的Student表正是存放在這個數據庫中的,然後輸入用戶名和密碼,並注意一定要選上Tables選擇框,然後單擊Next按鈕,如圖11所示;


圖11:選擇數據庫連接信息
圖11:選擇數據庫連接信息  

8.如圖12所示,選擇表Student,然後輸入表結構要保存的路徑,系統提供了一個默認的保存路徑,我們可以修改成爲我們想要保存的地方。然後單擊Import按鈕來導入表Student的表結構;


圖12:選擇要導入的表結構
圖12:選擇要導入的表結構  

9.接着我們來編輯DB2 UDB組件的屬性,雙擊組件,如圖13所示的屬性設置框就會彈出來,在Stage標籤的General子標籤中,我們輸入Server Name爲Sample,然後輸入連接數據庫用的用戶名和密碼,在事務隔離級別(Transaction Isolation)的下拉框中,我們使用系統的默認值,遊標穩定性隔離級別。然後單擊Output標籤;


圖13:設置數據庫連接信息
圖13:設置數據庫連接信息  

10.如圖14所示,在Output標籤的General子標籤中,在Table Name輸入框中輸入表名Student,然後在Query Type下拉框中選擇Generated SQL Query. 最後單擊子標籤Column進行進一步的屬性設置;


圖14:選擇要連接的表
圖14:選擇要連接的表  

11.如圖15所示,在Column子標籤中單擊按鈕Load..,系統會彈出一個對話框讓選擇需要引入的表結構,我們選擇剛纔從數據庫中導入的表Student的表結構,然後單擊OK按鈕;


圖15:引入表結構
圖15:引入表結構  

12.如圖16所示,在彈出的對話框中可以選擇需要導入表Student的那些列,系統默認是全部導入,保持默認,單擊OK按鈕;


圖16:選擇要導入的列
圖16:選擇要導入的列  

13.如圖17所示,導入表結構後,Column標籤裏面會顯示出我們從數據庫中導入的表Student的表結構,單擊View Data按鈕來測試一下連接;


圖17:導入後的表結構
圖17:導入後的表結構  

14. 單擊View Data按鈕後,如果所有的設置都正確的話,系統就會彈出如圖18所示的窗口,裏面顯示了Student表的內容,在我們的例子中,Student表裏面有兩條記錄。至此,DUB UDB組件的屬性設置已經完成。如果在這一步中不能成功顯示錶中的數據的話,就需要回過頭來看看前面的設置是不是正確;


圖18:測試連接
圖18:測試連接  

15.接下來我們設置RTI Input Stage的屬性,雙擊RTI Input Stage組件,系統會彈出如圖19所示的窗口,在Stage標籤的General子標籤中,你可以爲該組件加一些註釋以表明該組件的用途,也可以在這裏設置組件的顯示現實名稱。然後我們單擊Outputs標籤;


圖19:RTI輸入組件屬性設置
圖19:RTI輸入組件屬性設置  

16.在Outputs標籤的Columns子標籤中,可以直接輸入和Student表的ID字段相同的字段定義,也可以通過Load按鈕來從Student表結構中只選擇導入ID字段的定義。注意這裏的ID字段正是需要從客戶端接受的參數。當然客戶端可以傳過來一個ID的值或者以數組的形式傳過來多個ID的值,具體的設置是在部署Web Service的過程中進行的。設置完成後,單擊OK按鈕,如圖20所示;


圖20:引入字段定義
圖20:引入字段定義  

17.然後我們對RTI Output Stage組件屬性進行設置,雙擊RTI Output Stage組件,如圖21所示的窗口會顯示出來,像對RTI Input Stage組件進行屬性設置一樣,這裏同樣可以加入一些描述信息,更改RTI Output Stage組件的顯示名稱等,我們保持默認,然後單擊Inputs標籤;


圖  

18.在Inputs標籤的Columns子標籤中,直接輸入如圖22所示的內容,當然,你也可以從Student表中只導入Name字段的定義,注意我們這裏的Name字段正是需要返回給客戶端的數據,當然是返回一個還是多個值是通過在部署Web Service的過程中來設置的。最後單擊OK按鈕來完成設置;


圖  

19.然後我們來設置Transformer Stage組件的信息,具體設置的內容如圖23所示。在該圖中,左上角的Parameter框代表的是RTI Input Stage組件,它只含有一個字段ID,左下角的Data框代表的是DB2 UDB組件,連接的是Student表,它有兩個字段ID和Name。由下角的Name框代表的是RTI Output Stage組件的信息,它只有一個字段Name,這也正是需要返回給客戶端的信息;


圖23:配置Transformer Stage組件
圖23:配置Transformer Stage組件  

20.配置完每個組件的屬性後,我們需要對整個Job的屬性進行配置,以使得DataStage系統知道這是一個RTI Job。單擊DataStage Designer工具欄中的Job Properties圖標,如圖24所示的對話框就會彈出來,然後選上Allow Mutiple Instance和RTI Service Enabled選擇框。這樣就能利用DataStage提供的RTI控制檯將該RTI Job發佈成Web Service。最後單擊OK按鈕並保存更改;


圖24:配置RTI Job
圖24:配置RTI Job  

21.這時候我們已經配置好了所有需要配置的信息,接下來我們來編譯開發好的RTI Job,單擊DataStage Designer工具欄中的編譯圖標,編譯成功後的畫面如圖25所示。與一般的DataStage Job不同的是,如果你開發的是一個既含有RTI輸入組件又含有RTI輸出組件的RTI Job,那麼在編譯後就會自動運行這個RTI Job的實例。我們可以通過DataStage Director來觀察;


圖25:編譯RTI Job
圖25:編譯RTI Job  

22.如圖26所示,打開DataStage Director,在RTI Sample目錄下面,你會看到一個RTI Job的實例正在運行,這個實例維持着與數據庫的連接,如果你把數據庫連接斷掉,你會發現這個實例就會中斷掉,然後系統會接着嘗試啓動一個新的實例,直到數據庫連接恢復正常;


圖26:查看RTI Job的狀態
圖26:查看RTI Job的狀態  

現在我們已經成功開發並編譯了RTI Job,我們接下來的工作就是將這個RTI Job發佈成Web Service。



將RTI Job發佈成Web Service

這一部分我們將詳細講述如何將一個已經編譯好的RTI Job發佈成Web Service,在這一部分進行之前,你需要檢查一下你的軟件的安裝,確保以下軟件已經成功安裝好:

1. RTI Console 它是將RTI Job部署成Web Service的可視化接口,並且提供了部署的嚮導方便我們進行部署

2. RTI Agent 要確保它已經同DataStage Server安裝在了同一臺機器上,RTI Agent的安裝一般是和DataStage Server的安裝一起安裝的,RTI Agent負責RTI Server和DataStage Server的通信。

3. RTI Server 部署的Web Service是運行在RTI Server上的,當然RTI Server也是運行在一個Web應用程序服務器上的,比如IBM Web Application Server。

準備好需要的軟件後,我們進入利用RTI控制檯發佈Web Service的部分。

1.首先打開RTI控制檯,如圖27所示,DataStage提供了一個圖形化的界面方便我們把RTI Job發佈成RTI Service。然後我們在左側面板的Current Tasks模塊中單擊鏈接Register an RTI Server來新註冊一個RTI Server;


圖27:RTI 控制檯
圖27:RTI 控制檯  

2.在彈出的對話框中,輸入RTI服務器的名字或者IP地址,然後在Web Service End-point中輸入如圖28所示的值,這裏要注意,因爲我是把RTI Server部署在IBM Websphere 應用程序服務器上的,而運行在其上的應用程序都是運行在9080端口下面,所以我設置的端口號是9080,如果你是將RTI Server運行在其他的應用程序服務器上,你就需要將這個端口號改成該應用程序服務器所對應的端口號,最後單擊Finish按鈕;


圖28:註冊RTI Server
圖28:註冊RTI Server  

3. 如圖29所示,我們會看到右邊的面板中出現了我們剛纔註冊好的RTI Server,雙擊這個圖標。


圖29:成功註冊RTI Server
圖29:成功註冊RTI Server  

4. 如圖30所示,在雙擊剛纔註冊的RTI Server之後,左邊的菜單選項也發生了相應的改變,我們在Current Tasks模塊中單擊鏈接Register a DataStage Machine來註冊一個DataStage服務器。


圖30:註冊DataStage服務器
圖30:註冊DataStage服務器  

4. 彈出的對話框如圖31所示,我們可以在Machine Name輸入框中輸入DataStage服務器所在的計算機名或者IP地址。如果需要的話,我們還要輸入登陸的用戶名和密碼,其他選項保持默認,然後單擊Finish按鈕。


圖31:填寫註冊信息
圖31:填寫註冊信息  

5. 如圖32所示,註冊好的DataStage服務器會顯示在右邊面板的上半部分中,註冊成功後,我們單擊左側菜單Current Tasks模塊中的鏈接Add a new Service to the RTI Server去註冊一個新的RTI Service;


圖32:註冊新的RTI Service
圖32:註冊新的RTI Service  

6.如圖33所示,在彈出的對話框中,在Service Name文本框中輸入sample,其他的內容保持默認,然後單擊Finish按鈕;


圖33:填寫配置信息
圖33:填寫配置信息  

6. 如圖34所示,註冊好的RTI Service顯示在右邊面板的下半部分,注意我們現在註冊的這個RTI Service只是一個空的殼子,我們還需要爲它選擇使用的協議以及附加的RTI Job,這些都會在下面的步驟中進行配置。最後我們雙擊這個RTI Service的圖標;


圖34:註冊好的RTI Service
圖34:註冊好的RTI Service  

8.如圖35所示,單擊左側面板Current Tasks模塊中的鏈接Add support for Service Bindings;


圖35:添加Service Binding
圖35:添加Service Binding  

9.如圖36所示,選擇Service Binding的類型爲SOAP over HTTP,因爲我們是將RTI Job發佈成Web Service,所以我們必須選擇這個選項,其他選項是用來把RTI Job發佈成JMS或者EJB,然後單擊Next按鈕;


圖  

10.如圖37所示,你可以輸入一些描述信息,然後單擊Finish按鈕;


圖37:添加描述信息
圖37:添加描述信息  

11.如圖38所示,我們添加的Service Binding顯示在了右側面板的上半部分中,單擊該Service Binding的圖標,然後從左邊面板的Current Tasks模塊中單擊鏈接Add an operation來爲該RTI Service添加RTI Job;


圖38:註冊好的Service Binding
圖38:註冊好的Service Binding  

12.如圖39所示,在彈出的對話框中選中我們之前開發並編譯好的RTI Job RTIJob,然後單擊按鈕Next;


圖39:選擇RTI Job
圖39:選擇RTI Job  

13. 如下圖所示,我們需要在Operation Name文本框中輸入該RTI Job所對應到Web Service中的名字,直接輸入RTIJob,保持其他選項爲默認,然後單擊按鈕Next;


圖40:配置相關信息
圖40:配置相關信息  

14.在如圖41所示的頁面中,我們可以配置該Web Service所接受的參數的信息,注意系統已經默認爲我們生成了配置,那就是隻接受一個名稱爲ID參數,類型爲String,我們可以通過Options下來列表來改表輸入參數的設置,比如如果我們需要傳入的參數是結構化的,那麼我們需要選擇選項Group,如果我們需要傳入多個相同類型的數據,那麼我們的參數就需要設置成Array,在我們的例子中,如果我們設置成了Array,那麼就代表我們的Web Service會接受一個字符串數組,裏面可能存放了多個人的ID信息。由於我們這個例子只是傳入一個ID,然後返回該ID所對應的Name,所以我們不需要進行設置,保持系統默認,然後單擊按鈕Next。


圖41:配置輸入參數
圖41:配置輸入參數  

15.接着我們需要配置該Web Service向客戶端的返回值,由於我們只需要返回一個字符串類型的數據,我們保持系統的默認設置,然後單擊按鈕Next;


圖42:配置返回值類型
圖42:配置返回值類型  

16.在這裏可以設置一些和WSDL文件相關的名字空間的信息,我們使用系統提供的默認值,然後單擊Next按鈕;


圖43:名字空間的設置
圖43:名字空間的設置  

17.如圖44所示,確認選擇框Launch the Add Job/Map Wizard with the job or map you selected是選上的,然後單擊按鈕Finish;


圖44:完成配置
圖44:完成配置  

18.在圖45中可以配置一些運行時的參數,比如RTI Job的實例的最小數目是多少,最大樹木是多少等,可以根據自己的應用程序的需要來配置,比如如果同時會有多個客戶端來訪問該Web Service,那麼就需要將最小實例數目設置大一些。 設置好後,單擊按鈕Next;


圖45:配置運行參數
圖45:配置運行參數  

19.在下圖中輸入驗證信息,然後單擊按鈕Finish;


圖46:輸入驗證信息
圖46:輸入驗證信息  

20.如下圖所示,系統彈出一個對話框提示用戶已經成功的將RTI Job添加到了RTI Service當中;


圖47:添加成功
圖47:添加成功  

21.如圖48所示,我們需要重新激活我們之前配置的Service Binding,並且我們注意到我們添加的RTIJob也顯示在了右邊面板的下半部分;


圖48:激活Service Binding
圖48:激活Service Binding  

22.單擊左側面板的View RTI Service Repository鏈接,就進入到了如圖49所示的頁面,然後單擊我們剛纔註冊成功的Web Service sample;


圖49:部署的RTI Service
圖49:部署的RTI Service  

23.下圖顯示了我們剛部署成功的Web Service的相關信息,我們單擊對應的WSDL文件的鏈接去查看WSDL文件;


圖50:Web Service 相關信息
圖50:Web Service 相關信息  

24.圖51顯示了我們部署好的Web Service對應的WSDL文件的內容,而各種客戶端正是通過這個WSDL文件對後臺的應用邏輯進行調用的。我們在文章的最後一個章節會介紹如何調用該Web Service;


圖51:WSDL文件
圖51:WSDL文件  

利用Java客戶端調用發佈好的Web Service 文章接下來講述如何去調用我們之前發佈好的Web Service,我們使用一個用Java語言編寫的客戶端來進行調用。在開始之前,讀者應該準備好如下的環境:

1.Eclipse集成開發環境

因爲我們開發的Java項目是在Eclipse下面進行的,所以安裝一個Eclipse的環境能使讀者更容易的跟上文章的每一步。可以從Eclipse的官方網站上下載最新版本的Eclipse。

2.JDK1.4或者1.5

這是Java開發的必備環境。

3. Axis

文章中會使用Axis提供的工具生成調用Web Service的本地Stub,方便對Web Service進行調用。Axis可以從它的官方網站下載到,文章後面的資源列表包含了該鏈接。

下面我們開始Java客戶端的開發

1. 首先使用創建一個Java工程,命名爲TestRTIJob,然後右鍵單擊這個工程並選擇屬性,會彈出如圖52所示的窗口,單擊Library標籤,然後把下載的Axis的JAR文件加入進來。


圖52:添加外部JAR文件
圖52:添加外部JAR文件  

2. 然後從Eclipse中選擇Run ' Run..,會彈出如下圖所示的對話框,選擇程序運行的類別爲Java Application,然後單擊按鈕Search;


圖53:新建一個運行實例
圖53:新建一個運行實例  

3.如下圖所示,從彈出的對話框中選擇類WSDL2Java,這個類是Axis提供的用來從WSDL生成本地Stub類的工具。然後單擊OK按鈕;


圖54:選擇運行主類
圖54:選擇運行主類  

3. 然後在Argument標籤中輸入我們剛纔部署好的Web Service的WSDL文件的地址,如圖55所示,然後單擊按鈕Run;


圖55:運行WSDL2Java
圖55:運行WSDL2Java  

4. 如圖56所示,運行結束後,我們會看到我們創建的工程裏面生成了一些類,這些類就是輔助我們調用Web Service的Stub類;


圖56:生成的Stub類
圖56:生成的Stub類  

5.我們接下來新建一個叫做TestRTIJob類來通過生成的Stub類來進行調用Web Service,這個類的源代碼如下所示:


清單1:調用Web Service
package com.ascential.rti.sample;
            import java.rmi.RemoteException;
            import javax.xml.rpc.ServiceException;
            public class TestRTIJob {
            public static void main(String[] args){
            SampleLocator locator = new SampleLocator();
            SampleDOCLIT service = null;
            try {
            service = locator.getsampleSoap();
            String name = service.RTIJob("001");
            System.out.println("The name is: " + name);
            } catch (ServiceException e) {
            e.printStackTrace();
            } catch (RemoteException e) {
            e.printStackTrace();
            }
            }
            }
            

運行這個類,控制檯會打印出一串字符串:The name is Jason,這說明我們成功的調用了Web Service,我們的RTI Job也成功的完成了我們所設計的業務邏輯。關於這個Java工程的詳細信息,讀者可以在文章的下載部分下在提供的整個工程的源代碼。

至此,我們已經完成了從開發RTI Job到部署RTI Job再到用Java Client調用部署的Web Service的整個過程。



總結

本文首先介紹了什麼是RTI Job以及RTI Job的特點,然後通過開發、部署RTI Job使讀者對RTI Job有了更進一步的瞭解,最後通過開發一個Java客戶端對Web Service進行調用來結束了整個文章的講述。在面向服務的架構日益成熟的今天,通過把ETL Job發佈成Web Service供企業的其他應用程序進行調用無疑會是一個非常有價值的工作,從而使企業數據整合與企業的面向服務的架構實現了無縫的融合。希望本片文章對使用DataStage進行數據整合的讀者有所幫助。



參考資料

  1. 瞭解關於DataStage產品的更多信息:http://ibm.ascential.com/
  2. Eclipse官方網站:http://www.eclipse.org/
  3. 下載最新版本的JDK:http://java.sun.com/javase/downloads/index.jsp
  4. Axis官方網站:http://ws.apache.org/axis/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章