Tag Archives: shenjs

Java 栈上的 JavaScript

注:以上视频在 youtube 上,你懂得该怎么做。

这是我在 ShenJS 2015 上面所做的一个 lighting talk,当时的题目叫做 Enterprise JavaScript。

其实那天准备了很多演示和代码片段,无奈时间太短,只把 slides 简单过了一下就没有时间了,于是在这里做一个完整的介绍。

Enterprise JavaScript 是一个非常大的话题,会涉及到跟各种 Java 中间件的互操作问题,这里仅就如何在一个完整的 Java 栈上面以 JavaScript 作为首要编程语言来提高 Java 系统的开发效率展开讨论。

作为一门常年把持 TIOBE 排行榜冠军的静态编译类语言,Java 固然有数不胜数的优点,以至于其在企业级应用开发领域拥有无可替代的地位。但是,相信每一个 Java 开发人员都会在日常工作中忍受其种种弊端带来的烦恼,其中最令人发指的也正是其静态编译类的特性。静态类型在减少开发人员出错可能性的同时降低了语言的动态扩展能力;而编译执行除了能保证代码的编译期校验以外,更多的就只剩下无尽的等待。尽管现在大多数的工具链和集成开发环境都可以做到增量编译,但是增量编译后可执行代码的热部署能力却是差强人意。尽管有一些商业的开源的解决方案,但总归不是天生特性,使用很不方便。

其实针对 Java 缺陷的改良,社区始终也没有停止过尝试。著名的成果包括 ScalaGroovyJythonJRuby 以及我们今天要讨论的 JavaScript。社区通常都有这么一个共识:Java 虚拟机是个好东西,但 Java 语言本身不一定。因此改良的重点全部集中在语言层面,通过引入具有不同特性的新语言,经过编译器或解析器翻译成 Java 字节码,再交给虚拟机来运行。

另一方面,JavaScript 近两年人气爆棚,有逐渐发展成为全栈开发语言的趋势。尽管在 Node 平台上使用 JavaScript 开发后端应用早已是习以为常的事情,但是在 Java 平台上,这件事情就显得不那么容易了。说到在 Java 开发栈上运行 JavaScript 就不能不提大名鼎鼎的 Rhino。这是早在 1997 年就已经出现的 JavaScript 引擎,并完全由 Java 代码编写而成。后来被 JDK 1.6 收纳为官方默认的 JavaScript 引擎。这也就意味着在整个 Java 发展历史中,都是一直可以支持运行 JavaScript 的。不过由于大环境(在 Java 平台上面跑 JavaScript 毕竟接受度不高)以及 Java 虚拟机对动态语言支持能力欠缺等问题,使得这件事情并没有流行起来。

另外一个导致 Rhino 不够流行的原因,就是对其性能的诟病。在早期的时候 Rhino 是将 JavaScript 代码直接编译为 Java Class,运行期性能非常出色,往往可以击败很多用 C 实现的基于 JIT 技术的引擎。不过生成 Java 二进制代码和装载这些生成的类是个非常重量级的操作,需要耗费大量时间,而且编译过程产生的许多无用中间类和字符串无法被虚拟机垃圾回收掉。不过后来引入了解析模式以后这些问题就得到了解决。一些 性能 测试 报告 显示出 Rhino 的性能依旧非常良好。

后来 Java 官方也意识到虚拟机对动态语言欠缺支持以后,就从 JDK 1.7 开始引入了 invokedynamic 的技术,可以有效提升动态语言的运行性能,而且 Oracle 也在 JDK 1.8 中自带了一个基于此技术实现的新一代的 JavaScript 引擎 Nashorn,终于让性能不再是什么大问题了。

javascript-in-jvm-2

