項目地址:https://github.com/hjx601496320/transmitjava
在平常開發工做中,咱們常常會遇到要和各類第三方調試接口的狀況,若是是簡單的幾個接口還好,代碼寫起來很快就寫好了。可是若是在某一種業務狀況下,好比支付,咱們對接了不少家第三方的支付公司,每一家的支付接口都不同,這時就須要針對多家不一樣的接口文檔編寫不一樣的代碼。又或者咱們做爲接口提供方提供一套標準的接口,可是某些客戶會比較強硬,要求你提供的接口須要按照對方的要求來作,這時就又須要苦哈哈的寫一個適配他們的代碼。這個過程就十分的難受了。linux
我所在的項目就遇到了這種問題,我在的項目是作保險業務的,如今須要對接多家保險公司的接口,每家數據仍是那些常見的數據,可是數據結構都不相同。有些是XML的,有些是JSON的。像性別,證件類型的枚舉值也都不大相同。git
因此根據現有的狀況,我開發了一個HTTP接口適配工具。用於支持各類類型的HTTP接口轉發,轉換請求數據,轉換響應數據的需求。github
由於是一個已經開發完成的工具,在公司項目中使用良好。下面說一下如何使用。web
git clone https://github.com/hjx601496320/transmit.git cd transmit/ mvn package cd target/ //解壓 tar -zxvf transmit.tar.gz //啓動 sh bin/start.sh
這裏啓動用的是linux的腳本,由於Windows腳本我不會寫,因此只有linux的。數據庫
也能夠在項目中直接啓動Main.java中的main方法。json
├── bin 啓動腳本 │ ├── restart.sh 重啓 │ ├── start.sh 啓動 │ └── stop.sh 中止 ├── config 配置 │ ├── config.json 啓動時加載的配置文件 │ └── logback.xml 日誌配置,使用logback ├── lib │ ├── commons-cli-1.4.jar 依賴,本身添加的插件jar能夠放在這裏 ...... │ ├── transmit-1.0-SNAPSHOT.jar │ ├── vertx-web-client-3.8.0.jar │ └── vertx-web-common-3.8.0.jar ├── log 日誌 │ ├── debug │ │ └── debug.2019-09-17.log │ ├── error │ │ └── error.2019-09-17.log │ └── info │ └── info.2019-09-17.log └── sout.log 啓動時輸出的日誌
{ 其餘配置 "config": { 是否緩存模板文件,默認true. 關閉的話每次請求會從新加載模板,方便調試. "cache": true, 系統端口號 "port": 9090, 引用其餘的配置文件的文件路徑 "import": [ ], 其餘組件加載, 執行CLass.forName, 能夠加載本身定義的一些插件, 完成相似數據入庫, 接口簽名之類的功能 "ext": [ "com.hebaibai.ctrt.Driver" ], 數據庫配置, 用於保存接口請求日誌 "db": { "host": "127.0.0.1", "database": "dbname", "port": 3306, "username": "root", "password": "root" } }, 配置示例 "config-demo": { 接受請求 "request": { 接受請求的地址 127.0.0.1:9090/download "path": "/download", 請求的方式 "method": "GET", 請求參數類型: FORM(表單提交), JSON(json), QUERY(?key=value&key2=value), TEXT(文本), XML(xml), "request-type": "QUERY", 返回參數類型 "response-type": "TEXT" }, 轉發的接口配置 "api": { 接口請求地址 "url": "http://127.0.0.1:9003/api/download", 插件編號, 在ext中加載來的 "extCode": "null", 接口請求地址 "method": "GET", 請求參數類型 "request-type": "QUERY", 請求超時設置,默認3000 ms, 單位ms "timeout": 1, 返回參數類型 "response-type": "TEXT", 請求參數轉換模板 "request-ftl": "/home/hjx/work/transmit/file/download-req.ftl", 響應參數轉換模板 "response-ftl": "/home/hjx/work/transmit/file/download-res.ftl" } } }
這裏說一下,好比須要根據一個第三方接口添加一個轉換, 第三方接口信息以下:api
請求地址:http://xxx.xxx.com/text/getOrder緩存
請求方式:POST數據結構
參數類型:JSON
參數示例:
接口請求參數 { "header": { "code": "123123123", "date": "2019-09-19 14:28:57" }, "body": { "orderCode": "O1231231231231231" } } 接口返回參數 { "code":1 "msg":"success" }
而你可以發送的數據是這樣的:
請求方式:POST
參數類型:XML
參數示例:
請求數據 <Demo> <Info> <Code>XXX-1</Code> <UUID>d83a011a-958d-4310-a51b-0fb3a4228ef5</UUID> <Time>2017-11-15 16:57:36</Time> </Info> <Order> <SerialNo>0</SerialNo> <OrderNo>123123123</OrderNo> <OrderCode>asdasdasd</OrderCode> <Result>1</Result> </Order> </Demo> 須要返回的數據 <Demo> <Info> <Code>1</Code> </Info> <Order> <Msg>success</Msg> </Order> </Demo>
這時你須要添加以下配置
{ "config":{ "port":9527, "import":[ ], "ext":[ ], "db":{ "host":"127.0.0.1", "database":"dbname", "port":3306, "username":"root", "password":"root" } }, "getOrder":{ "request":{ "path":"/getOrder", "method":"POST", "request-type":"XML", "response-type":"XML" }, "api":{ "url":"http://xxx.xxx.com/text/getOrder", "method":"POST", "request-type":"JSON", "response-type":"JSON", "request-ftl":"/home/hjx/work/transmit/file/getOrder-req.json", "response-ftl":"/home/hjx/work/transmit/file/getOrder-res.xml" } } }
{ "header": { "code": "${ROOT.Info.Code}", "date": "${ROOT.Info.Time}" }, "body": { "orderCode": "${ROOT.Order.OrderCode}" } }
<Demo> <Info> <Code>${ROOT.code}</Code> </Info> <Order> <Msg>${ROOT.msg}</Msg> </Order> </Demo>
配置完成後,啓動transmit,向http://127.0.0.1:9527/getOrder發送post請求,就能夠轉換你的請求參數,並完成對http://xxx.xxx.com/text/getOrder接口的調用了。
原始數據:
<Demo> <Info> <Code>XXX-1</Code> <UUID>d83a011a-958d-4310-a51b-0fb3a4228ef5</UUID> <Time>2017-11-15 16:57:36</Time> </Info> <Order> <SerialNo>0</SerialNo> <OrderNo>123123123</OrderNo> <OrderCode>asdasdasd</OrderCode> <Result>1</Result> </Order> </Demo>
對應的節點
${ROOT.Info.Code}=XXX-1 ${ROOT.Info.UUID}=d83a011a-958d-4310-a51b-0fb3a4228ef5 ${ROOT.Info.Time}=2017-11-15 16:57:36 ${ROOT.Order.SerialNo}=0 ${ROOT.Order.OrderNo}=123123123 ${ROOT.Order.OrderCode}=asdasdasd ${ROOT.Order.Result}=1
插件有兩種。
是實現接口com.hebaibai.ctrt.transmit.util.ext。這個接口能夠處理一些簽名之類的操做,其中有四個方法。
/** * 用於判斷是否使用該插件,extCode爲配置文件中的配置 * @param extCode * @return */ boolean support(String extCode); /** * 獲取插件編號 * * @return */ String getCode(); /** * 在api請求前前執行 * * @param value 完整的數據 * @param valueMap 放進freemarker的數據 * @return 插件處理後的數據 */ String beforRequest(String value, Map<String, Object> valueMap) throws Exception; /** * 在api響應後執行 * * @param value 完整的數據 * @param valueMap 放進freemarker的數據 * @return */ String afterResponse(String value, Map<String, Object> valueMap) throws Exception;
單獨新建項目,實現該接口,添加一個類:
package com.hebaibai.ctrt; import com.hebaibai.ctrt.ext.sign.PICC_XM_testSign; import com.hebaibai.ctrt.transmit.util.CrtrUtils; /** * 驅動 */ public class Driver { /** * 將插件添加進項目 */ static { System.out.println("加載 簽名插件..."); CrtrUtils.EXT_LIST.add(你編寫的插件實例對象); } }
以後將這個項目單獨打成jar包,放進項目的lib文件夾中。以後修改配置:
。。。 "ext":[ "com.hebaibai.ctrt.Driver" ], 。。。
就完成了。
添加freemarker自定義指令,操做和上面的插件差很少,須要實現freemarker.template.TemplateDirectiveModel接口,而後
package com.hebaibai.ctrt; import com.hebaibai.ctrt.ext.sign.PICC_XM_testSign; import com.hebaibai.ctrt.transmit.util.CrtrUtils; /** * 驅動 */ public class Driver { /** * 將插件添加進項目 */ static { System.out.println("加載 簽名插件..."); CrtrUtils.EXT_LIST.add(你編寫的插件實例對象); //freeMarker 自定義指令 CrtrUtils.FREEMARKER_DIRECTIVE_MODEL.put("has", new Has()); } }
就完成了。