智联招聘App架构
一、智联招聘App架构模式简介
智联App前身
智联App一开始是只有一个单独工程在运行的App模式,里面掺杂着各种设计模式,诸如MVC、MVP、MVVM等等,还有各种不知道是什么来着的设计模式。模块代码耦合度高,业务代码历史包袱沉重等问题。
智联App现在
现在智联App采用了组件化的方式,将一个臃肿,复杂的单一工程的项目,根据功能或者业务进行分解,拆分成为各个独立的功能模块或者组件,最后统一组合成完整的App。解决了原来高耦合、易冲突、并行开发效率低下的问题。
关于什么是组件化开发
,我在之前一篇文章里iOS组件化之路有提到,大家可以移步过去看一下(Android遍稍后补上
)。
二、智联招聘App架构图解

每个业务模块都是一个独立存在、可独立运行和打包的子工程,原来的主工程则变成一个壳工程。
不同的子工程可以根据需求依赖其他子工程来独立运行,每个子工程都有他自己的版本号,比如子工程A,v1.1.0版本可以和子工程B的v2.1.0版本组合打包,也可以和子工程C的v1.3.1版本组合打包。
这样的好处是加快编译速度(不用编译主工程那一大坨代码了),减少对主工程的依赖,更方便QA同学去针对性测试。而且加快业务线发版效率(每个子工程都有自己的Git仓库和版本号,可以更方便的进行版本管理,多版本的并行开发)

三、路由组件
要实现这些单模块的拆分和组合,其中一个最主要也是最核心的组件,就是这个Router,所有模块间的交互和联调,都要经过这个Router。

Router在组件化工程中的作用是什么,从上图可以看出,其实路由所做的工作,就是把各个模块的互相依赖和耦合给抽离出来。
智联App路由组件
iOS组件ZPRouter

一、功能介绍
- 支持解析标准URL进行跳转,支持传递参数
- 支持回调传值
- 支持用户指定全局降级与局部降级策略
- 支持添加多个全局拦截器和某个页面自定义拦截
- 支持动态修改路径
- 支持模块解耦(供应者)
- 支持第三方APP跳转
二、典型应用
- 从外部URL映射到内部页面,以及参数传递与解析
- 跨模块页面跳转,模块间解耦
- 拦截跳转过程,处理登陆、埋点等逻辑
- 跨模块API调用,通过控制反转来做组件解耦
Android组件ARouter
Android的路由组件是基于阿里巴巴的ARouter
进行的二次开发,具体ARouter
的使用,可以参考ARouter的Git库的介绍
另外iOS的路由组件,具体大家可以移步看一下我们的另一篇文章,iOS路由组件
四、智联招聘网络框架
iOS网络框架ZPMNetwork
ZPMNetwork 是什么
ZPMNetwork 是智联招聘 iOS 研发团队基于 AFNetworking 封装的 iOS 网络库,其实现了一套 High Level 的 ZPMNetwork 现在同时被使用在公司的所有产品的 iOS 端,包括:智联招聘、智联企业版。
ZPMNetwork 提供了哪些功能
相比 AFNetworking,ZPMNetwork 提供了以下更高级的功能:
- 支持按时间缓存网络请求内容
- 支持按版本号缓存网络请求内容
- 支持统一设置服务器和 CDN 的地址
- 支持检查返回 JSON 内容的合法性
- 支持文件的断点续传
- 支持
block
和delegate
两种模式的回调方式 - 支持批量的网络请求发送,并统一设置它们的回调(实现在
ZPMBatchRequest
类中) - 支持方便地设置有相互依赖的网络请求的发送,例如:发送请求 A,根据请求 A 的结果,选择性的发送请求 B 和 C,再根据 B 和 C 的结果,选择性的发送请求 D。(实现在
ZPMChainRequest
类中) - 支持网络请求 URL 的 filter,可以统一为网络请求加上一些参数,或者修改一些路径。
- 定义了一套插件机制,可以很方便地为 ZPMNetwork 增加功能。例如,可以在某些网络请求发起时,在界面上显示“正在加载”的 HUD。
ZPMNetwork 的基本思想
ZPMNetwork 的基本的思想是把每一个网络请求封装成对象。所以使用 ZPMNetwork,你的每一个请求都需要继承 ZPMRequest
类,通过覆盖父类的一些方法来构造指定的网络请求。
把每一个网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:
- 将网络请求与具体的第三方库依赖隔离,方便以后更换底层的网络库。
- 方便在基类中处理公共逻辑,例如版本号信息就统一在基类中处理。
- 方便在基类中处理缓存逻辑,以及其它一些公共逻辑。
- 方便做对象的持久化。
ZPMNetwork架构图