针对在不同版本的 JDK 上运行 JavaScript,可以有不同的解决方案(如上图)。如果是在老版本的 1.6 上面,只能使用 Rhino,以及在 Rhino 之上封装的开发框架 Ringo,这个组合里面没有对 invokedynamic 的支持。当然由于向后兼容性的存在,其实这个解决方案是可以适用于后续 1.7 和 1.8 版本的。如果是在 1.7 版本上面尝试使用 JavaScript,那么可以考虑 DynJS 引擎,这是另外一个独立的 JavaScript 引擎实现,支持了 invokedynamic 技术,与此配套的还有一个 Nodyn 项目,是对 Node 的一个移植。不过很可惜,这套开发栈没等流行起来,就被后来的技术给超越了,因此除非你必须要坚守在 1.7 上面,否则并不建议采用。最后,也是这个话题的终极解决方案,就自然是升级到 JDK 1.8 并使用官方的 Nashorn 引擎,与其对应的框架可以选用 Vert.x。Vert.x 是由 Eclipse 开发的,实现了良好的事件驱动和异步非阻塞机制,这些都是 Ringo 所没有的。再有 Vert.x 还是 reactive 的。不过 Oracle 官方有一个基于 Nashorn 引擎的 Node 实现,叫做 avatar.js,不过已经有一段时间没有更新过了。

下面展示一些使用 JavaScript 开发 Java 应用的示例。

注:在尝试运行这些样例代码之前,请确认已经正确安装了 JDK 1.8u51 或以上版本、Vert.x 3.x 和 Maven 3.x。

一、操作 ArrayList

arraylist

二、Filter and Reduce

filter-and-reduce

三、Web 服务

webserver

四、Spring、Stick 和 Hibernate(SSH)

这是一个比较复杂的例子,首先项目使用 Maven 来管理,并通过 jetty-maven-plugin 来运行。项目内部使用 Spring 作为整个集成的核心,用 Hibernate 来实现数据访问。Stick 是基于 Ringo 的一个组件,实现了类似 express 一样的功能。下面的这段代码,主要演示了如何通过 JavaScript 实现一个 router,并在 router 内部调用 Spring 和 Hibernate 的 API 实现数据查询,并返回 JSON 结果。此项目的完整源代码请在 Github 上获取(这里面还包含了会上的演示文稿,所有的样例都在 demo 目录下)。

运行该项目前,需要首先安装一个 MySQL 数据库,并运行在默认的 3306 端口,root 用户的口令为 mysecretpassword。创建一个名为 ringo-ssh 的数据库,字符集为 UTF-8。然后使用如下的 SQL 语句创建一个数据库表 T_TASK,并插入一些数据:

另外,该项目依赖了我们公司的两个开源项目,分别是 origincdeio-runtime。请从 Github 上 clone 下来以后,进入项目目录,运行 mvn clean install 来编译和安装。注意执行的顺序为先 origin 再 cdeio-runtime。

最后,可以通过运行 mvn jetty:run 命令来启动这个示例。

注:如果是第一次运行该示例,Maven 会下载很多依赖包,这个过程根据网速快慢会长短不一,请耐心等待。

以下是系统运行后的控制台截图和 curl 的返回结果。

ringo-ssh-maven

ringo-ssh-curl

总之,在 Java 平台上使用 JavaScript 作为首要开发语言是完全可行的,在上面这个示例中,除了 Hibernate 必须的领域实体等是使用 Java 来编写的之外,其他的大部分逻辑都是可以用 JavaScript 完成的,而且可以跟各种 Java 中间件完美集成。有关这方面的深入介绍远不止一篇博客所能言尽,有兴趣了解更多的可以参考我公司的 CDEIO 平台。

ShenJS 2015 那些年我们一起追过的盛典

这还是我第一次听说过有追会的,当我第一天来到 ShenJS 的现场。

深圳的天气一如既往的好,也一如既往的热。

对 JSConf 其实早有耳闻,放眼全世界都算是最顶尖 JS 开发者的盛会。JSConf CN 三年前悄然兴起,我就在望眼欲穿的盼。沪——京——杭——终于,就跟 Linkin Park 要光临深圳开演唱会一样,我听说了传说中的 ShenJS。

