背景
在项目实施的过程中,经常需要调用一些本地程序(DLL,EXE或OCX),常用的方法就是将本地程序封装成OCX插件,在本地电脑安装注册,然后使用JavaScript进行调用,然而这种方案主要存在几个问题:
- 本地程序质量参差不齐,频繁的无响应或者崩溃导致浏览器卡死或崩溃,极大的降低了用户的体验
- 高版本的Chrome和FireFox已经不再支持插件,为保证插件的调用只能固定浏览器版本
- 丧失了BS技术产品集中部署,随处运行,工程实施以及产品更新更加方便的优势
- 对于不同的本地程序,均需要封装为OCX插件,对于Java程序员来说略显为难,更不用说封装过程中容易出现的内存泄露问题
问题分析
为解决浏览器调用本地程序过程耦合过于紧密的问题,需要提供一个解决方案替代之前调用插件的方式,改进要求大致有三点:
- 本地程序无论是无响应或者卡死崩溃,不能影响浏览器的正常运行
- 不能使用高版本浏览器已经弃用的OCX插件
- 不需要对本地程序做二次封装注册,能够做到拿来就用最好
综合起来看,第一点是迫切需要改善的,用户直接使用的对象是我们系统,因为一个操作点导致用户浏览器频繁的崩溃,然后重新登录,很容易引起用户的反感,而且这是个扯皮的事情,涉及到其他厂商,想找到问题也比较复杂。
技术思考
为了降低耦合度,考虑是在客户端电脑安装一个中间层程序,浏览器通过中间层程序调用本地程序。客户端电脑的中间层程序作为http服务运行,浏览器通过http请求的方式调用中间层程序,中间层程序根据http请求参数来确定需要调用的本地程序,动态调用后返回结果给浏览器。
浏览器和本地程序之间增加一个http的中间层,有以下优点:
- 全版本浏览器支持,不用考虑浏览器差异
- http可以设置同步请求或者异步请求,可以根据场景来设置不同的请求类型
- http可以设置超时时间,如果本地程序迟迟没有返回,超过时间可以认为此次调用失败
- 浏览器和厂商插件程序彻底解耦,只需要保证中间层程序的可用性,就完全抛开外部程序的制约,恢复了BS程序应有的优势
存在问题
中间层程序运行模式
1、中间层程序在客户端电脑作为Windows services服务运行,这样的话可以利用windows的功能设置开机自启动,错误重启等,方便管理,能够保证中间层程序的高可用。然而之后发现在调用有界面的插件时存在session0隔离的问题,虽然有办法能够绕过session0的隔离,但是有些windows的环境变量会出现问题。
2、中间层程序作为开机自启动的后台程序运行,开机启动的后台程序不存在session0隔离的问题,但是无法使用windows服务的开机自启动,错误重启等,中间层程序的可用性需要自己来保证。
中间层程序的可用性保障
1、中间层程序设置为开机自启动
2、客户端电脑增加一个守护进程程序,对中间层程序进行心跳检测,定时检查中间层程序有没有开启
3、浏览器调用中间层程序失败,触发守护进程启动中间层程序
总结
通过以上方案主要是实现了本地程序和浏览器解耦,可以实现一个统一的技术方案兼容多种情况的需求,而且能够充分利用中间层进行windows API的调用,实现本地文件的安全可控读写及上传下载。
然而这种方案还是存在缺陷,因为此方案的目标是浏览器和本地程序的解耦,对于需要嵌入浏览器并且需要进行界面操作的本地程序就无法友好的实现,通过中间层只能调起程序,而无法嵌入浏览器。
虽然本文中的这种方案,可以实现浏览器和本地程序的动态调用,但是如果可能的话,尽量不要使用,将数据的交互方式更改为http、webservice等技术方案更为妥当,毕竟随着技术的发展,类似插件的本地程序都将会被淘汰掉,云服务模式才是未来。
本文思路的实现方案:WebRunLocal中间层程序