h5专业 移动软件开发 还有一些其他的那种比较好!本人英语不行!在希望的田野上大神们给一些建设性的回答!

iOS 应用架构谈 动态部署方案
招聘信息:
前言这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容、新的业务流程部署进已发布的App。因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的手段来达到动态部署方案的目的。这篇文章主要的目的就是给大家列举一下目前业界做动态部署的手段,以及其对应的优缺点。然后给出一套我比较倾向于使用的方案。其实单纯就动态部署方案来讲,没什么太多花头可以说的,就是H5、Lua、JS、OC/Swift这几门基本技术的各种组合排列。写到后面觉得,动态部署方案其实是非常好的用于讲解某些架构模式的背景。一般我们经验总结下来的架构模式包括但不限于:Layered ArchitectureEvent-Driven ArchitectureMicrokernel ArchitectureMicroservices ArchitectureSpace-Based Architecture我在里面提到的MVC等方案跟这篇文章中要提到的架构模式并不是属于同一个维度的。比较容易混淆的就是容易把MVC这些方案跟Layered Architecture混淆,这个我在这篇文章里面也做过了区分:MVC等方案比较侧重于数据流动方向的控制和数据流的管理。Layered Architecture更加侧重于各分层之间的功能划分和模块协作。另外,上述五种架构模式在这本书里有非常详细的介绍,整本书才45页,个把小时就看完了,非常值得看和思考。本文后半篇涉及的架构模式是以上架构模式的其中两种:Microkernel Architecture和Microservices Architecture。最后,文末还给出了其他一些关于架构模式的我觉得还不错的PPT和论文,里面对架构模式的分类和总结也比较多样,跟Software Architecture Patterns的总结也有些许不一样的地方,可以博采众长。Web App实现方案其实所谓的web app,就是通过手机上的浏览器进行访问的H5页面。这个H5页面是针对移动场景特别优化的,比如UI交互等。优点无需走苹果流程,所有苹果流程带来的成本都能避免,包括审核周期、证书成本等。版本更新跟网页一样,随时生效。不需要Native App工程师的参与,而且市面上已经有很多针对这种场景的框架。缺点由于每一页都需要从服务器下载,因此web app重度依赖网络环境。同样的UI效果使用web app来实现的话,流畅度不如Native,比较影响用户体验。本地持久化的部分很难做好,绕过本地持久化的部分的办法就是提供账户体系,对应账户的持久化数据全部存在服务端。即时响应方案、远程通知实现方案、移动端传感器的使用方案复杂,维护难度大。安全问题,H5页面等于是所有东西都暴露给了用户,如果对安全要求比较高的,很多额外的安全机制都需要在服务端实现。总结web app一般是创业初期会重点考虑的方案,因为迭代非常快,而且创业初期的主要目标是需要验证模式的正确性,并不在于提供非常好的用户体验,只需要完成闭环即可。早年facebook曾经尝试过这种方案,最后因为用户体验的问题而宣布放弃。所以这个方案只能作为过渡方案,或者当App不可用时,作为降级方案使用。Hybrid App通过市面上各种Hybrid框架,来做H5和Native的混合应用,或者通过JS Bridge来做到H5和Native之间的数据互通。优点除了要承担苹果流程导致的成本以外,具备所有web app的优势能够访问本地数据、设备传感器等缺点跟web app一样存在过度依赖网络环境的问题用户体验也很难做到很好安全性问题依旧存在大规模的数据交互很难实现,例如图片在本地处理后,将图片传递给H5总结Hybrid方案更加适合跟本地资源交互不是很多,然后主要以内容展示为主的App。在天猫App中,大量地采用了JS Bridge的方式来让H5跟Native做交互,因为天猫App是一个以内容展示为主的App,且营销活动多,周期短,比较适合Hybrid。React-Native严格来说,React-Native应当放到Hybrid那一节去讲,单独拎出来的原因是Facebook自从放出React-Native之后,业界讨论得非常激烈。天猫的鬼道也做了非常多的关于React-Native的分享。React-Native这个框架比较特殊,它展示View的方式依然是Native的View,然后也是可以通过URL的方式来动态生成View。而且,React-Native也提供了一个Bridge通道来做Javascript和Objective-C之间的交流,还是很贴心的。然而研究了一下发现有一个比较坑的地方在于,解析JS要生成View时所需要的View,是要本地能够提供的。举个例子,比如你要有一个特定的Mapview,并且要响应对应的delegate方法,在React-Native的环境下,你需要先在Native提供这个Mapview,并且自己实现这些delegate方法,在实现完方法之后通过Bridge把数据回传给JS端,然后重新渲染。在这种情况下我们就能发现,其实React-Native在使用View的时候,这些View是要经过本地定制的,并且将相关方法通过RCT_EXPORT_METHOD暴露给js,js端才能正常使用。在我看来,这里在一定程度上限制了动态部署时的灵活性,比如我们需要在某个点击事件中展示一个动画或者一个全新的view,由于本地没有实现这个事件或没有这个view,React-Native就显得捉襟见肘。优点响应速度很快,只比Native慢一点,比webview快很多。能够做到一定程度上的动态部署缺点组装页面的元素需要Native提供支持,一定程度上限制了动态部署的灵活性。总结由于React-Native框架中,因为View的展示和View的事件响应分属于不同的端,展示部分的描述在JS端,响应事件的监听和描述都在Native端,通过Native转发给JS端。所以,从做动态部署的角度上讲,React-Native只能动态部署新View,不能动态部署新View对应的事件。当然,React-Native本身提供了很多基础组件,然而这个问题仍然还是会限制动态部署的灵活性。因为我们在动态部署的时候,大部分情况下是希望View和事件响应一起改变的。另外一个问题就在于,View的原型需要从Native中取,这个问题相较于上面一个问题倒是显得不那么严重,只是以后某个页面需要添加某个复杂的view的时候,需要从现有的组件中拼装罢了。所以,React-Native事实上解决的是如何不使用Objc/Swift来写iOS App的View的问题,对于如何通过不发版来给已发版的App更新功能这样的问题,帮助有限。Lua Patch大众点评的屠毅敏同学在基于的基础上写了,这个工具的主要原理是通过lua来针对objc的方法进行替换,由于lua本身是解释型语言,可以通过动态下载得到,因此具备了一定的动态部署能力。然而iOS系统原生并不提供lua的解释库,所以需要在打包时把lua的解释库编译进app。优点能够通过下载脚本替换方法的方式,修改本地App的行为。执行效率较高缺点对于替换功能来说,lua是很不错的选择。但如果要添加新内容,实际操作会很复杂很容易改错,小问题变成大问题总结lua的解决方案在一定程度上解决了动态部署的问题。实际操作时,一般不使用它来做新功能的动态部署,主要还是用于修复bug时代码的动态部署。实际操作时需要注意的另外一点是,真的很容易改错,尤其是你那个方法特别长的时候,所以改了之后要彻底回归测试一次。Javascript Patch这个工作原理其实跟上面说的lua那套方案的工作原理一样,只不过是用javascript实现。而且最近新出了一个这个库,相当好用。优点同Lua方案的优点打包时不用将解释器也编译进去,iOS自带JavaScript的解释器,只不过要从iOS7.0以后才支持。缺点同Lua方案的缺点总结在对app打补丁的方案中,目前我更倾向于使用JSPatch的方案,在能够完成Lua做到的所有事情的同时,还不用编一个JS解释器进去,而且会javascript的人比会lua的人多,技术储备比较好做。JSON Descripted View其实这个方案的原理是这样的:使用JSON来描述一个View应该有哪些元素,以及元素的位置,以及相关的属性,比如背景色,圆角等等。然后本地有一个解释器来把JSON描述的View生成出来。这跟React-Native有点儿像,一个是JS转Native,一个是JSON转Native。但是同样有的问题就是事件处理的问题,在事件处理上,React-Native做得相对更好。因为JSON不能够描述事件逻辑,所以JSON生成的View所需要的事件处理都必须要本地事先挂好。优点能够自由生成View并动态部署缺点天猫实际使用下来,发现还是存在一定的性能问题,不够快事件需要本地事先写好,无法动态部署事件总结其实JSON描述的View比React-Native的View有个好处就在于对于这个View而言,不需要本地也有一套对应的View,它可以依据JSON的描述来自己生成。然而对于事件的处理是它的硬伤,所以JSON描述View的方案,一般比较适用于换肤,或者固定事件不同样式的View,比如贴纸。架构模式其实我们要做到动态部署,至少要满足以下需求:View和事件都要能够动态部署功能完整便于维护我更加倾向于H5和Native以JSBridge的方式连接的方案进行动态部署,在cocoapods里面也有蛮多的JSBridge了。看了一圈之后,我还是选择写了一个,来满足动态部署和后续维护的需求。关于这个JSBridge的使用中的任何问题和需求,都可以在评论区向我提出来。接下来的内容,会主要讨论以下这些问题:为什么不是React-Native或其它方案?采用什么样的架构模式才是使用JSBridge的最佳实践?为什么不是React-Native或其他方案?首先针对React-Native来做解释,前面已经分析到,React-Native有一个比较大的局限在于View需要本地提供。假设有一个页面的组件是跑马灯,如果本地没有对应的View,使用React-Native就显得很麻烦。然而同样的情况下,HTML5能够很好地实现这样的需求。这里存在一个这样的取舍在性能和动态部署View及事件之间,选择哪一个?我更加倾向于能够动态部署View和事件,至少后者是能够完成需求的,性能再好,难以完成需求其实没什么意义。然而对于HTML5的Hybrid和纯HTML5的web app之间,也存在一个相同的取舍,但是还要额外考虑一个新的问题,纯HTML5能够使用到的设备提供的功能相对有限,JSBridge能够将部分设备的功能以Native API的方式交付给页面,因此在考虑这个问题之后,选择HTML5的Hybrid方案就显得理所应当了。在诸多Hybrid方案中,除了JSBridge之外,其它的方案都显得相对过于沉重,对于动态部署来说,其实需要补充的软肋就是提供本地设备的功能,其它的反而显得较为累赘。基于JSBridge的微服务架构模式我开发了一个,基于JSBridge的微服务架构差不多是这样的:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-------------------------
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&HTML5&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&View&+&Event&Response&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-------------------------
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&JSBridge
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&------------------------------------------------------------------------------
&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&|&&&Native&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&|&&------------&&&------------&&&------------&&&------------&&&------------&&|
&&&&&&&&|&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&|
&&&&&&&&|&&|&Service1&|&&&|&Service2&|&&&|&Service3&|&&&|&Service4&|&&&|&&&&...&&&|&&|
&&&&&&&&|&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&&|&&&&&&&&&&|&&|
&&&&&&&&|&&------------&&&------------&&&------------&&&------------&&&------------&&|
&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
&&&&&&&&------------------------------------------------------------------------------解释一下这种架构背后的思想:因为H5和Native之间能够通过JSBridge进行交互,然而JSBridge的一个特征是,只能H5主动发起调用。所以理所应当地,被调用者为调用者提供服务。另外一个想要处理的问题是,希望能够通过微服务架构,来把H5和Native各自的问题域区分开。所谓区分问题域就是让H5要解决的问题和Native要解决的问题之间,交集最小。因此,我们设计时希望H5的问题域能够更加偏重业务,然后Native为H5的业务提供基础功能支持,例如API的跨域调用,传感器设备信息以及本地已经沉淀的业务模块都可以作为Native提供的服务交给H5去使用。H5的快速部署特性特别适合做重业务的事情,Native对iPhone的功能调用能力和控制能力特别适合将其封装成服务交给H5调用。所以这对Native提供的服务有两点要求:Native提供的服务不应当是强业务相关的,最好是跟业务无关,这样才能方便H5进行业务的组装如果Native一定要提供强业务相关的服务,那最好是一个完整业务,这样H5就能比较方便地调用业务模块。只要Native提供的服务符合上述两个条件,HTML5在实现业务的时候,束缚就会非常少,也非常容易管理。然后这种方案也会有一定的局限性,就是如果Native没有提供这样的服务,那还是必须得靠发版来解决。等于就是Native向HTML5提供API,这其实跟服务端向Native提供API的道理一样。但基于Native提供的服务的通用性这点来看,添加服务的需求不会特别频繁,每一个App都有属于自己的业务领域,在同一个业务领域下,其实需要Native提供的服务是有限的。然后结合JSPatch提供的动态patch的能力,这样的架构能够满足绝大部分动态部署的需求。然后随着App的不断迭代,某些HTML5的实现其实是可以逐步沉淀为Native实现的,这在一定程度上,降低了App早期的试错成本。基于动态库的微内核模式我开发了这个库来解决动态库的调用问题,其实原先的打算是拿动态库做动态部署的,不过我用@念纪 的个人App把这个功能塞进去之后,发现苹果还是能审核通过的,但是下载下来的动态库是无法加载的。报错如下:error:Error&Domain=NSCocoaErrorDomain&Code=3587&"The&bundle&“DynamicLibDemo”&couldn’t&be&loaded&because&it&is&damaged&or&missing&necessary&resources."&(dlopen_preflight(/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo):&no&suitable&image&found.&&Did&find:
&&&&&&&&/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo:&code&signature&invalid&for&'/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo'
&&&&)&UserInfo=0x&{NSLocalizedFailureReason=The&bundle&is&damaged&or&missing&necessary&resources.,&NSLocalizedRecoverySuggestion=Try&reinstalling&the&bundle.,&NSFilePath=/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo,&NSDebugDescription=dlopen_preflight(/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo):&no&suitable&image&found.&&Did&find:
&&&&&&&&/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo:&code&signature&invalid&for&'/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework/DynamicLibDemo'
&&&&,&NSBundlePath=/var/mobile/Containers/Data/Application/61D3BF00-CF8D-4157-A87C-D0/Library/DynamicLibDemo1.framework,&NSLocalizedDescription=The&bundle&“DynamicLibDemo”&couldn’t&be&loaded&because&it&is&damaged&or&missing&necessary&resources.}主要原因是因为签名无法通过。因为Distribution的App只能加载相同证书打包的framework。在in house和develop模式下,可以使用相同证书既打包App又打包framework,所以测试的时候没有问题。但是在正式的distribution下,这种做法是行不通的。所以就目前看来,基于动态库的动态部署方案是没办法做到的。总结我在文中针对业界常见的动态部署方案做了一些总结,并且提供了我自己认为的最佳解决方案以及对应的JSBridge实现。文中提到的方案我已经尽可能地做到了全面,如果还有什么我遗漏没写的,大家可以在评论区指出,我把它补上去。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量16272点击量10875点击量8664点击量8017点击量7488点击量7063点击量6588点击量6497点击量5716
&2016 Chukong Technologies,Inc.
京公网安备89金币2539枚
发布于 17:51
移动开发后台H5页面动态生成方案
移动开发后台H5页面动态生成方案
800 || this.offsetHeight>600){if(this.offsetWidth/800 > this.offsetHeight/600){this.width=800;}else{this.height=600;}}" style="max-width:800max-height:600" onclick="if(this.parentNode.tagName!='A'&&this.width>screen.width-461) window.open(this.src);" />
在移动开发中,常用到的一个功能是“分享”,也就是将Native数据抓取并呈现在H5页面中。常见的H5制作工具只能静态生成H5页面,而且商业应用需要收费(免费版会在H5页面中添加工具商家信息)。本文提供一套基于开源技术的解决方案,能够高效的动态生成H5页面。
总体来讲,本解决方案采用Html5, CSS, Javascript等Web技术生成H5模板,使用Jsoup库来解析和处理H5标签元素,使用Java socket技术实现客户端(数据产生)和服务端(页面解析和生成)的数据交互。如果生成的H5页面自动部署到Web服务器环境下,就可以远程通过浏览器来访问。
本技术方案的主要优点是:
数据解析速度快:Jsoup可以快速的访问和修改H5元素,自定义H5减少外部依赖,页面内容解析和渲染速度快。架构灵活:采用开源工具(Jsoup, fastjson)和通用socket技术,保持模块化,且高度灵活,方便定制。2. 技术简介:
& &(1)Jsoup是一个Java库,它提供了快捷提取和操作网页数据的API。
&& & & & 首先从官网下载jsoup.jar包,并配置项目依赖的库路径后。
&& & & & 代码中解析html页面的语法要点包括:
解析html文档,获取document对象:Document doc = Jsoup.parse(html); 调用 Document类的getElementById()方法来访问元素, html()方法来生成新文档 调用Element类的attr()方法来修改元素属性, text()方面来修改其值。 & &(2)CS架构:即客户端服务器架构,它是将系统分解成两个相对独立的模块,相互间通过某种通信方式来交互。
&& & & & & Socket进程间通信是常用的一种通信方式。
3. 详细方案:
& &本文基于一个移动社交APP的真实案例。 在移动应用中,分享是一个很常见的功能。下图为UI设计原型图,描述了某一App的“约会”详情界面,包括约会创建者的个人信息,该约会的 & &描述信息,以及当前已经报名的人数等信息。
&
800 || this.offsetHeight>600){if(this.offsetWidth/800 > this.offsetHeight/600){this.width=800;}else{this.height=600;}}" style="max-width:800max-height:600" title="点击查看原图" onclick="if(this.parentNode.tagName!='A') window.open('/attachment/1508/thread/69_10_c093abc2da5f46a.png');" width="434" height="600" />
&系统需求是:当用户点击“分享”时,系统需要动态创建H5页面,以供浏览器环境下查看。 显然随着报名约会人数的变化,要求生成的H5页面内容会有所不同。常见的H5页面生成工具无法满足需求。接下来本文将详细讲解如何利用多种技术,动态生成H5页面。
第一步:使用Html, CSS以及Javascript技术,创建需要分享的H5页面模板。
H5页面模板一般包括html文件,CSS文件,以及需要用到的图片等资源文件。 对于移动开发,考虑到性能问题,在满足需求的前提下,尽量减少使用第三方css和js库。 为了便于修改网页元素,推荐使用div等标签组织和管理页面内容。
本部分实现可以看见附件源码,不做重点介绍。
第二步:客户端将实时数据转换为JSON字符串,发送至服务端。 下面的代码实现该功能。其中参数page保存H5页面用到的实时数据。 经过服务端处理后,如果成功将返回新生成的H5页面的路径,并存储于map对象中,供客户端使用。
private static boolean implementRequest(H5Page page, Map&String, Object& map){
String data = JSON.toJSONString(page);
String sharePage = H5ServiceAPI.sendRequest(data);
if(sharePage == null || sharePage.isEmpty()){
map.put(&sharePage&, sharePage);
public class H5ServiceAPI {
public static String sendRequest(String data){
String retStr =
H5Utils.h5Trace(&Client startup...&);
Socket socket =
socket = new Socket(H5Config.H5_SERVER_IP_ADDR, H5Config.H5_SERVER_PORT);
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(data);
retStr = input.readUTF();
H5Utils.h5Trace(&respons from server: & + retStr);
out.close();
input.close();
} catch (Exception e) {
H5Utils.h5Trace(&exception:& + e.getMessage());
} finally {
if (socket != null) {
socket.close();
} catch (IOException e) {
H5Utils.h5Trace(&excetpion in finally:& + e.getMessage());
return retS
} 第三步:服务端使用Jsoup库读取H5模板页面元素,并根据客户端请求的实时数据,修改H5模板元素值或者属性,并将修改后的内容保存在新页面中。处理完成后,将新页面的地址返回至客户端。 服务端类定义: public class H5Server {
private ServerSocket serverS
public static void main(String[] args) {
H5Utils.h5Trace(&h5 server start to launch... \n&);
H5Server server = new H5Server();
server.init();
public void init() {
serverSocket = new
ServerSocket(H5Config.H5_SERVER_PORT);
while (true) {
Socket client = serverSocket.accept();
new HandlerThread(client);
} catch (Exception e) {
H5Utils.h5Trace(&server exception:& +
e.getMessage());
private class HandlerThread implements Runnable {
public HandlerThread(Socket client) {
new Thread(this).start();
public void run() {
DataInputStream input = new
DataInputStream(socket.getInputStream());
String clientInputStr = input.readUTF();
H5Utils.h5Trace(&client data:& + clientInputStr);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String respond = handleRequest(clientInputStr);
H5Utils.h5Trace(&respond: & + respond);
out.writeUTF(respond);
out.close();
input.close();
} catch (Exception e) {
H5Utils.h5Trace(&server run exception: & + e.getMessage());
} finally {
if (socket != null) {
socket.close();
} catch (Exception e) {
H5Utils.h5Trace(&finally:& + e.getMessage());
} 具体的数据处理:
& & &首先检查H5页面操作类型,如果是新建页面,则直接调用H5Creator.createPage()生成页面;如果是更新页面操作,需要先删除原有H5页面。 private static String handleRequest(String request) throws Exception {
String ret = &&;
if(request == null || request.isEmpty()){
H5Utils.h5Trace(&start json parse \n&);
H5Page page = JSON.parseObject(request, H5Page.class);
int action = page.getAction();
if(action == 1){
// create new
H5Utils.h5Trace(&create new page \n&);
}else if (action == 2){
// update. first delete
H5Utils.h5Trace(&update page \n&);
String sharePage = page.getSharePage();
H5Utils.h5Trace(&current share page:& + sharePage);
if(sharePage != null && sharePage.isEmpty() == false){
String fileServerPath = sharePage.replaceFirst(H5Config.fileServerUrl, &&);
String absFilePath = H5Config.targetFileServerPath + fileServerP
H5Utils.deleteFileIfExist(absFilePath);
H5Utils.h5Trace(&deleted file:& + absFilePath);
ret = H5Creator.createPage(page);
} H5Creator类负责: &o 根据H5Page内容,结合H5页面模板,生成新H5页面。
&&o 生成新页面的文件名称
&&o 创建文件并保存新H5页面内容
public class H5Creator {
public static String createPage(H5Page page) throws Exception {
String content = page.generateH5Content();
System.out.println(&generated content:& + content);
String nameWithDate = H5Utils.getFileNameWithDate(page.getId(),
page.getPersonJoinedNum());
System.out.println(&nameWithDate:& + nameWithDate);
String filePath = H5Utils.getFilePath(nameWithDate);
System.out.println(&filePath:& + filePath);
boolean result = H5Utils.savePage(filePath, content);
if (result) {
String h5Path = H5Config.fileServerUrl + nameWithD
return h5P
其中,page.generateH5Content()是核心方法,通过调用Jsoup类来解析H5页面元素,并修改其内容,以实现动态页面生成。
public String parseH5Content(String h5) {
Document doc = Jsoup.parse(h5);
e = doc.getElementById(avatarId);
e.attr(&src&, (CheckStr(page.getAvatar())));
e = doc.getElementById(nickNameId);
e.text(CheckStr(page.getNickName()));
e = doc.getElementById(descId);
e.text(CheckStr(page.getDesc()));
return doc.html();
}
4. 优化和注意事项
效率是移动开发尤其注意的一个方面。
客户端生成H5页面时,我们可以结合H5页面名称和当前的实时数据,来判断H5页面是否需要最新。
比如在生成的H5页面名称中,包含报名的人数信息,如果判断报名人数没有变化,则没有必要重新生成H5页面。
5. 效果展示
下图为动态生成的H5页面(分别为4人报名和5人报名时的约会数据),除了显示App页面数据,也包括了“报名”按钮,其链接了该App的下载地址。
&800 || this.offsetHeight>600){if(this.offsetWidth/800 > this.offsetHeight/600){this.width=800;}else{this.height=600;}}" style="max-width:800max-height:600" title="点击查看原图" onclick="if(this.parentNode.tagName!='A') window.open('/attachment/1508/thread/69_10_e7dcae1b4692bbd.png');" width="416" height="600" />
当报名的人数有变化时,新的H5页面会被生成。因此我们看到的都是最新数据,即H5页面反应了Native应用的最新状态。
800 || this.offsetHeight>600){if(this.offsetWidth/800 > this.offsetHeight/600){this.width=800;}else{this.height=600;}}" style="max-width:800max-height:600" title="点击查看原图" onclick="if(this.parentNode.tagName!='A') window.open('/attachment/1508/thread/69_10_a3cea9c5281cda0.png');" width="401" height="600" />
6. 源码说明
第一:文件说明。附件中包含代码及资源等3个文件夹。(1)H5 Client工程代码: 该部分可以被集成于App的后台服务器代码中,作为一个模块被调用。本文为了方便读者,将之放置在单独的工程中,并填充了一些测试数据,将之作为一个单独的应用来运行。类介绍:H5ServerAPI类:Socket的客户端,发送请求数据。H5Page:页面元素model类H5PageManager:H5客户端对外提供服务的接口。H5使用者调用该类提供的API来使用H5模块。H5Config:定义参数常量,包括服务器地址,Socket端口号,H5文件的命名规则。H5Utils:主要是文件名称解析,日期格式转换等操作。代码编译后export为jar包(如命名为h5client.jar),并运行。命令如下:java -jar h5client.jar(2)H5 Server工程代码类介绍:H5Server类:Socket的服务端,接受客户端请求数据,处理后返回生成的H5页面地址。H5Page:页面元素model类IParser:页面解析接口TemplateParser:自定义的解析器,如果不使用Jsoup,而是自己解析时使用。AdvancedParser:基于Jsoup的H5页面元素解析生成器。H5Config:定义参数常量,包括Socket端口号,H5原模板和资源文件位置,生成的H5存放物理路径及网友访问路径,H5文件的命名规则。H5Utils:主要是文件的读取存储,删除等操作。代码编译后export为jar包(如命名为h5server.jar),并运行。命令如下:java -jar h5server.jar(3)模板及资源文件附件中h5文件夹中包括:resources:保存的是图片资源文件和css文件。templates:保存的是作为模板的html文件。
第二:配置说明(1)模板以及资源文件配置路径:在H5Server工程下的H5Config文件,定义了h5OriginPath,来配置模板以及资源文件位置。同时生成的H5页面也位于该目录下。 注意:缺省设置的目录是 &/Users/billli/Desktop/h5test/“(该路径适用于Mac环境,请根据自己的环境,设置适合自己系统的路径,例如在Linux系统下,设置为 &/data/appAppTemp/h5/&);应用运行生成的H5页面将位于此路径下。 (2)服务端IP地址的设置。 在H5Client工程下的H5Config文件,定义了H5_SERVER_IP_ADDR来配置实际的服务端地址。(3)Web服务器域名配置: 在H5Server工程下的H5Config文件,定义了ipAddress。其代表生成的H5文件所在的Web地址。 另外,为了在浏览器中可以访问文件,Web服务器配置需要将h5OriginPath设置为虚拟根路径。诸如在Tomcat配置文件中设置: &Context debug=&0& docBase=&/data/appAppTemp& path=&/files&/&总结运行代码的步骤:(1)根据H5Server工程下的H5Config文件中定义的h5OriginPath,创建路径,并将附件中h5下的所有内容复制到该目录下。(2)根据实际服务器地址,修改H5Client工程下的H5Config文件中定义的H5_SERVER_IP_ADDR的值。目前测试是客户端和服务端在同一机器,因此设置为127.0.0.1(3)启动服务器:java -jar h5server.jar(4)运行客户端:java -jar h5client.jar,在h5OriginPath下将会生成一个基于时间的新目录,其下保存新生成的H5页面。
7. 版权说明
本源代码由“极分享”社区创建,添加或者修改,我们会持续优化源代码以提供更好的解决方案,更多详情和支持请前往。
&&&&&&&&附件名称/大小
打赏金额¥:
选择支付方式:
微信扫码支付
打赏金额¥
您需要登录后才可以回帖
最热文章墙
Powered by Created by

我要回帖

更多关于 希望之地 的文章

 

随机推荐