闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鎯у⒔閹虫捇鈥旈崘顏佸亾閿濆簼绨奸柟鐧哥秮閺岋綁顢橀悙鎼闂侀潧妫欑敮鎺楋綖濠靛鏅查柛娑卞墮椤ユ艾鈹戞幊閸婃鎱ㄩ悜钘夌;闁绘劗鍎ら崑瀣煟濡崵婀介柍褜鍏涚欢姘嚕閹绢喖顫呴柣妯荤垹閸ャ劎鍘遍柣蹇曞仜婢т粙鎮¢姘肩唵閻熸瑥瀚粈鈧梺瀹狀潐閸ㄥ潡銆佸▎鎴犵<闁规儳澧庣粣妤呮⒒娴e憡鍟炴い顓炴瀹曟﹢鏁愰崱娆屽亾濞差亝鍊垫鐐茬仢閸旀碍绻涢懠顒€鈻堢€规洘鍨块獮姗€鎳滈棃娑欑€梻浣告啞濞诧箓宕滃☉鈶哄洭顢橀悢铏圭槇闂佸啿鐨濋崑鎾绘煕閺囩偟浠涢柣銈勭铻栭柣姗€娼ф禒婊勪繆椤愶絿绠撴い鏇秮椤㈡岸鍩€椤掆偓閻g兘鎮℃惔顔惧數濡炪倕绻嬮悞锕€鈻嶆繝鍥ㄧ厵妞ゆ梻鐡斿▓婊堟煛娴g懓濮堥柟顖涙煥閳规垿宕煎┑鍡樼槗闂備浇顕уù鐑藉箠閹捐绠熼柨娑樺瀹曟煡鏌涢弴銊ュ箺妞ゎ偅娲熼弻鐔兼倻濡闉嶇紓鍌氱Т濞差參寮婚弴鐔虹闁割煈鍠栨慨銏ゆ⒑閼姐倕鏋傞柛鏂跨焸閳ユ棃宕橀鍢壯囧箹缁厜鍋撻懠顒€鍤紓鍌氬€风欢锟犲窗濡ゅ懎绠伴柟闂寸劍閸嬧晠鏌i幋锝嗩棄缁绢厸鍋撻梻浣虹帛閸旀洜绮旈崼鏇炵獥闁哄稁鍘肩粻鏍ㄧ箾閸℃ɑ灏紒鐙呯稻缁绘繈妫冨☉娆愭倷濡炪倧鑵归弲鐘差潖濞差亜绠柤鎭掑劜閺嗙娀姊洪幖鐐插婵犫偓閸楃倣锝夊箛閺夎法顔掗柣搴㈢⊕閿氭い搴㈡尰缁绘繂鈻撻崹顔界亶闂佺硶鏅涢悧濠勭矉瀹ュ應鏀介悗锝庝簽閻ゅ嫰姊洪棃娴ュ牓寮插☉銏″€峰┑鐘叉处閻撳繐鈹戦悙鑼虎闁逞屽墯椤ㄥ牏鍒掔拠宸僵妞ゆ帒顦扮€靛矂姊洪棃娑氬婵☆偅绋掗弲鍫曨敆閸曨剛鍘介梺鍝勫暞閸ㄥ灚鏅堕幘顔界厽闁瑰灝鍟晶瀛樸亜閵忊槅娈滅€规洘甯掕灃闁逞屽墯缁傚秵銈i崘鈺佷画濠电偛妫楃换鎰邦敂椤忓棛妫柣鎰靛墯閸婃劙鏌$仦鍓р姇闁诡垱妫冮弫鎰板幢濡崵妲楅梺璇插椤旀牠宕抽鈧畷鎴炵節閸モ晛绁﹀┑鈽嗗灥閸嬫劗澹曢崗闂寸箚妞ゆ牗绮庣敮娑欍亜韫囨洖鏋涙慨濠勭帛閹峰懘鎳為妷褋鈧﹪姊洪棃鈺冪Ф缂佺姵鎹囬悰顔跨疀濞戞瑦娅㈤梺璺ㄥ櫐閹凤拷婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繘鏌i幋锝嗩棄闁哄绶氶弻娑樷槈濮楀牊鏁鹃梺鍛婄懃缁绘﹢寮婚敐澶婄闁挎繂妫Λ鍕⒑閸濆嫷鍎庣紒鑸靛哺瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈嗐亜椤撶姴鍘寸€殿喖顭烽弫鎰緞婵犲嫮鏉告俊鐐€栫敮濠囨倿閿曞倸纾块柟鎯у绾捐棄霉閿濆懏鎯堢亸蹇涙⒑閸涘⿴娈曞┑鐐诧工椤曪絾绻濆顓炰簻闂佺ǹ绻愰惃鐑藉箯婵犳碍鐓熼幖娣妽濞懷冾熆閻熷府宸ラ崡杈ㄣ亜閺傚灝鈷旂痪鎹愭闇夐柨婵嗘噺閹牓宕幖浣光拺闁告縿鍎辨牎闂佺粯顨堟慨鎾敋閿濆棛绡€婵﹩鍎甸埡鍛厓闁告繂瀚埀顒€鎲$粋宥呪堪閸啿鎷洪梺鍛婄☉閿曪妇绮婚幘缁樺€垫慨姗嗗墯閸ゅ洤鈹戦鐟颁壕闂備線娼ч悧鍡椢涘☉銏犲偍闂侇剙绉甸埛鎴︽⒒閸喕鍎愮憸鐗堝笒绾惧潡姊洪鈧粔鎾倿閸偁浜滈柟鍝勬娴滄儳鈹戦悩顐壕闂備緡鍓欑粔瀵哥不閺屻儲鐓忛煫鍥ㄦ礀琚ュ┑鈩冨絻閻楁捇寮婚弴锛勭杸闁哄洨鍊姀銈嗙厾闁哄娉曟禒銏ゆ煃鐟欏嫬鐏撮柛鈹垮劦瀹曞崬螖閸愌勬▕濠碉紕鍋戦崐鏍р枖閿曞倸鐐婃い顓熷灦椤ュ鏌f惔锛勭暛闁稿酣浜惰棟濞村吋娼欓悡鏇㈡煙鐎电ǹ啸缁炬儳銈搁幃妤呮晲鎼粹€茶埅闂佺ǹ绨洪崕鐢稿蓟濞戞瑦鍎熼柕蹇曞Т椤海绱撴担浠嬪摵閻㈩垳鍋ら獮蹇涙偐鐠囪尙顔岄梺鍦劋閹稿顢欓幒鎴旀斀闁绘ɑ顔栭弳婊呯磼鏉堛劍绀嬬€殿噮鍋嗛幏鐘绘嚑椤掍焦顔曢梻浣虹帛濮婂鍩涢崼銉ユ瀬鐎广儱妫欓崣蹇斾繆椤栨哎浠掗柛姘煎亰閺屸剝寰勭€n偄鈧劖鎱ㄦ繝鍕笡闁瑰嘲鎳樺畷顐﹀Ψ閿旈敮鍋撻灏栨斀闁斥晛鍟ㄦ禒鐘绘煕閺傚潡鍙勬鐐茬箳閳ь剨缍嗛崰鏍嫅閻斿吋鐓忓璺虹墕閸斻倝鏌ㄥ☉娆戞创婵﹨娅i幉鎾礋椤愩値妲版俊鐐€栧▔锕傚炊瑜忛ˇ銊╂⒑闁偛鑻晶鎾煙椤旂厧妲绘顏冨嵆瀹曟﹢鎮欓鑺ョ€伴梺璇插椤旀牠宕板Δ鍛畺闁稿本鍑归崵鏇熴亜閺囨浜鹃悗瑙勬礀閵堟悂骞冮姀銈呬紶闁告洦鍋呮潏鍫ユ⒒閸屾艾鈧兘鎳楅崜浣稿灊妞ゆ牗顕㈠ú顏勫唨妞ゆ挾鍋熼敍娆撴⒑闂堚晛鐦滈柛妯绘倐瀹曟垿骞橀幇浣瑰兊闂佺粯鍔﹂崜娆擃敂閿燂拷
开发学院软件开发Java 消息中介的实用介绍——第 2 部分:使用中介路由消... 阅读

