通用轉(zhuǎn)換接口設(shè)計(jì)

通用轉(zhuǎn)換接口設(shè)計(jì)


目錄

  • 轉(zhuǎn)換接口的定義
  • 轉(zhuǎn)換接口的作用
  • 轉(zhuǎn)換接口的使用
  • 轉(zhuǎn)換接口的實(shí)現(xiàn)

1. 轉(zhuǎn)換接口的定義

接口是系統(tǒng)內(nèi)部與第三方系統(tǒng)協(xié)議數(shù)據(jù)的相互轉(zhuǎn)換處理過程,轉(zhuǎn)換接口以XML配置的形式把這種處理過程描述出來弃舒,方便接口的開發(fā)與維護(hù)乘凸;


2. 轉(zhuǎn)換接口的作用

  • 增加開發(fā)效率椎扬,轉(zhuǎn)換接口抽象出通用的轉(zhuǎn)換處理馍管,開發(fā)只需組裝對應(yīng)轉(zhuǎn)換操作即可去团,減少了重復(fù)開發(fā)的工作寞秃,增加開發(fā)效率瑰枫;
  • 降低出錯率踱葛,統(tǒng)一協(xié)議轉(zhuǎn)換之外的處理,接口開發(fā)只需配置相應(yīng)的轉(zhuǎn)換處理光坝,減少代碼量尸诽,降低出錯概率;
  • 減少維護(hù)成本教馆,接口配置化后逊谋,對接口協(xié)議的調(diào)整,只需要針對接口配置修改即可土铺;

3. 轉(zhuǎn)換接口的使用

接口配置以XML文件描述胶滋,XSD文件定義節(jié)點(diǎn)結(jié)構(gòu),節(jié)點(diǎn)分為轉(zhuǎn)換接口和擴(kuò)展節(jié)點(diǎn)悲敷,轉(zhuǎn)換節(jié)點(diǎn)用于做數(shù)據(jù)轉(zhuǎn)換處理究恤,可擁有多個子節(jié)點(diǎn),一般先執(zhí)行父節(jié)點(diǎn)后德,后執(zhí)行子節(jié)點(diǎn)部宿,執(zhí)行方式有順序、選擇瓢湃、循環(huán)理张,子節(jié)點(diǎn)如果出現(xiàn)異常,父節(jié)點(diǎn)可捕獲做處理绵患;擴(kuò)展節(jié)點(diǎn)用于對接口配置或轉(zhuǎn)換節(jié)點(diǎn)擴(kuò)展使用雾叭;

3.1 接口配置說明

轉(zhuǎn)換定義文件:有XSD文件表示,定義具體轉(zhuǎn)換節(jié)點(diǎn)落蝙,需描述節(jié)點(diǎn)名稱织狐、參數(shù)名稱,參數(shù)類型和轉(zhuǎn)換處理類筏勒;

<!--MD5加密-->
    <xsd:element name="md5">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="nestedConverterType">
                    <!--MD5處理類-->
                    <xsd:attribute name="clazz" type="xsd:string" 
                    fixed="com.nnk.ecsys.interfaceConverter.converter.Md5Converter"/>
                    <!--加密字符串-->
                    <xsd:attribute name="value" type="paramType" use="required"/>
                    <!--編碼類型-->
                    <xsd:attribute name="charsetType" type="paramType" use="optional"/>
                    <!--大小寫類型-->
                    <xsd:attribute name="caseType" type="caseType" use="optional" 
                    default="LowerCase"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

轉(zhuǎn)換節(jié)點(diǎn):由XML節(jié)點(diǎn)表示移迫,做具體的轉(zhuǎn)換處理,可有多個輸入?yún)?shù)和一個輸出參數(shù)管行,輸入?yún)?shù)由具體轉(zhuǎn)換節(jié)點(diǎn)定義厨埋,屬性name表示輸出參數(shù),轉(zhuǎn)換結(jié)果以name值作為名稱存入【上下文變量】捐顷;

輸入?yún)?shù):值可直接用字符串表示揽咕,如需引用【上下文變量】則使用${變量名}表示悲酷,還可以相互組合, 如:value="${參數(shù)2} AAA ${參數(shù)2}"亲善,如需要引用對象的參數(shù)设易,則使用${變量名.參數(shù)名}表示,基本用法和EL表達(dá)式類似蛹头;

