題注:
發表這篇解決方案,屬于非盈利目的。主要是為了讓大家了解一種接口技術解決方案文檔的編寫格式以及讓大家評審在我的這個技術解決方案中的不足之處,以便大家指出并加以改進。
轉載,下載或與各種形式使用這篇文章,必須注明文章的作者,出處。
其他未盡事宜,以國家法律規定的為準!
作者:南瘋
在Web Service的調用過程中,無論是外協系統還是施工系統,都有發送數據和接收數據的要求,也即雙方系統同時作為客戶端又作為服務端。我們統稱這些傳遞的數據為報文。
客戶端發送報文,屬于調用;服務端接收報文,屬于被調用。
客戶端和服務端互相之間通訊的請求報文和結果報文遵循XML格式。客戶端發送請求報文,服務器解析調用報文,執行報文中所在接口對應的服務功能。生成結果報文,以xml格式頁返回給請求者。請求者拿到結果報文,進行解析,然后再進行相應的處理。
u 報文中所有的字典信息(比如性別1-男,2-女),都以代碼的值(1或者2)來傳遞。施工單位向外協系統發送的報文中的代碼都需要轉換成外協的代碼,外協系統向施工系統發送的報文中的代碼無需轉換。
u 報文中的其他數據類型,比如貨幣、RowID,自定義對象類型等,根據需要轉換成文本、數值或二進制(最終轉換成Base64字符)的數據類型。
u 報文中數值信息,轉換成文本,如:
<ItemCount>50</ItemCount>
<ValueSum>12368.36</ValueSum>
u 報文中數值不支持科學計數的方式。報文中數值的單位使用國標的單位,比如貨幣使用“元”,長度使用“米”等。無國標的單位以約定為準。
u 報文中的日期信息,轉換成YYYYMMDD HHmmss文本格式(24小時制)。如果是空日期,則轉換成空文本。
u 報文中的true和false數據類型,轉換成 0(表示false)、1(表示true)
u 報文中的二進制數據,轉換成Base64字符方式發送。
u 報文中的記錄集,放在< Records>標簽中;報文中一條記錄,放在< Records>標簽中。
u 報文中如果存在多條記錄,則在<Records>標簽中就包含多個的<Record>標簽。如果報文中僅有一條記錄,則<Records>標簽中只包含一個<Record>標簽.如果沒有記錄,則僅僅包含一個<Records>標簽,沒有<Record>標簽。
u 如果返回結果數據集非常多,在性能考慮和數據量沖突的情況下,可以使用分頁返回數據集的方式分批返回數據(每次返回最多100條記錄)。服務端提供分批結果返回的功能。至于如何使用分頁查詢的功能,參見下面的XML框架說明。
施工系統向外協系統發送請求的數據目前有幾點需要考慮:
u 如何請求查詢一個業務數據
u 如何新增一條記錄,新增之后如何點到記錄的鍵值
u 如何修改一條記錄
u 如何刪除一條記錄
u 文檔如何上傳
u 一條記錄中一個FileID的字段如何上傳多個文件
u 如何在一條記錄中補充上傳文檔
u 如何在一條記錄中刪除一個文檔
u 如何獲得文檔的基本信息
u 如何獲得文檔的所有兄弟信息
u 如何獲得文檔的所有父親信息
u 如何下載一個文檔
針對這些問題,接口方案的解決方法如下:
施工系統針對外協系統發送的業務數據查詢請求根據業務類型有很多種。為了簡化接口,而不是在接口上進行業務操作,所以,外協系統將施工系統發起的數據查詢請求看作是數據下載的一種方式,而不為了復雜的業務查詢請求提供復雜的條件解析。
外協系統提供的數據查詢接口是從數據下載和數據延期性來考慮的。為了滿足數據的下載,外協系統提供了按照某一個表的主鍵來下載數據和按照記錄的變更時間范圍來下載數據的兩種方式查詢請求。
請求報文:
<?xml version="1.0" encoding="utf-8" ?>
<XmlData>
<UserInfo>
<User>ZhangSan</User>
<PassWord>123456</PassWord>
</UserInfo>
<Description>
<RowID>0</RowID>
<KeyValue>123</KeyValue>
<QueryBeginTime>20061018 153000</QueryBeginTime>
<QueryEndTime>20061019 153000</QueryEndTime>
</Description>
</XmlData>

響應報文:
<?xml version="1.0" encoding="utf-8"?>
<XmlData>
<Description>
<RowID>100</RowID>
</Description>
<Records>
<Record>
<Field1>Value1</Field1>
<Field2>Value2</Field2>
<Field3>Value3</Field3>
<Field4>Value4</Field4>
</Record>
<Record>
<Field1>Value1</Field1>
<Field2>Value2</Field2>
<Field3>Value3</Field3>
<Field4>Value4</Field4>
</Record>
<Record>
<Field1>Value1</Field1>
<Field2>Value2</Field2>
<Field3>Value3</Field3>
<Field4>Value4</Field4>
</Record>
</Records>
</XmlData>

