Qunar機(jī)票客戶端Schema分發(fā)技術(shù)改造實踐

前菜 -- 科普

是什么

移動開發(fā)中所說的schema概念是指資一種自定義的資源標(biāo)示符融虽,格式是[scheme:][//authority][path][?query][#fragment]锐借,相當(dāng)于絕對路徑版的URI穴店,實在通俗的說,URL?的http(s)替換成自定義的協(xié)議頭骑篙,就是schema。

舉例一個國際航線搜索的schema可以是這樣(具體協(xié)議命名脫敏)


Paste_Image.png
有什么用

schema主要用作異構(gòu)體系之間的低耦合互操作方案森书,每個應(yīng)用/模塊都可以自定義的協(xié)議頭靶端。借助schema可以是實現(xiàn)比如touch頁中打開特定APP谎势,某APP觸發(fā)其他APP的功能,或是用于類似Qunar這樣組件化架構(gòu)的APP內(nèi)各組件間互操作躲查。

項目背景

做為Qunar移動端業(yè)務(wù)組件間以及與內(nèi)外互操作的主要機(jī)制它浅,單機(jī)票業(yè)務(wù)所提供的schema數(shù)量就有數(shù)十個。早期的做法是“見招拆招”镣煮,每加一種schema就加一個判斷姐霍,在schema規(guī)模擴(kuò)大后這種做法的維護(hù)效率會快速下降。

最初的schema處理方式(偽代碼)

String type = schema.getLastPathSegment();
...
if(type == 'search') {
    String flightType = map.get("flightType");
    if(flightType == 'oneway') {
        ...
    }
    if(flightType == 'round') {
        ...
    }
    if(flightType == 'multi') {
        ...
    }
}
if(type == 'orders') {
    ...
}

同時典唇,由于缺少有效的文檔同步機(jī)制和測試用例镊折,內(nèi)部的wiki已經(jīng)不能100%保證完整,如果PM/QA/schema調(diào)用方同學(xué)需要確認(rèn)app到底支持什么schema介衔,有什么樣的參數(shù)恨胚,大多時候竟然需要肉查代碼。

總的來說有三方面要改進(jìn):

  • 實現(xiàn)不夠先進(jìn)(理解修改使用麻煩)
  • 信息不對稱(文檔和編碼?割裂炎咖,且文檔缺失不完整)
  • 沒有簡單易用的測試機(jī)制來驗證schema相關(guān)代碼的增刪改

改造成啥樣赃泡?

最簡化的模型

所謂的schema處理其實就是干這么個事情,給定一個schema乘盼,找到并執(zhí)行一段代碼升熊。

Paste_Image.png

這事兒看上去實在太簡單了。绸栅。级野。不過也能幫我們看的更透徹,其實改造的關(guān)鍵是實現(xiàn)一個schema到對應(yīng)執(zhí)行點的匹配分發(fā)機(jī)制粹胯。

要易維護(hù)蓖柔、要直觀、要schema支持范圍可確定性......首先想到用某種配置作為匹配的依據(jù)

Paste_Image.png

技術(shù)改造類項目风纠,如果僅是讓大家開發(fā)起來爽+快况鸣,或許是最低的標(biāo)準(zhǔn),為了讓這個改造能在開發(fā)以外的方面產(chǎn)生協(xié)同效應(yīng)竹观,我們要考慮借此項目一并解決文檔缺失和難于測試的痛點懒闷。

辣么期望達(dá)到的效果是:

  • 基于某種配置自動識別schema?該由誰來處理(基于配置的匹配分發(fā))
  • 能夠基于配置生成文檔(自解釋性)
  • 能夠加載schema測試樣本源并對接到我們的自動化測試系統(tǒng)

Finally, 完整的架構(gòu)

Paste_Image.png

如何使用?超級簡

Paste_Image.png

Query/Test Tools保真效果頁面(Powered by Adobe XD)

點我看Showcase
features:

  • 查看當(dāng)前App受支持的所有schema
  • 從schema樣本源中篩選不被支持的schema

主要角色栈幸、行為含義解釋:

  • schema配置信息:包括schema表達(dá)式愤估、分發(fā)執(zhí)行的落腳點、文檔說明和樣例schema等速址。
  • Entry:schema的入口玩焰,對安卓來說是manifest.xml中定義的intent-filter對應(yīng)的組件
  • Registration:schema規(guī)則注冊器,提供規(guī)則的裝載注冊和匹配查找能力芍锚。
  • Dispatch:schema分發(fā)器昔园,接收schema并使用Registration做查詢和分發(fā)處理蔓榄。
  • Producer:執(zhí)行器包裝?,每個schema配置在運行時層面都對應(yīng)一個Producer默刚,將具體的反射甥郑、傳參等可能對規(guī)則變化封閉在內(nèi)部。
  • SchemaHandler:執(zhí)行各個schema的實現(xiàn)類
  • dump:導(dǎo)出app所支持的schema配置信息
  • Test/Query:查詢/測試schema是否被當(dāng)前app支持并提供反饋結(jié)果
  • Document:可閱讀的schema說明文檔

數(shù)據(jù)事件流轉(zhuǎn)說明

  • schema通過intent-filter傳遞到Entry組件(activity或receiver等)
  • Entry中初始化Dispatch荤西,并將schema和Bundle交付給Dispatch做分發(fā)
  • Dispatch通過Registration查詢到Producer并傳入uri和bundle
  • Producer將schema和bundle做參數(shù)提取成字典結(jié)構(gòu)澜搅,構(gòu)造SchemaHandler實例并執(zhí)行。

關(guān)鍵細(xì)節(jié)實現(xiàn)思路

如何匹配schema

schema可以看成一種表達(dá)式邪锌,我們設(shè)計了一個表達(dá)式規(guī)則來判定指定的schema是否和我的schema表達(dá)式規(guī)則兼容勉躺。

Paste_Image.png

分為三部分:

  • 第一部分protocol+host(也叫authority)對于每個業(yè)務(wù)組件是確定的;
  • 第二部分是path觅丰,不同含義的schema的path一定不同(比如航班搜索是search饵溅,航班動態(tài)是status),相同的path可能會有多個行為妇萄;
航班搜索-單程:sopaco://flight/search?module=oneway&depCity=BJS...
航班搜索-往返:sopaco://flight/search?module=roundway&depCity=BJS...
航 班 動 態(tài): sopaco://flight/status?depCity=BJS...
  • 第三部分是模糊匹配的參數(shù)區(qū)蜕企,我們總結(jié)了目前用到的幾種特定參數(shù)值如枚舉值、日期冠句、數(shù)字轻掩、必須字段、可選字段轩端。

模糊匹配值表達(dá)方式:


Paste_Image.png

如何轉(zhuǎn)化為配置

配置信息中除了要包含schema表達(dá)式,還要有對應(yīng)的函數(shù)執(zhí)行標(biāo)識逝变,考慮到要能自解釋生成文檔基茵,還需要攜帶本身的說明信息。我們選擇用java interface + annotation來作配置載體壳影。

Paste_Image.png

其中X.classSchemaHandler的實現(xiàn)

public interface SchemaHandler {
    void handle(SchemaContext context, Uri originalSchema, Map<String, String> params, Bundle extra);
}

這個interface不需要實現(xiàn)類也不需要實例化拱层,僅利用annotation語法做配制標(biāo)注作用并享受語法檢查的便利,每個函數(shù)名稱命名隨意宴咧,在@Schema中聲明schema表達(dá)式規(guī)則和對應(yīng)的實現(xiàn)類根灯。

讀取配置

?設(shè)計一個Registration組件(類似于協(xié)議注冊中心的概念),來加載業(yè)務(wù)線的schema分發(fā)規(guī)則配置是ISchemaProtocol.class掺栅,核心方法是裝載配置的函數(shù)setupmatch匹配的schema處理器烙肺。

Paste_Image.png

setup函數(shù)實現(xiàn)

public <Protocol> void setup(Class<Protocol> contract) {
        Method[] methods = contract.getMethods();
        for (Method method : methods) {
            Schema schemaConfig = method.getAnnotation(Schema.class);
            Class<? extends SchemaHandler> executor = schemaConfig.executor();
            Producer producer = new Producer(method, executor);
            SchemaPattern pattern = new SchemaPattern(schemaConfig, producer);
            SchemaDocument schemaDoc = method.getAnnotation(SchemaDocument.class);
            pattern.setDocument(schemaDoc);
            patterns.add(pattern);
        }
    }

衍生物-自解釋文檔

所謂自解釋文檔,就是app應(yīng)該能把自己能支持的schema都有哪些氧卧、參數(shù)都是啥桃笙、說明信息等dump出來并以某種形式展示,我們在ISchemaProtocol.class上沙绝,增加了@SchemaDocument這樣一個標(biāo)注搏明,和@Schema不同的是這個要區(qū)分production構(gòu)建環(huán)境鼠锈,在gradle里配置兩套SchemaDocument的實現(xiàn),release下是source級別的標(biāo)注星著,這樣線上包編譯期間就能丟掉SchemaDocument购笆,僅在beta/dev做RUNTIME標(biāo)注。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Inherited
public @interface SchemaDocument {
    String title();
    String content() default "該配置無說明";
    String sample() default "";
}

配套的schema toolkit頁面虚循,能看到app中受支持的所有schema表達(dá)式同欠。

Paste_Image.png

衍生物-對接自動化測試

自動化測試要做的是提供一份schema用例樣本,app能識別出其中所支持/不支持的schema邮丰,對支持的schema行您,并且通過QA團(tuán)隊之前搞的自動化圖像對比工具,在每次發(fā)版前對比新舊版本相同schema跳轉(zhuǎn)后的頁面切合度是否一致剪廉。

效果請點擊看Showcase(based on Adobe XD)

現(xiàn)已拆分為QunarSchemaDispatcher庫項目

該項目已經(jīng)拆分出庫版本供其他業(yè)務(wù)線同學(xué)使用
http://gitlab.corp.qunar.com/mobile_flight_adr/qschemadispatcher

業(yè)界類似方案和區(qū)別

對schema處理娃循,目前在業(yè)界開源放出來的主流方案有Airbnb的DeepLinkDispatch和阿里巴巴的ARouter,這倆的思路和做法幾乎是一樣的斗蒋,通過在schema落地組件上直接加annotatio實現(xiàn)點對點的"鏈接"并且支持依賴屬性注入配置捌斧,為了達(dá)到對直連組件的零侵入性,對標(biāo)注的處理使用了APT技術(shù)在編譯前生成了Navigator Delegate代碼而非運行時反射泉沾。

DeepLinkDispatch和ARouter都是現(xiàn)階段開源出來的優(yōu)秀方案捞蚂,如果是全新的項目無腦選就是了。但不適用于像我們這種已經(jīng)積累了幾十個schema業(yè)務(wù)處理繁雜帶包袱需要在短期優(yōu)化核心痛點的項目跷究,如果選用就意味著完整的重寫姓迅,產(chǎn)生很高的測試驗證成本。而我們的這個方案只需修改整個schema處理鏈中前置的匹配和分發(fā)環(huán)節(jié)俊马,最終的schema業(yè)務(wù)邏輯處理部分(SchemaHandler)只是搬代碼丁存,解決關(guān)鍵問題同時降低重構(gòu)風(fēng)險。

我是無法屏蔽的廣告位

我們在國內(nèi)頂尖的在線旅游平臺去哪兒網(wǎng)的主干力量機(jī)票事業(yè)部中最懂C端的用戶產(chǎn)品部柴我,歡迎各路移動端精英加入解寝。
職位描述:
1.負(fù)責(zé)移動端技術(shù)分析和設(shè)計工作,解決技術(shù)難題和技術(shù)攻關(guān)突破艘儒,保證app穩(wěn)健聋伦、高效運行。
2.針對復(fù)雜業(yè)務(wù)進(jìn)行架構(gòu)和重構(gòu)編碼界睁,設(shè)計有效的技術(shù)方案并推動提高業(yè)務(wù)交付效率觉增。
3.對移動端進(jìn)行性能和質(zhì)量優(yōu)化。
4.感知業(yè)內(nèi)技術(shù)變革趨勢并合理運用到實際項目中翻斟。

職位要求:
1.2年以上Android應(yīng)用開發(fā)經(jīng)驗抑片,3年以上java開發(fā)經(jīng)驗。
2.精通java語言杨赤,在數(shù)據(jù)結(jié)構(gòu)敞斋、算法截汪、設(shè)計模式和架構(gòu)上有扎實的技術(shù)功底。
3.熟悉主流的android應(yīng)用設(shè)計思路植捎、開發(fā)架構(gòu)和框架
4.有性能調(diào)優(yōu)經(jīng)驗衙解,熟練使用常用tracer/profiler工具,能針對app性能和質(zhì)量的相關(guān)性指標(biāo)實施監(jiān)控和改進(jìn)方案焰枢。
5.對業(yè)內(nèi)熱點技術(shù)趨勢如rx響應(yīng)式編程蚓峦、mvp/vm、APT/aspectJ济锄、react-native泛前端等技術(shù)有深刻理解并在移動端的有實踐經(jīng)驗暑椰。
5.具備有效的溝通能力、團(tuán)隊協(xié)作意識和工作責(zé)任心荐绝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末一汽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子低滩,更是在濱河造成了極大的恐慌召夹,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恕沫,死亡現(xiàn)場離奇詭異监憎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)婶溯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門鲸阔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迄委,你說我怎么就攤上這事褐筛。” “怎么了跑筝?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵死讹,是天一觀的道長瞒滴。 經(jīng)常有香客問我曲梗,道長,這世上最難降的妖魔是什么妓忍? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任虏两,我火速辦了婚禮,結(jié)果婚禮上世剖,老公的妹妹穿的比我還像新娘定罢。我一直安慰自己,他們只是感情好旁瘫,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布祖凫。 她就那樣靜靜地躺著琼蚯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惠况。 梳的紋絲不亂的頭發(fā)上遭庶,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音稠屠,去河邊找鬼峦睡。 笑死,一個胖子當(dāng)著我的面吹牛权埠,可吹牛的內(nèi)容都是我干的榨了。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼攘蔽,長吁一口氣:“原來是場噩夢啊……” “哼龙屉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秩彤,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤叔扼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后漫雷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓜富,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年降盹,在試婚紗的時候發(fā)現(xiàn)自己被綠了与柑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蓄坏,死狀恐怖价捧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涡戳,我是刑警寧澤结蟋,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站渔彰,受9級特大地震影響嵌屎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恍涂,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一宝惰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧再沧,春花似錦尼夺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寝衫。三九已至,卻和暖如春拐邪,著一層夾襖步出監(jiān)牢的瞬間竞端,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工庙睡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留事富,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓乘陪,卻偏偏與公主長得像统台,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子啡邑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理贱勃,服務(wù)發(fā)現(xiàn),斷路器谤逼,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,072評論 25 707
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,803評論 6 342
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫贵扰、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評論 4 62
  • 對于git老版本或者對于一些不需要過于管理嚴(yán)苛的私人項目流部,可以使用以下的格式進(jìn)行clone:git clone h...
    stiller閱讀 867評論 0 0