Android网络架构ZhaopinHttp
ZhaopinHttp 是什么
ZhaopinHttp是智联招聘 Android 研发团队基于 [okhttp-OkGo][okhttp-OkGo] 封装的Android 网络库,提供给智联android 开发团队使用,包括:智联招聘、智联企业版。
ZhaopinHttp 提供了哪些功能
相比 B/C端老旧网络框架,ZhaopinHttp 提供了以下更高级的功能:
- 一般的 get,post,put,delete,head,options请求
- 基于Post的大文本数据上传
- 多文件和多参数统一的表单上传
- 支持一个key上传一个文件,也可以一个Key上传多个文件
- 大文件下载和下载进度回调
- 大文件上传和上传进度回调
- 支持cookie的内存存储和持久化存储,支持传递自定义cookie
- 支持304缓存协议,扩展四种本地缓存模式,并且支持缓存时间控制
- 支持301、302重定向
- 支持可信证书和自签名证书的https的访问,支持双向认证
- 支持根据Tag取消请求
- 支持自定义泛型Callback,自动根据泛型返回对象
- 支持可信证书和自签名证书的https的访问,支持双向认证
ZhaopinHttp 的基本思想
ZhaopinHttp 的基本的思想是把每一个网络请求形成一个实例,以Builder的模式进行功能扩展及暴露方法,链式请求传入APi、MAP等可配置信息回调。支持泛型和实体类两种方式,解析层有内部解析和Response 回传的方式外部String 解析,便于外部根据业务建立项目的拦截机制。
ZhaopinHttp架构图

五、持续集成CI系统
什么是持续集成
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
没有CI之前的流程图

使用CI之后的流程图

智联App的iOS的持续集成

智联App的Android的持续集成

智联移动App持续集成系统结构图:

集成软件的过程不是新问题,如果项目开发的规模比较小,比如一个人的项目,如果它对外部系统
的依赖很小,那么软件集成不是问题,但是随着软件项目复杂度的增加(即使增加一个人),就会对集成和确保软件组件能够在一起工作提出了更多的要求-要早集成,常集成。早集成,频繁的集成帮助项目在早期发现项目风险和质量问题,如果到后期才发现这些问题,解决问题代价很大,很有可能导致项目延期或者项目失败。
持续化构建带来的自动化发布和自动化测试,可以避免人为发包忘记环境切换或者参数配置出错的问题。同时减少开发人员的打包时间,提升了开发效率。
六、降级方案
一个完整的App,除了有路由、网络、CI系统、还必须有对应的降级方案。所谓的降级方案,就是当一个线上页面(或模块)出问题后,使用某种方法对这个页面(或模块)进行降级处理,比如Native页面切换成h5或者weex,甚至灰度的关闭该模块等方式,去保护线上App的稳定性和用户体验,以保障用户使用App的流程完整性。
智联的四级通道

智联的降级方案从上往下分为四种:
- App级别
- 路由级别
- 模块级别
- 单独模块内部级别
App级别
分为版本升级和App本身的容错处理,此级别为最上层级别,当发生了不可控的错误,只能通过版本升级来处理时,采取此方法;
路由级别
可以灵活的通过服务下发的命令,自由调度页面间的跳转,甚至模块间的调度方式。比如A页面出现了问题(App崩溃等不可控的情况),可以通过服务器下发的命令,暂时关闭此模块;
模块级别
通过页面的切换来确保线上流程的完整性,比如A页面是Weex页,服务器出现问题后,可通过配置切换到Native或者h5页面去支持线上完整的业务流程(淘宝的订单页也会经常性的切换到h5);
七、其他提升
1、版本管理
之前的App升级提示只能按照小于某个版本来提示,比如最新版本是7.9.0,选择7.9.0之后,那么小于这个版本的诸如7.8.9等版本都会收到升级提示。看似合理,但是实际上无法做到自由控制版本的提示,比如在7.9.0之前有几个版本,比如7.7.0,7.8.1有严重bug,其他版本没有此类bug,就无法做到我只提示这2个版本升级,而其他版本不提示。
另外还有一点就是老的升级只能控制是强制升级还是普通升级。但是一旦选了强制升级,其他版本就无法显示普通升级。比如我想7.8.5以下版本都提示强制升级,但是7.8.6、7.8.7等小于7.9.0版本普通升级,就无法做到。
新架构版本的App升级提示优化了这一点,既可以控制哪个版本升级提示,还能选定是强制还是普通升级。除此之外,还能自由控制每个版本的提示文案、升级App的下载地址。


这个安装包地址,是为了防止你的App哪天被下架了,而你又有一个小号App在上面,那么你就可以利用这个升级提示,把用户引导到你的另一个App上。
2、标签管理

这个标签,实际上是底部的tabbar,通过这个标签管理,可以在后台随时配置App底部tabbar的item的是否显示、显示的位置,显示多少个item,还有进入App后优先显示哪个tabbar的页面等,都可以自由控制。
另外还支持按比例来灰度显示,比如让百分之多少的用户这样显示,另外的百分之几的用户显示其他的item。

3、路由控制
可以自由配置页面间的跳转,甚至层级关系,比如原来A页面是要跳转到B页面的,可以通过后台配置,将A页面的跳转改为跳到C页面。甚至还可以改变他们直接的层级关系,比如原来的A页面是一级页面,B页面属于二级页面,可以通过路由控制,让B页面变成一级,A变成二级页面(当然,技术上是可行的,但要考虑到业务逻辑,所以还是得提前适配的)。
有了这个自由控制,诸如一些模块的某个页面出现了问题,就可以通过这个路由控制来替换其他页面,或者关闭这个有问题的模块。
4、业务管理
用来控制具体页面模块的灰度分发比例、模块的显示内容、显示数量等。比如首页列表的样式、列表的长度是20个还是40个还是100个。还可以根据灰度分发比例,让不同的用户看到的内容是不一样的。