虽然在经济上总跟“北上广”齐名,但是在技术峰会方面,深圳永远无法望“京沪”项背。或许是我所接触的行业不同,国内的互联网圈子或许会更活跃,更喜欢组织活动,进行分享。可惜我们是搞企业信息系统集成的——对,就是那些成天面对需求变更,被外行指导软件开发,永远延期,没有最烂只有更烂的项目外包企业——在这里,Oracle 是我们的天空,Java 是我们的空气,Apache 是我们的信仰。

这似乎跟 JS 没有太大关系,除了我个人的 JS 情节。

从我接触 JS 的那天起就被她吸引了,虽然当时根本不知道那是一种什么样的语言。那个时候 Web 开发很纯净,纯净到只有 IE 6,Firefox 还是 1.0,Chrome 还没有出生,什么 jQuery 还不流行,prototype.js 在争议与无奈中被一遍又一遍的使用,Crockford 刚刚发明 JSON,即时函数调用还在他脑子里,至于 Node.JS 嘛——孩子,你说的是用来处理 DOM 的函数库吗?就这样在懵懂中我完成了职业生涯的第一个像模像样的项目,整个前端重度依赖 JavaScript。也是那个时候才知道,原来一种语言可以有那么多种风格截然不同的写法,浏览器原来有那么大的差异,IE 6 原来是那么的慢。或许正是这次项目的成功让我对 JS 产生了好感和依赖。“任何能够碰巧用 JS 编写的程序最后就一定会被用 JS 编写”,这个碰巧在我这里成为了必然。

转眼间十年已逝,Java 和 JavaScript 都迎来了 20 周年的庆典,我走入了 ShenJS 的会场。

一进门就被热烈气愤所惊骇:这是技术人员的聚会吗?程序猿会有那么嗨吗?竟然还有人是从外地专门赶来的?有人遭遇台风到不了的?竟然有神人参加过全部四届的 JSConf 大会?Oh my god,这是我想要的感觉,外加舞台上还有个这么逗逼的主持人,Oh yeah,程序猿的高潮瞬间就一泻千里了。

JSConf 无愧为国内最高水平的 JS 会议,总共邀请了来自 11 个国家和地区的 21 位讲师,为大家奉上两天不间断的饕餮盛宴。先来看看菜单吧:

JS中国开发者大会   ShenJS

主持人 Goddy Zhao 必须要提一下,他的开场和串场也真是醉了,还让单身狗明白,“找不到对象”的原因是因为写了太多的空指针。

言归正传,这毕竟还是一次技术的交流会议,总得有点干货吧。

一、React + Flux

这个一点都不稀奇,这半年除了 ES6,估计就属 React 最风光无限了。Web 开发就是这样,为了解决 DOM 性能瓶颈,八仙过海,各显神通。不过 Facebook 给出的解决方案还是让社区为之一振。Virtual DOM(就是在内存中构建一棵虚拟的 DOM 树,在界面需要更新的时候,先在内存中做一次 diff,只将发生变更了的 DOM 节点应用到界面上)的引入让社区瞬间沸腾(Herman 说 React 在阿里很火),看上去多此一举的计算,却能显著提高渲染的性能。在符合要求的前提下,两棵 DOM 树的 diff 复杂度能控制在 O(n) 水平,充分体现了 Facebook “牛逼闪闪”的技术实力。就连不怎么好看的 JSX 也逐渐被爱屋及乌了,况且 React 的组件特性还能顺带解决 CSS 的一些固有问题

Flux 更是简单得一塌糊涂,简单到竟然不一定需要第三方类库来实现(当然还是会有的)。比起 MVC 和 MVVM 这样的重量级框架,React + Flux 就可以解决从数据流动到界面渲染的全套 UI 过程,而且强制要求的单项数据流,也使得架构设计变得简单许多。