擴(kuò)展節(jié)點(diǎn):可自定義擴(kuò)展節(jié)點(diǎn)顿肺,針對接口配置或轉(zhuǎn)換節(jié)點(diǎn)做處理,現(xiàn)有擴(kuò)展節(jié)點(diǎn)渣蜗,import可導(dǎo)入其他接口配置屠尊,loadProperty可加載properties文件變量;

示例:
interface-trade.xml

<?xml version="1.0" encoding="UTF-8"?>
<converter xmlns="http://www.007ka.com/schema/converter"
           xmlns:extend="http://www.007ka.com/schema/converter/extend"
           xmlns:interface="http://www.007ka.com/schema/converter/interface">
    <!--導(dǎo)入配置文件-->
    <extend:loadProperty location="properties/common.properties"/>
    <!--定義請求對象-->
    <getRequest name="request"/>
    <!--組裝請求報文-->
    <interface:tryException errorCode="CEC_FAILED" errorMsg="請求報文組裝異常">
        <!--轉(zhuǎn)換參數(shù)-->
        <set name="orderReq" value="${request.reqeustParam}" />
        <interface:mapget name="cardType" key="${orderReq.providerId}" mappingName="providerMap"/>
        <!--組裝協(xié)議-->
        <set name="orderInfo" 
            value="${nnk_merId}|${orderReq.orderId}|${cardType}|${orderReq.unitCount}|"/>
        <interface:md5 name="sign" value="${orderInfo}|${inter_channelKey}" 
            charsetType="${inter_charset}"/>
        <interface:newInstance name="httpParam" value="java.util.HashMap">
            <set name="httpParam.Orderinfo" value="${orderInfo}"/>
            <set name="httpParam.Sign" value="${sign}"/>
        </interface:newInstance>
    </interface:tryException>
    <!--調(diào)用http接口-->
    <interface:tryException errorCode="CEC_UNKNOWN" errorMsg="網(wǎng)絡(luò)異常">
        <interface:http name="httpResponse" url="${inter_interUrl}" 
            paramMap="${httpParam}" charsetType="${inter_charset}"/>
    </interface:tryException>
    <!--解析響應(yīng)報文-->
    <interface:tryException errorCode="CEC_UNKNOWN" errorMsg="響應(yīng)報文解析異常">
        <!--解析報文-->
        <interface:xmlToMap name="mapRes" value="${httpResponse}" />
        <set name="mapRes" value="${mapRes.root}"/>
        <!--協(xié)議驗(yàn)簽-->
        <interface:verifyMd5 charsetType="${inter_charset}" sign="${mapRes.Sign}" 
            value="${mapRes.MerID}|${mapRes.OrderID}|${mapRes.TranStat}|${inter_channelKey}"/>
        <!--組裝響應(yīng)對象-->
        <interface:newInstance name="orderRes" 
            value="com.nnk.ecsys.database.mapper.order.entity.ExternOrderOrderInfo">
            <set name="orderRes.orderId" value="${mapRes.OrderID}"/>
            <set name="orderRes.partnerOrderId" value="${mapRes.TranOrder}"/>
            <set name="orderRes.partnerOrderReceiveErrorCode" value="${mapRes.TranStat}"/>
            <set name="orderRes.partnerOrderReceiveErrorMsg" value="${mapRes.TranInfo}"/>
        </interface:newInstance>
    </interface:tryException>
    <!--返回響應(yīng)結(jié)果-->
    <setResponse value="${orderRes}"/>
</converter>

TestMain.java

//接口配置資源
Resource resource = ResourceUtils.getResource("interface-trade.xml");
//轉(zhuǎn)換構(gòu)建器
ConverterStackerBuilder converterStackerBuilder = new DefaultConverterStackerBuilder();
//創(chuàng)建轉(zhuǎn)換器
ConverterStacker converterStacker = converterStackerBuilder.buildConverterStacker(resource);
//執(zhí)行轉(zhuǎn)換
Order.ExternOrderInfo tradeRequest= Order.ExternOrderInfo.getDefaultInstance();
ExternOrderOrderInfo tradeResponse = (ExternOrderOrderInfo) converterStacker.invoke(tradeRequest);