消息中介的实用介绍——第 2 部分:使用中介路由消息

 2009-10-21 00:00:00 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鎯у⒔閹虫捇鈥旈崘顏佸亾閿濆簼绨绘い鎺嬪灪閵囧嫰骞囬姣挎捇鏌熸笟鍨妞ゎ偅绮撳畷鍗炍旈埀顒勭嵁婵犲嫮纾介柛灞捐壘閳ь剛鎳撻~婵嬪Ω閳轰胶鐤呯紓浣割儐椤戞瑩宕ョ€n喗鐓曟い鎰靛亝缁舵氨绱撻崘鈺傜婵﹤顭峰畷鎺戔枎閹搭厽袦婵犵數濮崑鎾绘⒑椤掆偓缁夌敻骞嗛悙鍝勭婵烇綆鍓欐俊鑲╃磼閹邦収娈滈柡灞糕偓鎰佸悑閹肩补鈧尙鏁栧┑鐐村灦閹稿摜绮旈悽绋课﹂柛鏇ㄥ灠閸愨偓濡炪倖鍔﹀鈧繛宀婁邯濮婅櫣绱掑Ο璇茶敿闂佺ǹ娴烽弫璇差嚕婵犳碍鏅插璺猴工瀹撳棝姊虹紒妯哄缂佷焦鎸冲畷鎴﹀箻鐠囧弶宓嶅銈嗘尰缁嬫垶绂嶉悙顒佸弿婵☆垳鍘ф禍楣冩倵濮樼偓瀚�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鎯у⒔閹虫捇鈥旈崘顏佸亾閿濆簼绨奸柟鐧哥秮閺岋綁顢橀悙鎼闂侀潧妫欑敮鎺楋綖濠靛鏅查柛娑卞墮椤ユ艾鈹戞幊閸婃鎱ㄩ悜钘夌;婵炴垟鎳為崶顒佸仺缂佸瀵ч悗顒勬⒑閻熸澘鈷旂紒顕呭灦瀹曟垿骞囬悧鍫㈠幍缂傚倷鐒﹂敋缂佹う鍥ㄧ厓鐟滄粓宕滈敃鍌氱煑闁告劦鐓堝ḿ鏍煕濠靛棗鐝旂憸鏂跨暦閹偊妲炬繛瀵稿Т閵堢ǹ顫忛搹瑙勫珰闁肩⒈鍓涢澶愭⒑閻撳海绉虹紒鐘崇墵楠炲啯銈i崘鈺佲偓濠氭煢濡警妲奸柟鑺ユ礋濮婃椽妫冨☉杈€嗘繝纰樷偓铏枠鐎规洏鍨介幃浠嬪川婵炵偓瀚奸梺鑽ゅ枑閻熴儳鈧氨鍏樺畷顖濈疀濞戞瑧鍘遍梺缁樏壕顓熸櫠閻㈠憡鐓忛柛鈩冾殔閳ь剙婀辩紓鎾寸鐎n亜绐涙繝鐢靛Т鐎氼剟鐛崼銉︹拺缁绢厼鎳庨ˉ宥夋煙濞茶绨芥俊鍙夊姍瀵挳鎮㈤崫鍕ㄥ彏闂傚倸鍊搁崐椋庢濮橆兗缂氱憸宥囧弲闂侀潧鐗嗗ú鐘诲磻閹炬剚娼╂い鎰╁灩缁侇噣姊虹紒妯圭繁闁革綇缍侀悰顕€骞掗幊铏閸┾偓妞ゆ帒鍊绘稉宥夋煥濠靛棙顥犵紒鈾€鍋撻梻鍌氬€搁悧濠勭矙閹达箑姹叉繛鍡楃贩閻熸壋鍫柛顐犲灮閺嗩偊姊洪崫鍕効缂傚秳鐒﹂幈銊╁焵椤掑嫭鐓冮柟顖滃绾偓绻濋埀顒佹綇閵娧呭骄闂佸搫娲ㄩ崰鎾跺姬閳ь剙鈹戦鏂や緵闁告﹢绠栧畷銏ゆ偨閸涘ň鎷虹紓鍌欑劍閿氬┑顕嗙畵閺屾盯骞橀弶鎴濇懙闂佽鍠楄摫婵炵厧绻樻俊鎼佸Χ閸モ晝鏆伴梻鍌欑濠€杈╁垝椤栨粍鏆滈柣鎰摠濞呯姵绻涢幋鐐寸殤缁炬崘鍋愮槐鎾存媴鐠愵垳绱板┑鐐村絻椤曨參鍩€椤掑喚娼愭繛鍙夌墪閻g兘顢楅崘顏冪胺闂傚倷绀侀幉锟犲礉閺囥垹鐤柣妯款嚙缁€鍫熺節闂堟稓澧涚€规洖寮剁换娑㈠箣閻愩劎绱伴梺鍝勬濡鍩為幋锔藉亹閺夊牜鍋勯崢锟犳⒑鏉炴壆鍔嶉柣妤佺矌濡叉劙骞樼€涙ê顎撴繛瀵稿Т椤戝懘骞楅悽鍛娾拺闁革富鍘介崵鈧┑鐐茬湴閸婃繈骞冩ィ鍐╁€婚柦妯侯槺椤斿﹪姊虹憴鍕剹闁告ü绮欏畷鎾绘偨閸涘ň鎷洪梺鑽ゅ枑濠㈡﹢骞冩笟鈧弻锝夊箳閻愮數鏆ら梺璇″枟椤ㄥ﹪鐛弽銊﹀闁稿繐顦扮€氳棄鈹戦悙鑸靛涧缂佹彃娼″畷鏇㈠Χ婢跺﹤鎯為梺閫炲苯澧存慨濠冩そ楠炴牠鎮欏ù瀣壕闁哄稁鍘介崑瀣煟濡灝鍚圭€规挷绶氶悡顐﹀炊閵娧€濮囬梺鍝勬噺閹倿寮婚妸鈺傚亞闁稿本绋戦锟�濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻橀弻锝夊箣閿濆棭妫勯梺鍝勵儎缁舵岸寮诲☉妯锋婵鐗婇弫楣冩⒑閸涘﹦鎳冪紒缁樺灴婵$敻宕熼姘鳖啋闂佸憡顨堥崑鐔哥閼测晝纾藉ù锝呮惈椤庡矂鏌涢妸銉у煟鐎殿喛顕ч埥澶愬閻樼數鏉搁梻鍌氬€搁悧濠勭矙閹烘鍊堕柛顐犲劜閸婄敻鏌i悢鍝勵暭闁哥喓鍋熺槐鎺旀嫚閹绘帗娈绘繝纰夌磿閺佽鐣烽悢纰辨晬婵﹢纭搁崯瀣⒑鐠囨煡鍙勬繛浣冲洤绠烘繝濠傜墛閸嬧晛鈹戦崒姘暈闁抽攱鍨归惀顏堫敇閻愭潙顎涘┑鐐插悑閸旀牜鎹㈠☉銏″殤妞ゆ巻鍋撻柡瀣閵囧嫰顢曢姀銏㈩唺缂備浇椴哥敮鎺曠亽闂佸吋绁撮弲婊堝吹瀹€鍕拻濞撴埃鍋撻柍褜鍓涢崑娑㈡嚐椤栨稒娅犳い鏃囧亹閺嗗棝鏌ㄥ┑鍡欏闁告柨鐏氶妵鍕晜閻e苯寮ㄩ梺璇″櫙缁绘繃淇婇懜闈涚窞閻庯綆鍓欑敮楣冩⒒娴gǹ顥忛柛瀣噽閹广垽宕橀鑲╋紱濡炪倕绻愰幊鎰不閸撗€鍋撻悷鏉款棌闁哥姵娲滈懞杈ㄧ節濮橆剛鐣鹃梺缁樻煥閸氬鍩涢幋锔藉€甸柛锔诲幖鏍¢梺闈涙閸熸挳寮婚妶澶婄闁肩⒈鍓欓悡鐔兼倵鐟欏嫭绀冪紒璇茬墦瀵偊宕橀鑲╁姦濡炪倖甯掔€氀囧焵椤掍焦顥堢€规洘锕㈤、娆撳床婢诡垰娲﹂悡鏇㈡煃閳轰礁鏋ゆ繛鍫燂耿閺岋綁鎮㈢粙鍨潚濠殿喖锕ュ浠嬪箖閳╁啯鍎熼柍鈺佸暞閻︼綁姊绘担铏瑰笡闁绘娲熸俊鍓佺矙鐠恒劍娈鹃梺缁樺灦宀h法寮ч埀顒勬⒑閹肩偛鍔€闁告劑鍔庨妶顕€姊婚崒娆戠獢婵炰匠鍕垫闊洦娲橀~鏇㈡煛閸ャ儱鐏╅柛灞诲妽閵囧嫯绠涢幘璺侯杸闂佹娊鏀遍崹鍧楀蓟閻斿吋鍤冮柍杞版缁爼姊洪崨濠冣拹妞ゃ劌锕濠氭晸閻樻彃绐涘銈嗘閺侇喗鎱ㄩ崶鈺冪=濞达絿枪閳ь剙婀遍弫顕€鎮㈡俊鎾虫川閳ь剟娼ч幗婊呭婵傜ǹ绾ч柛顐g☉婵¤偐绱掑Δ浣侯暡缂佺粯鐩幃鈩冩償閿濆浂鍟嬮梻浣虹《閺備線宕滃┑瀣闁告稑鐡ㄩ悡銉╂倵閿濆懐浠涚紓宥嗩殜濮婂宕掑顑藉亾瀹勬噴褰掑炊瑜滃ù鏍煏婵炵偓娅嗛柛濠傛健閺屻劑寮撮悙娴嬪亾閸濄儳涓嶉柡灞诲劜閻撴洟鏌曟径妯烘灈濠⒀屽櫍閺岋紕鈧絺鏅濈粣鏃堟煛瀹€鈧崰鏍х暦濠婂棭妲鹃柣銏╁灡閻╊垶寮婚敓鐘插窛妞ゆ棁妫勯埀顒佸姍閺岋紕浠︾拠鎻掝潎闂佽鍠撻崐婵嗙暦閹烘垟妲堟慨妤€妫旂槐锟�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鎯у⒔閹虫捇鈥旈崘顏佸亾閿濆簼绨绘い鎺嬪灪閵囧嫰骞囬姣挎捇鏌熸笟鍨妞ゎ偅绮撳畷鍗炍旈埀顒勭嵁婵犲嫮纾介柛灞捐壘閳ь剛鎳撻~婵嬪Ω閳轰胶鐤呯紓浣割儐椤戞瑩宕ョ€n喗鐓曟い鎰靛亝缁舵氨绱撻崘鈺傜婵﹤顭峰畷鎺戔枎閹搭厽袦婵犵數濮崑鎾绘⒑椤掆偓缁夌敻骞嗛悙鍝勭婵烇綆鍓欐俊鑲╃磼閹邦収娈滈柡灞糕偓鎰佸悑閹肩补鈧尙鏁栧┑鐐村灦閹稿摜绮旈悽绋课﹂柛鏇ㄥ灠閸愨偓濡炪倖鍔﹀鈧繛宀婁邯濮婅櫣绱掑Ο璇茶敿闂佺ǹ娴烽弫璇差嚕婵犳碍鏅插璺猴工瀹撳棝姊虹紒妯哄缂佷焦鎸冲畷鎴﹀箻鐠囧弶宓嶅銈嗘尰缁嬫垶绂嶉悙顒佸弿婵☆垳鍘ф禍楣冩倵濮樼偓瀚�  闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚敐澶婄闁挎繂鎲涢幘缁樼厱闁靛牆鎳庨顓㈡煛鐏炶鈧繂鐣烽锕€唯闁挎棁濮ら惁搴♀攽閻愬樊鍤熷┑顕€娼ч~婵嬪Ω瑜庨~鏇㈡煙閹规劦鍤欑痪鎯у悑缁绘盯宕卞Ο铏圭懆闂佸憡锕槐鏇犳閹惧鐟归柛銉戝嫮褰梻浣规偠閸斿矂鎮ラ崗闂寸箚闁圭虎鍠栫粈鍐┿亜閺冨倸甯剁紒鎰洴濮婃椽宕崟鍨ч梺鎼炲妼缂嶅﹤鐣烽姀鐘嗘椽顢旈崨顓涘亾閸偒娈介柣鎰皺娴犮垽鏌涢弮鈧喊宥夊Φ閸曨垱鏅滈悹鍥皺娴犳悂鎮楃憴鍕┛缂佺粯绻堥悰顔芥償閵婏箑娈熼梺闈涳紡閸愩劌顩梻鍌氬€搁オ鎾磻閸曨個娲晝閳ь剛鍙呴梺鍝勭Р閸斿孩鏅堕敓鐘斥拻闁稿本鐟︾粊鐗堛亜閺囧棗鎳夐崑鎾诲垂椤愩垺璇為悗瑙勬礃缁捇骞冮姀锛勯檮濠㈣泛顑囩粙渚€姊绘担鐟板姢缂佺粯鍔曢敃銏℃綇閳轰緡妫滈梺绋跨箻濡法鎹㈤崱妯镐簻闁哄秲鍔庨。鏌ユ煙椤栨氨澧涢柕鍥у椤㈡洟濮€閵忋垹濮辨繝娈垮枛閿曘儱顪冮挊澶屾殾闁绘垹鐡旈弫鍥ㄧ箾閹寸偟鎳冮柣婵嬩憾濮婄粯鎷呴崨闈涚秺椤㈡牠宕ㄩ鍥ㄧ☉閳规垹鈧綆浜為悾楣冩⒑闁偛鑻晶顖炴煏閸パ冾伂缂佺姵鐩獮妯尖偓鍨偠閸嬫劖绻濈喊妯活潑闁搞劍澹嗛埀顒佺濠㈡﹢锝炶箛鎾佹椽顢旈崟顏嗙倞闂備礁鎲″ú锕傚礈濮樿泛绠柛妤冨亹閺€浠嬫煟閹邦厼绲荤紒鐙欏啰鏆嗛柨婵嗘噺閸嬨儲顨ラ悙鏉戠伌濠殿喒鍋撻梺缁橈供閸嬪懘寮埀顒€鈹戦悩鍨毄濠殿喖顕埀顒佸嚬閸o絽顕i崼鏇炵濞达絽鍘滈幏娲⒑閸涘﹦绠撻悗姘煎幖椤斿繐鈹戦崱蹇旀杸濡炪倖姊归崕鎶藉储閹绢喗鐓欐い鏃囶嚙瀹撳棗鈹戦敍鍕幋闁糕晪绻濆畷鎺懳旀担鍓蹭紲濠电姷鏁搁崑鐘诲箵椤忓棗绶ゅù鐘差儏缁犺銇勯幇鈺佲偓鏍汲濠婂牊鍋i弶鐐村椤掔喖鏌i弬鎸庮棦闁哄矉缍侀幃銏犵暋閹殿喚娉块梻浣姐€€閸嬫捇鏌ゆ慨鎰偓妤冨婵傚憡鐓曢悘鐐靛亾閻ㄦ垹鈧稒绻傝灃婵°倕锕g花鐑芥煕濡も偓閸熷潡鎮鹃悜鑺ュ亗閹兼惌鍠楅崓鐢告⒑閹稿海绠撻柟鍐茬У缁旂喖寮撮姀鈾€鎷洪梺鍛婄箓鐎氼剟寮冲▎鎾寸厽婵°倐鍋撴俊顐g〒閸掓帡宕奸妷銉ь槰闂佸磭鎳撻妵妯艰姳婵犳碍顥婃い鎰╁灪閹兼劖绻涚€电ǹ鍘撮挊婵嬫煥閺囨浜鹃梻鍥ь槹缁绘繃绻濋崒婊冣叡闂佷紮绲惧浠嬪蓟閿涘嫪娌悹鍥ㄥ絻椤牓姊虹€圭媭娼愰柛銊ョ仢閻g兘宕¢悙鈺傤潔闂佺懓鍚€缁€浣圭閻愵兛绻嗛柕鍫濆€告禍鎯ь渻閵堝骸寮ㄩ柛搴☆煼绡撳〒姘e亾闁哄本鐩幃鈺佺暦閸パ€鎷版繝鐢靛Л閸嬫挸銆掑锝呬壕濠殿喖锕ㄥ▍锝囨閹烘嚦鐔煎即閻旈浼岄梺璇″枤閸忔ɑ淇婇悿顖fХ闂佺ǹ顑嗛幐鎼侊綖濠靛鍋傞幖娣灮娴滃墽绱撻崒娆戣窗闁哥姵姘ㄩ崚鎺楊敍閻愬弬褔鏌ㄥ┑鍡╂Ц缂佲偓閸愵喗鐓冮柛婵嗗閺嗘瑦顨ラ悙鑼濞e洤锕幃娆擃敂閸曘劌浜鹃柡宥庡幖缁€澶愭煙鏉堝墽鐣辩痪鎯х秺閺岋繝宕堕妷銉т患闂佸憡鍨规繛鈧鐐寸墪鑿愭い鎺嗗亾濠碘€茬矙閺岋綁骞樼捄鐑樼亪闂佺粯鎼╅崑濠傜暦閹偊妾ㄩ梺绋块缁绘﹢寮诲☉銏犵睄闁逞屽墰閸掓帡骞樼拠鑼舵憰闂佸搫娲㈤崹褰掓倷婵犲嫭鍠愮€广儱顦介弫鍌涖亜閹捐泛袥闁稿鎸搁埢鎾诲垂椤旂晫浜舵繝鐢靛仜閸氬鎮烽妸鈺傚€堕柟鐑橆殕閳锋垿鏌涘☉姗堝姛缂佺姵鎹囬幃妤€顫濋悡搴♀拤濡炪們鍊曢崐鍦崲濠靛牆鏋堝璺虹灱閿涚喖姊虹粙娆惧剱闁搞劌鐏濋悾鐑藉箛閺夎法顓洪梺鎸庢磵閸嬫捇鏌涢妸銉モ偓鍦崲濞戞﹩鍟呮い鏃囧吹閸戝綊姊虹粙娆惧劀缂佺粯绻堝璇差吋婢跺﹣绱堕梺鍛婃处閸撴瑥鈻嶉敐鍥╃=濞达絽鎼牎闂佺粯顨堟繛鈧€殿喛顕ч鍏煎緞婵犲嫬骞愬┑鐐舵彧缁蹭粙骞夐垾鏂ユ灁闁哄被鍎查埛鎴犵磼鐎n偄顕滈柟鐧哥秮閺屾盯鎮╁畷鍥р拰閻庢鍠栭…宄邦嚕閹绢喖顫呴柣姗€娼ч埀顒傚仱閹嘲饪伴崘顎倝鏌ゆウ鍧楀摵缂佺粯绻傞~婵嬵敇閻樻彃绠ラ梻鍌欑閹诧繝宕归鐐茬9闁哄稁鍋€閸嬫挸顫濋悙顒€顏�
核心提示:引言本系列文章的第 1 部分介绍了中介的基本知识,现在您应该已知道了使用中介的原因和场合,消息中介的实用介绍——第 2 部分:使用中介路由消息,以及如何开发、组装、部署和测试简单的中介处理程序,在这第二篇文章中,以便可以根据消息的内容对消息进行处理,我们将扩展 DebugMediation 以输出消息内容,您将了解如何

引言

本系列文章的第 1 部分介绍了中介的基本知识。现在您应该已知道了使用中介的原因和场合,以及如何开发、组装、部署和测试简单的中介处理程序。在这第二篇文章中,您将了解如何使用中介路由消息。我们将首先描述在不使用中介的情况下如何路由消息,然后接着介绍使用中介扩展此功能的方式以及原因。

准备

要开发和测试本文包含的中介,必须安装以下软件组合之一:

IBM® WebSphere® Application Server Toolkit Version 6.0 与 IBM WebSphere Application Server V6

IBM Rational® Application Developer for WebSphere Software V6,包括集成的 WebSphere Application Server V6 测试环境。

IBM Rational Application Developer for WebSphere Software V6 与 WebSphere Application Server V6。

IBM Rational Software Architect V6.0,包括集成的 WebSphere Application Server V6 测试环境。

您还应该下载和应用所安装产品的最新服务水平。撰写本文时,所发布的最新 Fixpack 为 WebSphere Application Server V6 Refresh Pack 1 (V6.0.1)。可以使用 Rational Product Updater 来获得 Rational 产品的更新,Rational Product Updater 会在安装任何 Rational 产品时自动安装。

