Qunar机票客户端Schema分发技术改造实践

前菜 -- 科普

是什么

移动开发中所说的schema概念是指资一种自定义的资源标示符,格式是[scheme:][//authority][path][?query][#fragment],相当于绝对路径版的URI,实在通俗的说,URL�的http(s)替换成自定义的协议头,就是schema。

举例一个国际航线搜索的schema可以是这样(具体协议命名脱敏)


Paste_Image.png
有什么用

schema主要用作异构体系之间的低耦合互操作方案,每个应用/模块都可以自定义的协议头。借助schema可以是实现比如touch页中打开特定APP,某APP触发其他APP的功能,或是用于类似Qunar这样组件化架构的APP内各组件间互操作。

项目背景

做为Qunar移动端业务组件间以及与内外互操作的主要机制,单机票业务所提供的schema数量就有数十个。早期的做法是“见招拆招”,每加一种schema就加一个判断,在schema规模扩大后这种做法的维护效率会快速下降。

最初的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') {
    ...
}

同时,由于缺少有效的文档同步机制和测试用例,内部的wiki已经不能100%保证完整,如果PM/QA/schema调用方同学需要确认app到底支持什么schema,有什么样的参数,大多时候竟然需要肉查代码。

总的来说有三方面要改进:

  • 实现不够先进(理解修改使用麻烦)
  • 信息不对称(文档和编码�割裂,且文档缺失不完整)
  • 没有简单易用的测试机制来验证schema相关代码的增删改

改造成啥样?

最简化的模型

所谓的schema处理其实就是干这么个事情,给定一个schema,找到并执行一段代码。

Paste_Image.png

这事儿看上去实在太简单了。。。不过也能帮我们看的更透彻,其实改造的关键是实现一个schema到对应执行点的匹配分发机制

要易维护、要直观、要schema支持范围可确定性......首先想到用某种配置作为匹配的依据

Paste_Image.png

技术改造类项目,如果仅是让大家开发起来爽+快,或许是最低的标准,为了让这个改造能在开发以外的方面产生协同效应,我们要考虑借此项目一并解决文档缺失和难于测试的痛点。

辣么期望达到的效果是:

  • 基于某种配置自动识别schema�该由谁来处理(基于配置的匹配分发)
  • 能够基于配置生成文档(自解释性)
  • 能够加载schema测试样本源并对接到我们的自动化测试系统

Finally, 完整的架构

Paste_Image.png

如何使用?超级简

Paste_Image.png

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

点我看Showcase
features:

  • 查看当前App受支持的所有schema
  • 从schema样本源中筛选不被支持的schema

主要角色、行为含义解释:

  • schema配置信息:包括schema表达式、分发执行的落脚点、文档说明和样例schema等。
  • Entry:schema的入口,对安卓来说是manifest.xml中定义的intent-filter对应的组件
  • Registration:schema规则注册器,提供规则的装载注册和匹配查找能力。
  • Dispatch:schema分发器,接收schema并使用Registration做查询和分发处理。
  • Producer:执行器包装�,每个schema配置在运行时层面都对应一个Producer,将具体的反射、传参等可能对规则变化封闭在内部。
  • SchemaHandler:执行各个schema的实现类
  • dump:导出app所支持的schema配置信息
  • Test/Query:查询/测试schema是否被当前app支持并提供反馈结果
  • Document:可阅读的schema说明文档

数据事件流转说明

  • schema通过intent-filter传递到Entry组件(activity或receiver等)
  • Entry中初始化Dispatch,并将schema和Bundle交付给Dispatch做分发
  • Dispatch通过Registration查询到Producer并传入uri和bundle
  • Producer将schema和bundle做参数提取成字典结构,构造SchemaHandler实例并执行。

关键细节实现思路

如何匹配schema

schema可以看成一种表达式,我们设计了一个表达式规则来判定指定的schema是否和我的schema表达式规则兼容。

Paste_Image.png

分为三部分:

  • 第一部分protocol+host(也叫authority)对于每个业务组件是确定的;
  • 第二部分是path,不同含义的schema的path一定不同(比如航班搜索是search,航班动态是status),相同的path可能会有多个行为;
航班搜索-单程:sopaco://flight/search?module=oneway&depCity=BJS...
航班搜索-往返:sopaco://flight/search?module=roundway&depCity=BJS...
航 班 动 态: sopaco://flight/status?depCity=BJS...
  • 第三部分是模糊匹配的参数区,我们总结了目前用到的几种特定参数值如枚举值、日期、数字、必须字段、可选字段。