4. 轉(zhuǎn)換接口的實(shí)現(xiàn)

4.1 配置文件的解析與擴(kuò)展

DefinitionReader            // 配置讀取類耕拷,讀取解析接口配置文件
NamespaceHandler            // 命名空間處理類讼昆,包含命名空間內(nèi)每個節(jié)點(diǎn)的解析對象
NamespaceHandlerResolver    // 命名空間管理類,管理每個命名空間的XSD文件路徑和處理類
DefinitionParser            // 節(jié)點(diǎn)解析類骚烧,解析具體的轉(zhuǎn)換節(jié)點(diǎn)或擴(kuò)展節(jié)點(diǎn)
ConverterDefinition         // 轉(zhuǎn)換節(jié)點(diǎn)定義信息類浸赫,包含返回值名稱,參數(shù)列表赃绊,轉(zhuǎn)換執(zhí)行類名既峡,子節(jié)點(diǎn)列表等信息
ConverterDefinitionContext  // 轉(zhuǎn)換定義上下文信息類,包含轉(zhuǎn)換節(jié)點(diǎn)結(jié)構(gòu)信息碧查,常量參數(shù)對象等信息

處理流程:

1.DefinitionReader讀取接口配置运敢,遞歸解析節(jié)點(diǎn)信息,

2.根據(jù)節(jié)點(diǎn)命名空間調(diào)用NamespaceHandlerResolver獲取指定NamespaceHandler處理

2.NamespaceHandler內(nèi)部根據(jù)節(jié)點(diǎn)名稱獲取對應(yīng)的DefinitionReader

3.DefinitionReader解析完成后把ConverterDefinition返回DefinitionReader忠售,并存入ConverterDefinitionContext中

4.遞歸解析完成后最后得到ConverterDefinitionContext對象

擴(kuò)展說明:

1.添加擴(kuò)展節(jié)點(diǎn)解析類DefinitionParser传惠,解析方法可獲取ConverterDefinitionContext對象,可自定義轉(zhuǎn)換節(jié)點(diǎn)稻扬,或?qū)涌谂渲没蜣D(zhuǎn)換節(jié)點(diǎn)做擴(kuò)展處理涉枫;

2.添加命名空間處理類NamespaceHandler,描述節(jié)點(diǎn)名稱與DefinitionParser解析類對應(yīng)關(guān)系

3.添加擴(kuò)展配置信息腐螟,在目錄META-INF.converter下添加擴(kuò)展配置:XSD文件、handlers.properties困后、schemas.properties乐纸,在NamespaceHandlerResolver對象初始化的時候,會讀取運(yùn)行環(huán)境下所有Jar下此目錄的擴(kuò)展文件摇予;

            XSD文件:定義擴(kuò)展節(jié)點(diǎn)結(jié)構(gòu)信息汽绢,以及指明命名空間名稱
handlers.properties:描述命名空間與之對應(yīng)的NamespaceHandler類
 schemas.properties:描述命名空間與之對應(yīng)的XSD文件路徑

4.2 轉(zhuǎn)換器的構(gòu)建

ConverterDefinitionContext  // 轉(zhuǎn)換定義上下文信息類,包含轉(zhuǎn)換節(jié)點(diǎn)結(jié)構(gòu)信息侧戴,常量參數(shù)對象等信息
ConverterStacker            // 轉(zhuǎn)換器宁昭,執(zhí)行具體的轉(zhuǎn)換操作
Converter                   // 轉(zhuǎn)換節(jié)點(diǎn)執(zhí)行類
ConverterStackerBuilder     // 轉(zhuǎn)換器構(gòu)建類

處理流程:

1.通過DefinitionReader讀取接口配置跌宛,得到ConverterDefinitionContext;

2.ConverterStackerBuilder遞歸遍歷ConverterDefinition积仗,通過ConverterDefinition實(shí)例化Converter對象疆拘;

3.在Converter實(shí)例化過程,將會把Converter參數(shù)列表中存在的部分常量引用寂曹, 根據(jù)ConverterDefinitionContext常量列表設(shè)置為具體的值哎迄;

4.遍歷完成后,每個Converter對象會有一個父節(jié)點(diǎn)喝多個子節(jié)點(diǎn)隆圆,形成樹形架構(gòu)的Converter集合漱挚;