本文中所出现的屏幕图像均出自 Rational Application Developer V6。如果使用 WebSphere Application Server Toolkit,仍然可以采取本文中所述的步骤,因为这些步骤对于 Application Developer 和该工具包而言,是完全相同的。可以从 WebSphere Application Server 安装媒体或映象安装 WebSphere Application Server Toolkit。

最理想的情况是:您已经成功地按照上一篇文章中所述进行操作,已开发、部署并测试过一个中介处理程序。如果尚未读过上一篇文章,请确保按照本文后面所述的附加步骤进行相应操作。

使用受管理路由路径路由消息

WebSphere Application Server V6 的缺省消息传递提供程序会使目的地采用受管理路由路径,从而在将消息发送到目的地时提供一个简单的方法来路由消息。为了本文起见,我们将以一个简单的零售管理的例子来演示消息路由的一种可能的用法:

跨国大型超市公司的每家连锁店都通过电子方式与总部进行交互,以报告交易情况、订购量以及进行其他业务活动。销售点 (POS) 终端以及其他系统使用 JMS 消息传递与总部系统进行通信。为了获得更大的控制和灵活性,每个连锁店都使用一个专用的目的地。

为了确保将消息转发到总部系统,每个连锁店目的地都定义了一个到达中心目的地的受管理转发路由路径。实际上,每个连锁店目的地都作为要路由到中心目的地的消息的“下一个跃点”使用,这些消息将在中心目的地由总部系统进行处理。此消息路由拓扑如图 1 所示。
图 1. 使用路由路径转发消息的逻辑消息传递拓扑
消息中介的实用介绍——第 2 部分:使用中介路由消息