報文說明:
標簽名
|
說明
|
<XmlData>
|
報文數據主體
|
<Description>
|
報文頭部信息
|
<Records>
|
記錄集合
|
<Record>
|
一行記錄
|
<UserInfo>
|
業務認證的用戶信息
|
<User>
|
業務用戶登錄名
|
<PassWord>
|
業務用戶驗證口令
|
<RowID>
|
第一次請求的時候,客戶端RowID發送0,表示從第0條記錄開發返回。服務端根據條件查詢,發現結果超過100條記錄,則在返回的結果中,RowID的值為99,表示服務端當前的記錄位置處在第100條的位置上,后面還會有剩余的記錄。客戶端檢查返回的結果,如果發現RowID大于0,則繼續發送請求進行查詢。但是,客戶端第二次發送請求繼續查詢的時候,RowID的值要賦值為第一次返回的值,即RowID=99。服務端第二次收到請求的時候,發現RowID是99,則從第100條返回結果。以此類推循環調用,直到服務端達到記錄的末尾,這時候,服務端在返回的結果中RowID=0.客戶端發現服務端RowID=0,終止循環調用。
字典、用戶信息、單位信息,因為返回的字段比較少,不受100條記錄返回的限制。一次調用,就返回全部的結果。
|
<KeyValue>
|
查詢時主鍵的值。這個<KeyValue>和下面的<QueryBeginTime><QueryEndTime>是互斥的。如果在請求的時候提供了主鍵的值,表示客戶端要求服務器按照主鍵的值查詢一條記錄。如果客戶端提供了主鍵的值,則服務端將忽略<QueryBeginTime><QueryEndTime>中的值。
字典、用戶信息、單位信息,因為沒有查詢時間范圍,所以<KeyValue>即表示字典類型。
|
<QueryBeginTime>
<QueryEndTime>
|
查詢時時間段范圍。<QueryBeginTime>是起始時間,<QueryEndTime>是結束時間。表示客戶端要求服務端查詢在這個時間范圍之內所有變更過的記錄(包括新增、修改、刪除)。
在外協中,一條記錄新增的時候,它的創建時間和最后修改時間是一樣的,以后修改記錄的時候,創建時間不變,改變的僅僅是最后修改時間。同時,外協系統中刪除記錄僅僅在“記錄是否刪除”字段中標記“1”,并不是真正的物理刪除記錄。
這里的時間指的是記錄變更的時間,不是記錄中的某個業務時間。如果用戶需要按照業務時間來查詢數據,則施工系統把外協系統的數據獲取到本地進行保存,在施工系統中提供按照業務時間查詢的功能。
<QueryBeginTime><QueryEndTime>和<KeyValue>是互斥的。如果客戶端需要按照時間范圍來查詢,則必須<KeyValue>空。
|
<Field1>
<Field2>
<Field3>
<Field4>
|
一行記錄中的英文字段名稱。實際中,這些標簽都是字典的英文名。字段的標簽全部是大寫。
具體的字段名稱請參見提供的數據模型
|
為了簡化數據模型的處理,本方案不考慮主從表的并發處理情況。如果存在主從表的數據需要上傳,那么,在一個事務中,施工單位首先先上傳主表的記錄,從反饋信息中獲得主表的主鍵值。然后,把剛剛獲得的主表的主鍵值賦值給從表的對應外鍵,再上傳從表數據,得到從表的主鍵值。
如果不是主從表,而是單表,則直接上傳數據,從反饋信息中得到主鍵值。
這種情況的優點是:數據和表相關,施工單位可以靈活的控制表之間的關系;同時,數據包中的報文比較簡單,容易解析;接口上面比較清晰,與業務的耦合比較低。
缺點是:一個業務涉及的主從表不能在同一個報文中(這個缺點可以通過施工系統靈活的控制表之間關系來解決);一個業務中可能會使用到兩個或兩個以上的接口,造成業務完整性上面的分離(這種缺點可以通過把業務放在一個事務中來解決);
鍵值的返回:在調用新增接口之后,外協會按照記錄的順序返回外外協中所生成的鍵值。 施工單位獲得鍵值之后,可以在本地表中更新記錄的主鍵值。
請求報文:
<?xml version="1.0" encoding="utf-8"?>
<XmlData>
<UserInfo>
<User>ZhangSan</User>
<PassWord>123456</PassWord>
</UserInfo>
<Description>
<Note>開工報告</Note>
</Description>
<Records>
<Record>
<KeyField></KeyField>
<NormalField1>Value1</NormalField1>
<NormalField2>Value2</NormalField2>
<NormalField3>Value3</NormalField3>
<NormalField4>Value4</NormalField4>
</Record>
<Record>
<KeyField></KeyField>
<NormalField1>Value1</NormalField1>
<NormalField2>Value2</NormalField2>
<NormalField3>Value3</NormalField3>
<NormalField4>Value4</NormalField4>
</Record>
</Records>
</XmlData>

響應報文:
<?xml version="1.0" encoding="utf-8"?>
<XmlData>
<Description>
<Result>成功</Result> <!--如果失敗,則<Result>里面內容是:失敗:(錯誤原因)-->
</Description>
<Records>
<Record>
<KeyField>Value1</KeyField>
</Record>
<Record>
<KeyField>Value2</KeyField>
</Record>
</Records>
</XmlData>


報文說明:
標簽名
|
說明
|
<XmlData>
|
報文數據主體
|
<Description>
|
報文頭部信息
|
<Records>
|
記錄集合
|
<Record>
|
一行記錄
|
<UserInfo>
|
業務認證的用戶信息
|
<User>
|
業務用戶登錄名
|
<PassWord>
|
業務用戶驗證口令
|
<Note>
|
業務的簡單描述。比如:開工報告、施工組織方案 等
|
請求中的<KeyField>
|
一行記錄中的主鍵字段。在新增的時候,施工系統所給的主鍵字段內容為空。外協系統中根據主鍵字段內容為空,認為這是一條新增的記錄
|
響應中的<KeyField>
|
一行記錄中的主鍵字段。外協系統返回的主鍵值。這里的主鍵值和施工系統發送的記錄的順序是一一對應的。
|
<Result>
|
反饋報文中的保存成功與否信息。
如果保存成功,則信息是“成功”
如果保存失敗,則信息是“失敗:(后面是錯誤的詳細信息)”
|
|
|
|
|
|
|