因为 Virtual DOM 需要先期做一次 diff,那么很明显的性能瓶颈就有可能会出现在这个地方。Facebook 何许人也,immutable.js 就好像是 React 的孪生姐妹一样,早就在那里等待大家的临幸了。这次会议上听说的唯一一个新概念就是 Persistence Data Structure,其实也可以完美的和 React 集成来实现更多炫酷的能力。我之所以对这个概念非常感冒是因为在曾经的一个项目中,客户就要求实现这样一个需求:可以将组织机构变更的历史记录下来,并随时可以回滚。这正是 PDS 的应用场景呀,当时我懂得少,把这需求给搪塞回去了。

Web 开发还经常前前后后的变化。曾经的服务器比终端性能好,大部分计算在服务器上完成,以实现所谓的瘦客户端;后来终端性能提升了,为了释放服务器的计算能力,降低网络传输负载,将一部分的运算(尤其是界面渲染)转交给终端,以实现所谓的富客户端(或者那个时候的流行词 Web 2.0);现在 React 的来临再一次提出服务器端渲染的能力,而且 isomorphic/universal 的类库还使得前后端的代码一致而通用。

不过 React + Flux 也不是完全没有问题。Flux 官方对异常处理没有一个明确的方案指引,Yahoo Fluxible 的实现也通篇没提到过关于异常数据该如何流动的问题,这些还需要时间和更多的社区实践来总结跟积累了。测试方面,Jest 的性能是个严重的问题,coding.net 的同学们在单元测试的选型中就遭遇了这个问题,最终投向 Karma 的怀抱。另外我觉得 Jest 的侵入性太强,不如 Karma 有那么好的框架整合能力,对于混合使用各种技术的单元测试应该不是个明智之选。

二、异步流程控制

这个话题应该是 JS 社区永远无法停止的。JS 异步单线程的特性,刺激了各种最强大脑对于此问题的思考。就目前状况来看,解决方案无疑有如下几种:

1、Promise:ES6 先天支持的特性,ES5 也有各种第三方库可以使用,算是最容易获得的解决方案。
2、co + generator:这是最接近 ES7 async/await 写法的解决方案,需要 JS 运行时支持 ES6 的 generator 特性,或通过 Babel 等转译。
3、thunks:这是在严老师的《Koa 和 Toa 的框架原理及开发实践》课程中提到过的一种解决方案,能够友好的支持 promise,generator 和回调等各种异步返回方式。
4、async/await:这个应该算是异步流程控制的终极解决方案了,可惜是 ES7 中才会出现的特性,但是依靠 Babel 尝尝鲜是不成问题的,但谁能保证最终的规范不会发生变化呢?

当然,重要的事情最后再说,庄恒飞同学给出的 fibjs 是以消灭这个问题的思路去解决问题的,有兴趣的大大们可以多多关注。

三、架构实战

说实在,因为不从事互联网这种高并发、重架构的日常工作,所以对其中的一些设计没有太多感觉。而且因为没有真正遇到过问题,对其解决方案的精妙之处也就无从感知了。只是在演示中看到各种性能的提升。外行就不在这里评论了,免得被笑掉大牙。

四、炫酷演示

我把 90 后(尼玛,那么年轻)沈毅同学的 ECharts 课程放到炫酷演示里面应该毫不为过,顺便也刺激一下身为东道主的企鹅公司,就算不开 session,也好歹赞助几个公仔吧。百度在前端领域为社区做出的贡献是有目共睹的,我们公司在日常开发中使用的唯一一个国产开源产品就是百度 FEX 团队出品的 F.I.S。当然这个课程并不是纯粹的演示,还是深入介绍了一些难点问题的解决思路和实现原理,本人对 canvas 及相关内容不甚熟悉,也不妄加评论了。

真正的炫酷演示还是来自于三个老外。感觉国内大牛们分享的大多是跟工作有关的内容,或者或多或少会在工作中碰到或用到的;而国外的牛牛们似乎更偏重娱乐与兴趣,不知是环境使然还是文化使然。