可以在目的地之间使用自动路由消息功能,以更好地实现组件、服务或应用程序之间的分隔。在本例中,没有使用中介就实现了消息路由,这引出了一个问题:为什么要使用中介进行路由呢?

使用中介路由消息

使用中介,可以对正在传递的消息进行有条件的处理;通过比较,可以发现受管理路由路径没有条件元素,此类路径应用到发送到目的地的所有消息。在我们的示例中,受管理路由路径的用法是有效的,因为需要将所有消息按照完全相同的方式进行路由。如果同一目的地的消息需要按照不同的方式进行路由,则不能使用受管理路由路径。如果需要有条件地路由消息,请使用中介。

对我们的示例进行修改,可以反映出需要进行选择性路由的一个原因:

此超市连锁公司开发了总部 POS 应用程序的新版本,此版本采用了不同的消息格式。解决方案以前基于 JMS 对象消息;新应用程序使用通过 JMS 文本消息发送的 XML 消息。该应用程序的新版本定义了接收消息的特定目的地,而该目的地使用新格式。当然,可以要求所有连锁店一起切换到新版本的应用程序,但更实际的方法则是让一些或全部连锁店开始只升级其部分 POS 终端。一旦证明应用程序的可靠性后,再将新应用程序推广到所有连锁店中的每个终端。

场景中的这一变化给我们提出了一系列简单的要求,可以用中介满足这些要求:最根本的,将调用中介处理程序检查消息格式,然后据此路由消息。此中介应用到每个连锁店目的地。调用中介时,中介会将 JMS 文本消息(格式为“JMS:text”)路由到为处理 XML 消息的新版应用程序定义的目的地。使用旧格式“JMS:object”的消息将不会修改其路由路径,因此将被路由到原来的中心目的地。

消息路由中介

前一篇文章中提供了关于如何开发和测试基本中介处理程序的详细说明,因此我们将主要讨论中介处理程序的代码。(如果尚未读过第一篇文章,则应该考虑读一读;其中的基本知识将不会在此处复述。)

中介参数和上下文属性

使中介处理程序具有可配置性,可以使其更便于进行重用;请考虑此“最佳实践”。组装中介处理程序时,工具安装过程将在 Java™ 类中查找可以公开为处理程序参数的字段。如果某个处理程序字段具有相应的 getter 和 setter 方法,则此字段可作为参数公开给您的中介处理程序。

简单 Java 原语在部署描述符中定义;通过在中介处理程序面板中选择参数并单击 Edit 按钮,可以进行赋值。调用中介处理程序转发消息之前,将使用部署描述符中定义的值设置处理程序的参数。引用对象的字段也可以作为中介处理程序参数公开。这些对象引用参数在部署描述符(将在运行时解析)中作为资源引用公开。中介的部署者必须确保资源引用映射到了恰当的对象,否则将会出现运行时错误。

要更改中介处理程序的参数,必须:

编辑部署描述符

更改参数

重新部署组装过的处理程序。

您可能希望通过为部分或全部参数提供覆盖机制以避免这些步骤。管理员可以在目的地和中介上定义上下文属性,这些属性可以在运行时使用 javax.xml.rpc.handler.MessageContext 引用进行检索,此引用会在调用中介处理程序时传递给它。使用上下文属性提供覆盖功能非常简单,稍后我们将在示例处理程序中举例说明。

我们将要公开一些属性,用于控制是否需要对某条消息进行路由以及应将其路由到何处。下表显示了中介处理程序的属性及其可以具有的效果。所有属性的类型都为 java.lang.String。

