摘要:解析和內(nèi)容的一點(diǎn)技巧概述在沒有統(tǒng)一標(biāo)準(zhǔn)的情況下,一個(gè)系統(tǒng)對(duì)接多個(gè)外部系統(tǒng)往往會(huì)遇到請(qǐng)求接口響應(yīng)數(shù)據(jù)異構(gòu)的情況,有可能返回的是,也有可能返回。解析內(nèi)容也是同理的,只不過定義的是表達(dá)式。
解析XML和JSON內(nèi)容的一點(diǎn)技巧 概述
在沒有統(tǒng)一標(biāo)準(zhǔn)的情況下,一個(gè)系統(tǒng)對(duì)接多個(gè)外部系統(tǒng)往往會(huì)遇到請(qǐng)求接口響應(yīng)數(shù)據(jù)異構(gòu)的情況,有可能返回的是XML,也有可能返回
JSON。除了返回類型不同,內(nèi)容結(jié)構(gòu)也不盡相同。以XML類型為例,
接口1返回內(nèi)容
16112638767472747178067 OK 200 ...
接口2返回內(nèi)容
16112638767472747178068 成功 1 ...
如果在我們系統(tǒng)中為每種格式的內(nèi)容針對(duì)處理顯然是不合理的,上面的內(nèi)容中我們只是關(guān)心三種信息,分別是業(yè)務(wù)ID、狀態(tài)值和描述信息,那么可不可以抽象這三種信息,
獲得這些信息后再進(jìn)行業(yè)務(wù)邏輯處理。
根據(jù)業(yè)務(wù)抽象我們需要從XML或者JSON內(nèi)容中獲得三種信息,我們這里將會(huì)使用XPath和JSONPath的方式來解析。比如獲得接口1的重要信息,
我們可以設(shè)定三個(gè)XPath表達(dá)式,
{ bid: "/root/bizKey", code: "/root/returnCode", description: "/root/returnMsg" }
bid,code和description對(duì)應(yīng)我們系統(tǒng)自己定義的字段名。
解析JSON內(nèi)容也是同理的,只不過定義的是JSONPath表達(dá)式。
假設(shè)我們從原始的XML和JSON數(shù)據(jù)中獲得了bid,code和description信息,
從接口1獲得
{ bid: "16112638767472747178067", code: "200", description: "OK" }
從接口2獲得
{ bid: "16112638767472747178068", code: "1", description: "成功" }
假設(shè)我們從接口1文檔獲知狀態(tài)值200表示請(qǐng)求成功,從接口2文檔獲知狀態(tài)值1表示請(qǐng)求成功,雖然他們都表示請(qǐng)求成功,但是我們還是不能
把他們?cè)颈镜乇4娴轿覀兊臉I(yè)務(wù)相關(guān)表中(當(dāng)然這些響應(yīng)數(shù)據(jù)還是需要保存到另外的記錄表中的,至少方便排查問題)。
假設(shè)我們的業(yè)務(wù)相關(guān)表是這樣設(shè)計(jì)的
字段名 | 類型 | 描述 |
---|---|---|
bid | string | 業(yè)務(wù)ID |
code | int | 狀態(tài)值,0=初始,1=請(qǐng)求中,2=成功,3=失敗 |
description | string | 描述 |
因此,我們還必須定義規(guī)則把接口1返回的狀態(tài)值200轉(zhuǎn)換為我們系統(tǒng)的2,把接口2返回的狀態(tài)值1轉(zhuǎn)換為我們系統(tǒng)的2。
總結(jié)一下,兩步走解析XML和JSON數(shù)據(jù)內(nèi)容
根據(jù)XPath或者JSONPath表達(dá)式解析獲得重要信息
根據(jù)規(guī)則轉(zhuǎn)換狀態(tài)值
第一步解析數(shù)據(jù)獲得重要信息以XML為例,
public class XmlParseUtils { private DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); private XPathFactory xpathFactory = XPathFactory.newInstance(); /** * * @param param 數(shù)據(jù)內(nèi)容 * @param paths 表達(dá)式 * @return * @throws Exception */ public Mapparse(String param, Map paths) throws Exception{ InputSource inputSource = new InputSource(new StringReader(param)); Document document = dbFactory.newDocumentBuilder().parse(inputSource); Map map = Maps.newHashMap(); for(String key : paths.keySet()) { XPath xpath = xpathFactory.newXPath(); Node node = (Node) xpath.evaluate(paths.get(key), document, XPathConstants.NODE); if(node == null) { throw new Exception("node not found, xpath is " + paths.get(key)); } map.put(key, node.getTextContent()); } return map; } }
parse函數(shù)的返回類型也可以是Map
這一步稍稍有點(diǎn)麻煩,不過我們先不考慮代碼實(shí)現(xiàn),反正你能想到的可能別人已經(jīng)幫你實(shí)現(xiàn)了。首先我們根據(jù)接口文檔定義規(guī)則,寫出規(guī)則表達(dá)式(或者其他的什么),
又是表達(dá)式。假設(shè)接口1的返回的狀態(tài)值比較簡(jiǎn)單,只有200表示成功,其他情況都是失敗,那么我們可以這樣定義規(guī)則,
code.equals("200") ? 2: 3
或者
<#if code == "200"> 2 <#else> 3 <#/if>
亦或者
function handle(arg) { if(arg == 200) { return 2; } return 3; } handle(${code})
以上根據(jù)同一份文檔定義了三種不同類型的狀態(tài)值轉(zhuǎn)換規(guī)則,肯定需要三種不同的實(shí)現(xiàn)。下面一一說明,
三目表達(dá)式code.equals("200") ? 2: 3是一個(gè)三目表達(dá)式,我們將使用jexl引擎來解析,利用第一步解析數(shù)據(jù)獲得重要信息的結(jié)果,我們可以這樣做
public Object evaluateByJexl(String expression, MapFreeMarker模板context) { JexlEngine jexl = new JexlBuilder().create(); JexlExpression e = jexl.createExpression(expression); JexlContext jc = new MapContext(context); return e.evaluate(jc); }
<#if code == "200"> 2 <#else> 3 <#/if>
處理這段模板我們可以這么做
/** * * @param param FreeMarker模板 * @param context * @return * @throws Exception */ public String render(String param, Mapcontext) throws Exception { Configuration cfg = new Configuration(); StringTemplateLoader stringLoader = new StringTemplateLoader(); stringLoader.putTemplate("myTemplate",param); cfg.setTemplateLoader(stringLoader); Template template = cfg.getTemplate("myTemplate","utf-8"); StringWriter writer = new StringWriter(); template.process(context, writer); return writer.toString(); }
如果FreeMarker模板比較復(fù)雜,從模板預(yù)編譯成Template可能會(huì)消耗更多的性能,就要考慮把Template緩存起來。
JavaScript代碼段function handle(arg) { if(arg == 200) { return 2; } return 3; } handle(${code})
這段js代碼中存在${code},首先它需要使用FreeMarker渲染得到真正的handle方法的調(diào)用參數(shù),然后
public Object evaluate(String expression) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); return engine.eval(expression); }
ScriptEngineManager的性能估計(jì)不太樂觀,畢竟是一個(gè)語言的引擎。
不同轉(zhuǎn)換規(guī)則實(shí)現(xiàn)的比較類型 | 實(shí)現(xiàn) | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|---|
三目表達(dá)式 | Jexl | 簡(jiǎn)單(easy) | 簡(jiǎn)單(simple) |
FreeMarker模板 | FreeMarker | -- | -- |
JavaScript代碼段 | FreeMarker + ScriptEngine | 直觀 | 過程復(fù)雜,性能問題 |
看起來Freemarker是一個(gè)不錯(cuò)的選擇。
至此兩步走小技巧已經(jīng)實(shí)現(xiàn)了,都是利用了現(xiàn)成的代碼實(shí)現(xiàn)。
或許我們會(huì)這樣的挑戰(zhàn),在做狀態(tài)值轉(zhuǎn)換時(shí)需要知道當(dāng)前系統(tǒng)某個(gè)業(yè)務(wù)狀態(tài)值的情況,
此時(shí)Freemarker表達(dá)式可能是這樣的,
<# assign lastCode = GetLastCode(code)> <#if lastCode == "2"> 2 <#elseif code == "200"> 2 <#else> 3 <#/if>
這里我們可以使用Freemarker的特性,自定義Java函數(shù)或工具類,在模板中調(diào)用。
代碼地址https://github.com/Honwhy/xml...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/110361.html
摘要:解析和內(nèi)容的一點(diǎn)技巧概述在沒有統(tǒng)一標(biāo)準(zhǔn)的情況下,一個(gè)系統(tǒng)對(duì)接多個(gè)外部系統(tǒng)往往會(huì)遇到請(qǐng)求接口響應(yīng)數(shù)據(jù)異構(gòu)的情況,有可能返回的是,也有可能返回。解析內(nèi)容也是同理的,只不過定義的是表達(dá)式。 解析XML和JSON內(nèi)容的一點(diǎn)技巧 概述 在沒有統(tǒng)一標(biāo)準(zhǔn)的情況下,一個(gè)系統(tǒng)對(duì)接多個(gè)外部系統(tǒng)往往會(huì)遇到請(qǐng)求接口響應(yīng)數(shù)據(jù)異構(gòu)的情況,有可能返回的是XML,也有可能返回JSON。除了返回類型不同,內(nèi)容結(jié)構(gòu)也不盡...
摘要:使用的思考使用過對(duì)象的程序員最常做的一項(xiàng)工作便是,將對(duì)象轉(zhuǎn)化為字符串。該字符串的用途很多,例如可以使用在的中,在多個(gè)頁面間進(jìn)行傳遞。因?yàn)槟J绞枪潭ǖ模敲炊x模式的空間開銷一定比使用該模式生成字符串的時(shí)間開銷代價(jià)要小很多。 使用JSON.stringify的思考 使用過JSON對(duì)象的程序員最常做的一項(xiàng)工作便是,將JSON對(duì)象轉(zhuǎn)化為字符串。該字符串的用途很多,例如可以使用在WEB的URL...
摘要:圖意淫爬蟲與反爬蟲間的對(duì)決數(shù)據(jù)的重要性如今已然是大數(shù)據(jù)時(shí)代,數(shù)據(jù)正在驅(qū)動(dòng)著業(yè)務(wù)開發(fā),驅(qū)動(dòng)著運(yùn)營手段,有了數(shù)據(jù)的支撐可以對(duì)用戶進(jìn)行用戶畫像,個(gè)性化定制,數(shù)據(jù)可以指明方案設(shè)計(jì)和決策優(yōu)化方向,所以互聯(lián)網(wǎng)產(chǎn)品的開發(fā)都是離不開對(duì)數(shù)據(jù)的收集和分析,數(shù) showImg(https://segmentfault.com/img/remote/1460000013428119?w=539&h=337)...
摘要:學(xué)編程真的不是一件容易的事不管你多喜歡或是多會(huì)編程,在學(xué)習(xí)和解決問題上總會(huì)碰到障礙。熟練掌握核心內(nèi)容,特別是和多線程初步具備面向?qū)ο笤O(shè)計(jì)和編程的能力掌握基本的優(yōu)化策略。 學(xué)Java編程真的不是一件容易的事,不管你多喜歡或是多會(huì)Java編程,在學(xué)習(xí)和解決問題上總會(huì)碰到障礙。工作的時(shí)間越久就越能明白這個(gè)道理。不過這倒是一個(gè)讓人進(jìn)步的機(jī)會(huì),因?yàn)槟阋恢辈粩嗟膶W(xué)習(xí)才能很好的解決你面前的難題...
閱讀 683·2021-11-23 09:51
閱讀 3275·2019-08-30 15:54
閱讀 440·2019-08-30 15:52
閱讀 3107·2019-08-30 13:58
閱讀 2912·2019-08-30 13:53
閱讀 2684·2019-08-29 14:18
閱讀 2407·2019-08-27 10:54
閱讀 2363·2019-08-26 18:09