三个炫酷演示都是跟硬件有关,也再一次证明了 JS 作为全栈语言的强大实力。曾几何时,硬件的开发都永远是阳春白雪,束之高阁的。什么汇编还有 C,都不是普通码农所能靠近的。然而 JS 正在悄悄的改变着这一切。Arduino 作为标准的开源硬件,JS 作为使用最广泛使用的编程语言,他们的结合剩下的就是想象力的无限放飞。使用 Johnny Five 就可以通过电脑连接 Arduino 而实现用 JS 控制硬件的能力,Andrew 的 Nodebot 就是这么一个原理。Tim 的 NERD DISCO 更是使用了浏览器的 Web Audio API,在浏览器上实现了声音可视化的效果。其实技术都不是问题,音乐 + 灯光 + DJ 调音器,呈献给现场的就是一段炫爆了的电子 DISCO 秀,真是”不会写 JS 的 DJ 不是好讲师呀”。

有了声音自然还要有图像,平面的图像电影院都不怎么放了,3D 的东西也见太多了,VR 是近些年红的发紫的新鲜事物,ShenJS 也真是给力,Martin 关于 WebGL 和 WebVR 的介绍也算是让我们这些无法接触到像 Google Cardboard 这类玩意儿的天朝子民能开开眼界。而且他现场演示使用的 IDE 真是与众不同,实时写代码,还能及时看效果,关键是现场写程序调 3D 图形建模,可见功底之扎实呀,曾几何时,我们学过的这些知识都还给大学老师了。

Martias 的 p2p pipes 现场写代码,佩服佩服,讲什么都不重要了,但是老外们的 JS 都不写分号的吗?

五、其他

剩下的这些就不知道怎么分类了。

PM2 和 Keymatrix.io 的介绍,说实在的下午第一节,我基本上半睡半醒,只知道功能确实强大,还给出了 ShenJS2015 一个七折的优惠码。当然最令人兴奋的还是作为讲师的 Alexandre 竟然是 PM2 的作者,“敬仰犹如滔滔江水连绵不绝,又如黄河泛滥一发不可收拾”。

509.pic

Hax 的 JavaScript: The World’s Best Programming Language,我不得不先上图了,因为群里已经有人将此作为表情了。我在这里想评论的一点就是,这明显是一群 JSer 在一起意淫的结果嘛,但是那又怎样,JavaScript 专治各种不服。

Lighting Talk 是个有意思的环节,每个程序猿都有分享的意愿,这里就能满足你“好为人师”的心理。两天的小讲座内容着实不少:有介绍安全漏洞的,有介绍自己小产品的,有诉说开发经验的等等,太多了没都记下来。让我印象深刻的是华大基因的介绍,因为以前在 Amazon Awsome Day 的活动中,华大基因对 AWS 的应用也是作为典型案例被介绍的(这算广告吗,能给点赞助费吗)。当然还有我自己分享的关于 Enterprise JavaScript 的内容,可惜时间太短了,又是个大话题,准备的一些 Demo 都没来得及演示。后面抽空写个博客详细展开一下。

最后的最后,以 Herman 老师的课程作为结束吧,虽然全篇没太注意他在讲什么,但就是觉得印象深刻。Herman 老师的前端开发摩尔定律更是令人俯首称臣呀:每 18 到 24 个月,前端开发的难度就会增加一倍!干!

因为住的地方离南山比较远,所以两天的 Afterparty 都没有参加,尤其是 Nodebot 的分组对抗,尤其遗憾。后面又听群里说周日的派对上面很多人聊得非常投机,也没有机会参与。这是算是我第一次参加这种规模的技术峰会,收益颇深。难怪会有这么多忠实粉丝不远万里、不怕险阻、不惧台风、不辞艰辛的来执着追随着这个会议。或许所有 JSer 的内心都跟 JS 本身一样无比复杂,又无比单纯。回归生活我们是被人揶揄的程序猿,在这里我们是崇尚自由的乐天派。不论下一届的 JSConf 开在哪里,相信永远会是“那些年我们一起追过的盛典”。

版权所有,欢迎转载!