属性 用途
RouteMessageFormat要进行重新路由的消息的消息格式。可以对此值进行硬编码,但如果为可配置的,则中介处理程序的可重用性能更好。缺省情况下,将路由 JMS:text 格式的消息;可以在部署描述符中更改这一点,或者通过设置“RouteMessageFormat”上下文属性将其覆盖。(有关 JMS 消息的详细信息,请参阅 WebSphere Application Server Information Center。
RouteMessageDestination消息重新路由到的目的地。

开发消息路由中介处理程序

可以在下载文件中下载此中介的一个源代码版本,该文件中还包含一个用于创建测试消息环境的管理脚本。可以下载并导入所提供的中介代码,也可以按照以下步骤创建中介处理程序:

启动 Application Developer,并使用上一篇文章所使用的同一个工作区。如果没有此工作区,则:

创建一个名为 MessageMediation 的新 Java 项目。

使用项目上下文菜单选择项目属性,方法为右键单击此 Java 项目,然后从出现的菜单中选择 Project Properties。

选择 Server 属性,然后将 Target Server 设置为 WebSphere Application Server Version 6.0。

使用 Create Java Class 向导,向 MessageMediation 项目添加一个新的中介处理程序类。如图 2 所示,该类的名称为 RoutingMediation,软件包为 mediation.handlers,而且它必须实现 com.ibm.websphere.sib.mediation.handler.MediationHandler 接口。
图 2. 创建路由中介处理程序类
消息中介的实用介绍——第 2 部分:使用中介路由消息

需要在该处理程序类中添加两个字段,这两个字段与具有适当的 setter 和 getter 方法的中介参数对应。中介还使用标准 Java logging API 对消息进行记录。请添加清单 1 所示的代码。

清单 1. 路由中介参数和记录引用

// Mediation parameters 
  private String routeMessageFormat = "JMS:text"; 
  private String routeMessageDestination = "routeToQueue"; 
  // Used for logging and tracing the execution of the handler 
  private String logName = "MsgMediation"; 
  private Logger log; 
  public String getRouteMessageDestination() { 
    return routeMessageDestination; 
  } 
  public void setRouteMessageDestination(String routeMessageDestination) { 
    this.routeMessageDestination = routeMessageDestination; 
  } 
  public String getRouteMessageFormat() { 
    return routeMessageFormat; 
  } 
  public void setRouteMessageFormat(String routeMessageFormat) { 
    this.routeMessageFormat = routeMessageFormat; 
  } 
  private Logger getLog() { 
    if (log == null) { 
      log = Logger.getLogger(getLogName()); 
    } 
    return log; 
  } 
  public String getLogName() { 
    return logName; 
  } 
  public void setLogName(String logName) { 
    this.logName = logName; 
  }

当转发消息时,将调用 handle(MessageContext) 方法。我们的 handle 方法会将大部分处理委托给其他方法,请更改现有的 handle() method 以与清单 2 中的方法匹配。稍后我们将对所需的方法进行编码。

清单 2. 路由中介 handle() 方法

public boolean handle(MessageContext msgCtx) throws MessageContextException { 
    boolean contMsgProcessing = true; 
    SIMessageContext siMsgCtx = (SIMessageContext) msgCtx; 
    SIMessage msg = siMsgCtx.getSIMessage(); 
    if (shouldRouteMessage(siMsgCtx)) { 
      setRoutingPath(siMsgCtx); 
      getLog().log(Level.INFO, "Re-routed message {0}", msg.getApiMessageId()); 
    } else { 
      getLog().log(Level.INFO, "Message {0} does not require re-routing", msg.getApiMessageId()); 
    } 
    return contMsgProcessing; 
  }

shouldRouteMessage(MessageContext) 方法确定是否需要对消息进行路由;如果满足所定的条件,则将返回 true。这个操作是通过将待转发消息的消息格式与中介处理程序的配置值进行比较完成的。因为所需的消息格式可以由管理员覆盖,故而将调用 getRouteMessageFormat(MessageContext)。如果设置了消息上下文属性,此方法会返回此属性,否则它将返回定义的中介参数的值。这两个新方法都在清单 3 中给出。请将它们添加到该中介处理程序类中。

清单 3. 检查路由消息条件

private boolean shouldRouteMessage(SIMessageContext siMsgCtx) { 
    boolean result; 
    SIMessage msg = siMsgCtx.getSIMessage(); 
    result = msg.getFormat().equals(getRouteMessageFormat(siMsgCtx)); 
    return result; 
  } 
  private String getRouteMessageFormat(SIMessageContext siMsgCtx) { 
    String value = (String) siMsgCtx.getProperty("routeMessageFormat"); 
    if ((value == null) || (value.equals(""))) { 
      value = getRouteMessageFormat(); 
    } 
    return value; 
  }

如果消息需要重新路由,则调用 setRoutingPath(SIMessageContext) 方法来更改消息的路由路径。这将使用 com.ibm.websphere.sib.SIDestinationAddressFactory 查找要使用的目的地,以设置转发路径。与 getRouteMessageFormat(MessageContext) 类似,getRouteMessageDestination(MessageContext) 方法支持使用上下文属性管理目的地名称。请将清单 4 中所示的代码添加处理程序类中。

清单 4. 修改消息路由路径

private void setRoutingPath(SIMessageContext siMsgCtx) { 
    SIMessage msg = siMsgCtx.getSIMessage(); 
    List frp = new ArrayList(1); 
    String destName = getRouteMessageDestination(siMsgCtx); 
    SIDestinationAddress dest = SIDestinationAddressFactory.getInstance(). 
      createSIDestinationAddress(destName, false); 
    frp.add(dest); 
    msg.setForwardRoutingPath(frp); 
  } 
  private String getRouteMessageDestination(SIMessageContext siMsgCtx) { 
    String value = (String) siMsgCtx.getProperty("routeMessageDestination"); 
    if ((value == null) || (value.equals(""))) { 
      value = getRouteMessageDestination(); 
    } 
    return value 
  }

这样,我们就完成了消息路由中介处理程序所需的代码。现在就可以对其进行组装、部署和测试了。

组装、部署并测试路由消息中介

如果已按照前一教程所述进行了操作,则只需要在已经存在的 DeployableMediationEJB 项目中定义此处理程序。否则,将需要进行以下操作:

创建名为 DeployableMediation 的新 J2EE Enterprise Application 项目。

创建此项目时,请创建一个名为 DeployableMediationEJB 的新 EJB 项目,并将其添加到现有的 MessageMediation 项目。

编辑 DeployableMediationEJB 项目的 Java JAR 依赖性,并将 MessageMediation 项目添加为依赖性。

组装消息路由中介

要组装中介处理程序,请执行以下步骤:

打开 DeployableMediationEJB 项目的部署描述符。

选择 Mediation Handler 选项卡,如图 3 所示。
图 3. 编辑部署描述符中定义的中介处理程序
消息中介的实用介绍——第 2 部分:使用中介路由消息

使用 Add 按钮添加路由中介,并完成图 4 所示的面板。
图 4. 将处理程序类添加到部署描述符
消息中介的实用介绍——第 2 部分:使用中介路由消息

保存并关闭部署描述符。现在已经完成了中介处理程序的组装。

部署消息路由中介

如果已按照前一教程中所述进行了操作,则 DeployableMediation 企业应用程序可能仍然部署在服务器上。如果是这样的话,则只需确保更改已发布即可。如果未部署该企业应用程序,则按照以下步骤进行操作:

在所用部署工具的 Servers 视图中选择您的服务器。如果未定义任何服务器,则在服务器视图内单击右键,然后选择 Add and remove projects。

将 DeployableMediation 项目添加到服务器。

该项目现在应该自动添加到定义的服务器。如果有必要,可使用服务器上下文菜单强制发布该应用程序。

测试路由消息中介

在测试中介处理程序前,需要创建测试消息传递配置。下载文件中包括一个名为 routingMediationAdmin.jacl 的管理脚本,该脚本将创建:

两个目的地,originalQueue 和 routeToQueue。

一个 JMS Connection Factory,jms/CF2,它连接到总线 SimpleBus。

两个托管目的地(在 JNDI 中),名为 jms/originalQueue 和 jms/routeToQueue,并将它们链接到两个目的地。

一个名为 RoutingMediation 的中介,并将其应用到 originalQueue 目的地。

此脚本假定存在总线和总线成员。如果没有按照前一篇文章中所述进行操作,并且尚未定义总线,则请编辑此脚本文件,取消注释所包含的创建总线的代码:将下面的注释后紧跟的 # 字符删除:

# Uncomment the following section to create a messaging bus and assign the server as a member of the bus.

使用服务器的 Run external admin script 上下文菜单项运行该脚本(图 5)。导航到 routingMediationAdmin.jacl 文件并运行它。


图 5. 启动外部管理脚本
消息中介的实用介绍——第 2 部分:使用中介路由消息

图片看不清楚?请点击这里查看原图(大图)。

应该看到如下消息:

   Create SIB Queues 
$AdminTask createSIBDestination -bus SimpleBus -name originalQueue 
  -type queue -node neodogNode -server server1 
$AdminTask createSIBDestination -bus SimpleBus -name routeToQueue 
  -type queue -node neodogNode -server server1 
Create JMS JNDI Resources 
$AdminTask createSIBJMSConnectionFactory server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml 
  #Server_1114261967144) -name CF2 -jndiName jms/CF2 -busName SimpleBus -type queue 
$AdminTask createSIBJMSQueue server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml 
  #Server_1114261967144) -name originalQueue -jndiName jms/originalQueue -queueName originalQueue 
$AdminTask createSIBJMSQueue server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml 
  #Server_1114261967144) -name routeToQueue -jndiNamejms/routeToQueue -queueName routeToQueue 
Create and apply RoutingMediation to originalQueue 
$AdminTask createSIBMediation -bus SimpleBus -mediationName RoutingMediation 
  -handlerListName RoutingMediation 
$AdminTask mediateSIBDestination -bus SimpleBus -destinationName originalQueue 
  -mediationName RoutingMediation -node neodogNode -server server1 
Configuration saved 

为了让对 JNDI 服务器的更改生效,必须重新启动服务器。一旦服务器重启后,就可以使用通用测试客户端 (UTC) 测试中介了:

使用服务器上下文菜单项启动 UTC。

展开 Utilities 选项卡,并选择 Send JMS Message 实用工具。

使用 jms/CF2 Connection Factory 向 jms/originalQueue 目的地发送一条消息,如图 6 所示。
图 6. 使用 UTC 发送消息
消息中介的实用介绍——第 2 部分:使用中介路由消息

使用服务器上下文菜单启动 WebSphere Application Server 管理控制台,应该看到如下消息(此消息将在单个行上显示):

[17/04/05 14:40:13:418 BST] 0000005d MsgMediaiton I Routing message ID: 
  8fa289e1aff0dd0876a80a48110a134f0000000000000001 


登录并展开 Service Integration 选项卡。

选择 Buses => SimpleBus => Destinations => routeToQueue => Queue points,然后选择所显示的队列点。

面板显示时,选择 Runtime 选项卡。

定位到 Current Message depth,其值应该为 1。此项与日志项均指示发送到 originalQueue 的消息已经被路由到 routeToQueue 目的地。

也可以选择按照下面的步骤进行操作,以证实已经对此消息进行了路由:

通过选择 Messages 浏览队列。

从显示的这个表中选择该消息。

由中介写入到日志中的消息标识符应与此目的地上的消息的 API 消息标识符匹配。

跟踪下载的中介处理程序

中介处理程序的下载版本包含有附加的跟踪和调试语句。通过使用标准 Java logging 接口,处理程序将写入记录项以跟踪其执行路径。为了查看跟踪项,请启用应用服务器中的跟踪功能。缺省情况下,所有实例中介使用的记录器的名称都为 MsgMediation。要使用管理控制台启用跟踪功能,请执行以下步骤:

展开 Troubleshooting 选项卡。

选择 Logging and Tracing => server1 => Change Log Detail Levels。

等待屏幕刷新完成,然后将日志级别更改为 *=info: MsgMediation=all。

重新启动服务器。将在服务器的日志目录中创建一个名为 trace.log 的文件。

向 originalQueue 发送另一条消息。中介将会把此消息写入跟踪记录文件,此文件可用于调试。

使用中介发送克隆消息

开发或集成使用消息传递功能的应用程序时,可能希望对消息流进行捕获。或者,您可能需要将消息的副本发送到另一个目的地,以用于审核或其他目的。中介处理程序可以使用 SIMediationSession 发送消息,通过对处理程序的 SIMessageContext 引用调用 getSession() 可以获得 SIMediationSession。SIMessage 消息将实现 java.lang.Cloneable,从而使中介可以进行克隆操作,然后将克隆消息发送到另一个目的地。下面让我们对示例进行进一步扩展,从而阐释可将中介用于此目的的原因和方式。

对新的 POS 应用程序进行最后测试时,需要捕获所有消息的副本,以验证发送到应用程序的所有消息都得到了正确的处理。另外,还可以通过这种方式对任何无法处理的消息的内容进行检查。

同样,中介处理程序需要具有可配置性,以便管理员能够定义一些属性,以控制克隆消息的创建和路由。下表显示了中介处理程序的参数及其用途,所有参数的类型都是 java.lang.String:

名称 用途
CloneMessageDestination克隆消息发送到的目的地。
ExistingRouteAction控制在消息具有现有路由路径的情况下采取何种操作。可能的值为 PREPEND、APPEND 和 OVERWRITE(缺省值)。
CloneMessagePropertyName要在克隆消息上设置的布尔属性的名称。设置此属性可以防止对已经克隆消息进行克隆。

开发发送克隆消息的中介处理程序

与前面的中介处理程序一样,此处理程序的源代码也可以下载,其中也包含跟踪和调试语句。对应的下载文件中也包含一个用于创建所需测试环境的管理脚本。要开发用于发送克隆消息的中介处理程序,请按照以下步骤进行操作:

创建新的中介处理程序类 mediation.handlers.SendCloneMediation,该类将实现 com.ibm.websphere.sib.mediation.handler.MediationHandler。

向该类添加具有恰当 setter 和 getter 方法的中介参数及记录引用,如清单 5 所示。

清单 5. 中介参数和记录引用

// Mediation parameters 
  private String cloneMessageDestination = "clonedMsgQueue"; 
  private String existingRouteAction = "OVERWRITE"; 
  private String cloneMessagePropertyName = "messageCloned"; 
  // Used for logging and tracing the execution of the handler 
  private String logName = "MsgMediation"; 
  private Logger log; 
  private Logger getLog() { 
    if (log == null) { 
      log = Logger.getLogger(getLogName()); 
    } 
    return log; 
  } 
  public String getCloneMessageDestination() { 
    return cloneMessageDestination; 
  } 
  public void setCloneMessageDestination(String cloneMessageDestination) { 
    this.cloneMessageDestination = cloneMessageDestination; 
  } 
  public String getCloneMessagePropertyName() { 
    return cloneMessagePropertyName; 
  } 
  public void setCloneMessagePropertyName(String cloneMessagePropertyName) { 
    this.cloneMessagePropertyName = cloneMessagePropertyName; 
  } 
  public String getExistingRouteAction() { 
    return existingRouteAction; 
  } 
  public void setExistingRouteAction(String existingRouteAction) { 
    this.existingRouteAction = existingRouteAction; 
  } 
  public String getLogName() { 
    return logName; 
  } 
  public void setLogName(String logName) { 
    this.logName = logName; 
  }

中介框架将调用处理程序的 handle() 方法。此方法将使用 shouldSendClone() 方法进行检查,以确定是否应克隆消息。如返回后的值为 true,则将使用 sendClone() 方法发送消息的一个克隆。修改生成的 handle() 方进,如清单 6 所示。

清单 6. 发送克隆的 handle() 方法

public boolean handle(MessageContext ctx) throws MessageContextException { 
    boolean contMsgProcessing = true; 
    SIMessageContext siCtx = (SIMessageContext) ctx; 
    if (shouldSendClone(siCtx)) { 
      sendClone(siCtx); 
    } 
    return contMsgProcessing; 
  }

如果应该克隆消息,则调用 shouldSendClone() 方法。首先将检查 CloneMessagePropertyName 属性以确保不会克隆已克隆的消息。然后我们将确保不在克隆消息的目标目的地上调用此中介。这两个检查将确保中介不会引发“消息风暴”(Message storm) 配置错误。将使用 getCloneMessagePropertyName(SIMessageContext ctx) 方法检查和上下文属性(如果已设置)。将清单 7 中所示的代码添加到该中介处理程序中:

清单 7. shouldSendClone(SIMessageContext) 的代码

private boolean shouldSendClone(SIMessageContext ctx) { 
    boolean sendClone = true; 
    SIMessage msg = ctx.getSIMessage(); 
    try { 
     Boolean clonedMsgProperty; 
      String clonePropName = getCloneMessagePropertyName(ctx); 
      clonedMsgProperty = (Boolean) msg.getUserProperty(clonePropName); 
      if ((clonedMsgProperty != null) && clonedMsgProperty.booleanValue()) { 
        sendClone = false; 
     } 
    } catch (Exception e) { 
      getLog().log(Level.SEVERE, "Exception getting message property: " + getCloneMessagePropertyName(ctx), e); 
    } 
    String mediationDest = ctx.getSession().getDestinationName(); 
    if (getCloneMessageDestination(ctx).equals(mediationDest)) { 
  sendClone = false; 
    } 
    return sendClone; 
  } 
  private String getCloneMessagePropertyName(SIMessageContext ctx) { 
    String value = (String) ctx.getProperty("cloneMessagePropertyName"); 
    if ((value == null) || (value.equals(""))) { 
      value = getCloneMessagePropertyName(); 
    } 
    return value 
  }

如果需要克隆消息,该处理程序将调用 sendClone() 方法,此方法负责克隆消息并将克隆消息发送到配置的目的地,然后将克隆消息路由路径的设置委托给 setRoutingPath(clone, ctx) 方法。后者也将设置一个消息属性,以指示消息为一个克隆消息。请将清单 8 所示的代码添加到该处理程序中:

清单 8. sendClone(SIMessageContext) 的代码

private void sendClone(SIMessageContext ctx) { 
    SIMediationSession session = ctx.getSession(); 
    SIMessage clone = null; 
    try { 
      clone = (SIMessage) ctx.getSIMessage().clone(); 
      setRoutingPath(clone, ctx); 
      clone.setUserProperty(getCloneMessagePropertyName(ctx), Boolean.TRUE); 
      session.send(clone, false); 
      getLog().log(Level.INFO, "Message {0} cloned and routed to {1}", 
             new Object[] { clone.getApiMessageId(), clone.getForwardRoutingPath() } ); 
    } catch (Exception e) { 
      getLog().log(Level.SEVERE, "An exception occurred sending the cloned message", e); 
    } 
  }

现在需要添加 setRoutingPath(SIMessage, SIMessageContext) 及其依赖性。setRoutingPath() method 将根据 ExistingRouteAction 属性修改所有现有路由路径。将清单 9 中所示的代码添加到该处理程序中:

清单 9. 设置克隆消息的路由路径

private void setRoutingPath(SIMessage clone, SIMessageContext ctx) { 
    List frp = clone.getForwardRoutingPath(); 
 String destName = getCloneMessageDestination(ctx); 
 SIDestinationAddress dest = SIDestinationAddressFactory.getInstance(). 
    createSIDestinationAddress(destName, false); 
    if ((frp.isEmpty()) || (getExistingRouteAction().equalsIgnoreCase("OVERWRITE"))) { 
      List newFrp = new ArrayList(1); 
      newFrp.add(dest); 
      clone.setForwardRoutingPath(newFrp); 
    } else { 
      if (getExistingRouteAction().equalsIgnoreCase("APPEND")) { 
        frp.add(dest); 
      } else { 
        frp.add(0, dest); 
      } 
      clone.setForwardRoutingPath(frp); 
    } 
  } 
  private String getCloneMessageDestination(SIMessageContext ctx) { 
    String value = (String) ctx.getProperty("cloneMessageDestination"); 
    if ((value == null) || (value.equals(""))) { 
      value = getCloneMessageDestination(); 
    } 
    return value; 
  }

现在就可以组装、部署和测试这个新的中介处理程序了。

组装、部署和测试发送克隆的中介

要组装中介,请按照如下步骤进行操作:

打开 DeployableMediationEJB 项目的部署描述符。

选择 Mediation Handlers 选项卡(图 7),然后使用 Add 按钮添加新的中介。
图 7. 添加发送克隆的中介
消息中介的实用介绍——第 2 部分:使用中介路由消息

保存部署描述符

如果服务器仍在运行,且已经部署了 DeployableMediation,则应当自动发布所做的更改。如果有必要,启动服务器并发布更改。

为了测试中介,需要定义一些消息传递资源。(下载文件中包含了一个管理脚本。)运行 sendCloneMediationAdmin.jacl 脚本以设置以下配置:

两个目的地,名为 messageQueue 和 clonedMsgQueue。

三个 JMS 资源,名为 jms/messageQueue、jms/clonedMsgQueue 和 jms/CF3。

一个名为 SendCloneMediaiton 的中介,将应用到 messageQueue。

重新启动服务器,启动 UTC,然后向 jms/messageQueue 发送一条测试消息。如果成功调用中介处理程序,所得的结果将为一个设置到 clonedMsgQueue 目的地的克隆消息。通过检查服务器日志项或通过使用管理控制台浏览两个队列点,可以对此进行验证。应当看到一个如下所示的项(此消息将在单个行上显示):

[17/04/05 15:54:00:912 BST] 0000005e MsgMediaiton I Message ID: 
  ee5d090dc9dc751359fe3936110a134f0000000000000001 cloned and sent to [[ clonedMsgQueue, false, null, ]] 

结束语

本文的目的是演示如何使用中介处理程序进行消息路由。首先我们了解了如何修改消息的路由,以使其可以发送到不同的目的地。随后,我们了解了如何开发中介处理程序以将消息从一个目的地复制到另一个目的地。通过这些示例,您将获得更多组装、部署、测试中介和基于消息的解决方案的经验。

本系列的下一篇文章将讨论访问消息负载,以便可以根据消息的内容对消息进行处理。我们将扩展 DebugMediation 以输出消息内容,并开发一个修改消息内容的简单中介。

本文示例源代码或素材下载

Tags:消息 中介 实用

编辑录入:爽爽 [复制链接] [打 印]
[]
  • 好
  • 好的评价 如果觉得好,就请您
      0%(0)
  • 差
  • 差的评价 如果觉得差,就请您
      0%(0)
更多精彩
    赞助商链接

    热点阅读
      焦点图片
        最新推荐
          精彩阅读