模糊匹配值表达方式:


Paste_Image.png

如何转化为配置

配置信息中除了要包含schema表达式,还要有对应的函数执行标识,考虑到要能自解释生成文档,还需要携带本身的说明信息。我们选择用java interface + annotation来作配置载体。

Paste_Image.png

其中X.classSchemaHandler的实现

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

这个interface不需要实现类也不需要实例化,仅利用annotation语法做配制标注作用并享受语法检查的便利,每个函数名称命名随意,在@Schema中声明schema表达式规则和对应的实现类。

读取配置

�设计一个Registration组件(类似于协议注册中心的概念),来加载业务线的schema分发规则配置是ISchemaProtocol.class,核心方法是装载配置的函数setupmatch匹配的schema处理器。

Paste_Image.png

setup函数实现

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应该能把自己能支持的schema都有哪些、参数都是啥、说明信息等dump出来并以某种形式展示,我们在ISchemaProtocol.class上,增加了@SchemaDocument这样一个标注,和@Schema不同的是这个要区分production构建环境,在gradle里配置两套SchemaDocument的实现,release下是source级别的标注,这样线上包编译期间就能丢掉SchemaDocument,仅在beta/dev做RUNTIME标注。

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

配套的schema toolkit页面,能看到app中受支持的所有schema表达式。

Paste_Image.png

衍生物-对接自动化测试

自动化测试要做的是提供一份schema用例样本,app能识别出其中所支持/不支持的schema,对支持的schema,并且通过QA团队之前搞的自动化图像对比工具,在每次发版前对比新旧版本相同schema跳转后的页面切合度是否一致。

效果请点击看Showcase(based on Adobe XD)

现已拆分为QunarSchemaDispatcher库项目

该项目已经拆分出库版本供其他业务线同学使用
http://gitlab.corp.qunar.com/mobile_flight_adr/qschemadispatcher

业界类似方案和区别

对schema处理,目前在业界开源放出来的主流方案有Airbnb的DeepLinkDispatch和阿里巴巴的ARouter,这俩的思路和做法几乎是一样的,通过在schema落地组件上直接加annotatio实现点对点的"链接"并且支持依赖属性注入配置,为了达到对直连组件的零侵入性,对标注的处理使用了APT技术在编译前生成了Navigator Delegate代码而非运行时反射。

DeepLinkDispatch和ARouter都是现阶段开源出来的优秀方案,如果是全新的项目无脑选就是了。但不适用于像我们这种已经积累了几十个schema业务处理繁杂带包袱需要在短期优化核心痛点的项目,如果选用就意味着完整的重写,产生很高的测试验证成本。而我们的这个方案只需修改整个schema处理链中前置的匹配和分发环节,最终的schema业务逻辑处理部分(SchemaHandler)只是搬代码,解决关键问题同时降低重构风险。

我是无法屏蔽的广告位

我们在国内顶尖的在线旅游平台去哪儿网的主干力量机票事业部中最懂C端的用户产品部,欢迎各路移动端精英加入。
职位描述:
1.负责移动端技术分析和设计工作,解决技术难题和技术攻关突破,保证app稳健、高效运行。
2.针对复杂业务进行架构和重构编码,设计有效的技术方案并推动提高业务交付效率。
3.对移动端进行性能和质量优化。
4.感知业内技术变革趋势并合理运用到实际项目中。

职位要求:
1.2年以上Android应用开发经验,3年以上java开发经验。
2.精通java语言,在数据结构、算法、设计模式和架构上有扎实的技术功底。
3.熟悉主流的android应用设计思路、开发架构和框架
4.有性能调优经验,熟练使用常用tracer/profiler工具,能针对app性能和质量的相关性指标实施监控和改进方案。
5.对业内热点技术趋势如rx响应式编程、mvp/vm、APT/aspectJ、react-native泛前端等技术有深刻理解并在移动端的有实践经验。
5.具备有效的沟通能力、团队协作意识和工作责任心。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,546评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,223评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,704评论 6 342
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,972评论 4 60
  • 对于git老版本或者对于一些不需要过于管理严苛的私人项目,可以使用以下的格式进行clone:git clone h...
    stiller阅读 856评论 0 0