5.最后使用Converter集合構(gòu)建ConverterStacker對象;

4.3 轉(zhuǎn)換器執(zhí)行過程

ConverterStacker            // 轉(zhuǎn)換器渺氧,執(zhí)行具體的轉(zhuǎn)換操作
Converter                   // 轉(zhuǎn)換節(jié)點(diǎn)執(zhí)行類
ConverterRequest            // 轉(zhuǎn)換請求對象旨涝,作為執(zhí)行過程中變量存儲對象

處理流程:

1.接受轉(zhuǎn)換請求,組裝ConverterRequest侣背;

2.執(zhí)行開始白华,把根轉(zhuǎn)換節(jié)點(diǎn)倒序放入執(zhí)行棧中,然后循環(huán)出棧執(zhí)行Converter秃踩;

3.在執(zhí)行的過程中衬鱼,根據(jù)ConverterRequest變量集合,實(shí)例化Converter的參數(shù)列表憔杨,如過程中存在未實(shí)例化的參數(shù)鸟赫,將會拋出異常;

4.參數(shù)列表實(shí)例化完成后消别, 把變量列表傳給Converter執(zhí)行轉(zhuǎn)換方法抛蚤,完成后把結(jié)果以name為變量名把結(jié)果存入ConverterRequest;

5.轉(zhuǎn)換執(zhí)行完成后寻狂,獲取當(dāng)前Converter的后續(xù)節(jié)點(diǎn)倒序存入執(zhí)行棧中岁经,注意:獲取后續(xù)節(jié)點(diǎn)的邏輯將由Converter本身實(shí)現(xiàn),超類默認(rèn)實(shí)現(xiàn)是獲取子節(jié)點(diǎn)蛇券,但如果像選擇缀壤、循環(huán)之類的結(jié)構(gòu),此方法邏輯將會重寫纠亚;

6.如在Converter執(zhí)行過程中出現(xiàn)異常塘慕,則會進(jìn)入異常捕獲處理分支,詳情看代碼蒂胞;

7.循環(huán)執(zhí)行到執(zhí)行棧為空時图呢,返回結(jié)果對象

4.4 上下文變量管理

ConverterRequest            // 轉(zhuǎn)換器請求對象
ConverterDefinitionContext  // 轉(zhuǎn)換定義上下文信息類,包含轉(zhuǎn)換節(jié)點(diǎn)結(jié)構(gòu)信息,常量參數(shù)對象等信息
AssemblyParam               // 裝配參數(shù)對象

處理流程:

詳情看代碼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛤织,一起剝皮案震驚了整個濱河市赴叹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌指蚜,老刑警劉巖乞巧,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異姚炕,居然都是意外死亡摊欠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門柱宦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來些椒,“玉大人,你說我怎么就攤上這事掸刊〖春幔” “怎么了鹰晨?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵谤饭,是天一觀的道長播歼。 經(jīng)常有香客問我,道長蚓炬,這世上最難降的妖魔是什么松逊? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮肯夏,結(jié)果婚禮上经宏,老公的妹妹穿的比我還像新娘。我一直安慰自己驯击,他們只是感情好烁兰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著徊都,像睡著了一般沪斟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上暇矫,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天主之,我揣著相機(jī)與錄音,去河邊找鬼李根。 笑死槽奕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的朱巨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼枉长,長吁一口氣:“原來是場噩夢啊……” “哼冀续!你這毒婦竟也來了琼讽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤洪唐,失蹤者是張志新(化名)和其女友劉穎钻蹬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凭需,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡问欠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粒蜈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顺献。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枯怖,靈堂內(nèi)的尸體忽然破棺而出注整,到底是詐尸還是另有隱情,我是刑警寧澤度硝,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布肿轨,位于F島的核電站,受9級特大地震影響蕊程,放射性物質(zhì)發(fā)生泄漏椒袍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一藻茂、第九天 我趴在偏房一處隱蔽的房頂上張望驹暑。 院中可真熱鬧,春花似錦捌治、人聲如沸岗钩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兼吓。三九已至,卻和暖如春森枪,著一層夾襖步出監(jiān)牢的瞬間视搏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工县袱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浑娜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓式散,卻偏偏與公主長得像筋遭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容