原文出处: WildFly
受到好文《Web开发的发展史》(英文)激发的灵感,写下我对web开发技术的认识。
1. 静态页面时代
大学时候,上机还得换卡穿拖鞋,Novell的网络是很神奇的,然而更神奇的是通讯原理老师半神秘的讲他上 Internet,“Cernet(教育网)有条64K的出口,半年前还很快,现在已经比较卡了”。就这样,我们用Netscape指向Yahoo。那是一个HTML加图片的世界,充斥着各种花哨闪耀的字体和鞠躬的小人,蓝色连接点击后会奇幻的变色。
我们开始用不熟练的HTML和简陋的设计来设计网页,并且知道这边有个浏览器,那边有个叫WebServer的东西,但管理Sun工作站的机房老师总是盯的很紧,不会让你动系统半分。听说有个叫Linux的神奇东西,好吧我想尝试,可是我只有一台攒的电脑,以及若干张5寸3寸的软盘。我至今感谢一位师兄,他帮我下载并切分了一个版本的Mandrake,就这样室友看到非常奇怪的一幕,我奔波在机房宿舍之间,仔细计算容量来拷贝,就这样在假期里我第一次搭建了Apache。
2. CGI时代
很快页面上流行一个叫做计数器的东西,免费的收费的建站网站都把它当作卖点,“立体超炫变色时尚计数器”,很快我们看到几乎每个页面都有了一个点击量在88888的酷装置,只是无论怎么点都不会变化。而校园里张贴着令人眼红的广告,“征人写CGI程序,一支500元!“。
慢慢的,知道了CGI是利用进程间输入输出通信,和WebServer进行通信,从而可以写程序来控制页面输出的内容。但在当时会给硬盘分区就在中关村被看成电脑高手的年代,实在是会者寥寥。即便到了今天,我依然对Perl敬而远之。一些前辈用C写出更高级的CGI应用,比如WebMail,挖到第一桶金,成为今天互联网的先驱。
3. PHP露出锋芒
说实话,我认为PHP是最受益于互联网浪潮的语言,在合适的时间和好伙伴Mysql一起出现。利用Apache的模块mod-php,将php作为web服务器的一部分运行,效率和维护性都达到很好的提升。脚本语言成为互联网前端开发主力一直到今天。PHP和大哥Perl,以及兄弟Python,Ruby一起盘据在编程语言排行榜5-10名位置。
同样的Mysql也是时代的娇子,它快速灵活易用成为网站数据库的首选,但很长时间里,Mysql被其他数据库诟病,别说Oracle等高富帅,即便是同为开源的Postgres社区里,也会有这样的声音,“不支持事务也叫数据库?”。没关系,开源社区很快为其加入各种引擎,如今Mysql绝对是装机总量第一的数据库。
4. J2EE
Java时代来临,一杯咖啡,一个可跳动的小精灵牵动了所有的大型软件公司。没错是所有,包括微软,Sun公司一时星光无限,所有的开发人员都在谈Java。人们对其桌面表现失望进而质疑时,J2EE及时出现了,Servlet+JSP快速成为Web开发的好用技术。能够跨平台,独立解包使用的Web服务器,挂接任意数据库的JDBC接口,一时世界变得很美好。
微软的ASP也出现了,一开始也是脚本解释,和PHP等技术类似。很快微软的C#和dotNET战略出台,ASP也升级为ASP.Net,从此dotNET和J2EE是竞争者,更是一对站在相同站壕的朋友,互相学习和抄袭对方的技术和设计,直到今天。
5. Web层框架百花齐放
Servlet是一个优异的Web技术规范,但面对丛多的开发需求,还是不能很好的覆盖。Struts框架很快成为主流,今天我们依然看到很多.do后缀的页面。Struts主要做了三件事,一是对请求Url进行很好的梳理,通过Command模式把请求指配到Action对象上,并可以用同期出现的Ioc框架进行注入。二是梳理出若干有用好用的Intecepter,并可以*组合构成自己的Stack。三是对页面流转流程通过xml的方式可以灵活定义。
同期,数以百计的各种框架出现了,多数都是针对Servlet的空白点,在几个方面进行代码或者配置的约定,可谓百花齐放,百家争鸣,我想Java社区能到今天依然繁荣,这种海纳百川,开放的态度是根本原因。如今很多框架已经走过生命期,但还有很多活跃的,其中Webwork即Struts2,和SpringMVC是模板技术类别最出色的。GWT,Wicket等在页面组件类表现不错,还有脱离Servlet束缚Play等框架。
6. WithoutEJB
J2EE里,除了Servlet外另一个重量级的规范就是EJB。EJB设计的来源是Corba技术,分布式对象技术在EJB规范中有完整的体现。Rod在著作中对EJB规范粗重庞大难用提出各种质疑,尤其是针对其强制分布的要求。我的观念是分布式支持没有错,现在EJB规范中对于Local和Remote的划分定义是正确的。开发人员应该一开始就需要了解接口粒度的划分,本地和远程接口是不同的。对于一般的小型应用,Servlet和EJB容器都在一个虚拟机中,本地接口是合理的,但对于大型企业应用和互联网级别应用,势必需要服务的远程划分和调用。所以早期的EJB,可以说一方面设计不完备,另一方面又过度设计。但EJB自从3以后完全脱胎换骨,成为设计良好的规范。
Spring作为开发框架,把Ioc和AOP能力发挥的淋漓尽致,在各个层次很好融合其他技术和项目库,一直是Java Web开发的主流。不过面对CDI等JavaEE规范,在注入,生命期管理,对象解耦等优势不在。我预计今后Spring, JavaEE和Osgi会在主流Java开发框架方向竞争,也会相互借鉴和融合。
7. Ajax
Javascript是浏览器正统的脚本语言,但在那个机器性能不佳的年代,一段Js代码造成鼠标没有响应的情况比比皆是。Js的给人影响就是页面上飘来飘去“点击我”对话框,页面上走马灯效果的变色通告,或者是几十层模态对话框的恶意页面,很多网吧的机器默认Js是禁用的。在很长的一段时间里,Java web开发一个潜规则就是少手写Js文件,这样可以很好的支持多种浏览器和提高效率。
谷歌火了,Ajax也成为火爆的前端技术,我们在使用gmail,google map等产品时,有了另一种体验,点击链接或按钮后,即便网络不算流畅,页面不再全白重新刷新,而是内容渐渐的出现。其原理就是利用Js脚本到后台服务器获取数据,在浏览器前端对数据进行解析和渲染,在这个过程中,大多数页面并不需要进行改变,只是更新页面中一部分即可。谷歌公司大力支持Firefox使其重生,并和苹果一起发展webkit项目,各自发展了chrome和safari浏览器,伴随者页面渲染能力大力提升同时,Js脚本的解析能力也突飞猛进。我个人认为Ajax这个技术看似简单,但却是新一代Web,所谓Web2.0的基石性质技术,为互联网泡沫后互联网的复兴和今日腾飞起到了重要作用。
8. Ruby and Rails
快速成长的互联网需要快速的web开发能力,Rails框架出现了,同时火爆的还有Ruby语言,它的出现满足了当时开发者的需要,快速开发,玩cool的东西,有完备的后端模型支持。让我们仔细分析一下Rails中MVC就能发现,Model中对实体对象的关系定义,和JavaEE的JPA很多概念一致,但利用Ruby语言的元能力,可以直接对实体对象进行功能扩展,而其时Java社区还在为贫血,充血对象争论不休。Control,View等层次也能和Java的一些框架概念一致,不过有些设计构思更巧妙,而且Rails的基因就是满足互联网开发需要,和JavaEE企业级应用有所不同。
很快的,各种语言纷纷出现模仿Rails的项目,Java的Grails, SpringROO,JBossForge,Python的Django,PHP的Symfony等等。毫无例外的,能有影响力的都是开源的,有良好社区能力建设的项目。
9. JSF和CDI
让我们回到企业应用开发,大家有没有想过所谓企业应用和互联网应用之间最大的差别是什么?我认为是用户数量级别的差异,导致前端设计方式,软件体系,后台数据库,缓存技术应用,有不同的设计理念和方式。用更技术化来说,就是会话和事务。企业应用是有强会话和事务需求的,而这两个技术词语也会一并关联存在。很简单,在一个事务中会经过多次会话过程,直到这个事务全部做完。和我们日常办事是一样的,填单子,和办事人员沟通,修改单据,盖章,各种口舌,最终感慨,办事真难。
从软件层面考虑,一个企业应用软件可能用户数并不太多,就企业中百十号人,但前后台的交互是长时间,多次会话交互的。JSF技术其实是借鉴了微软ASP.net,它们继承了传统IDE快速开发的思路,希望通过拖拽连接可以快速开发一个应用。页面上的组件,对应后台服务器的业务组件,在得到服务器请求之后,组件需要做一系列动作来完成解析,校验,模型重建,业务方法调用,页面渲染等步骤,这些必然有个较长的过程。复杂性,效率,和其他技术的融合,JSF技术从诞生起就被质疑不断,而且面对每个明星技术,都有些格格不入,比如Ajax出现了,而JSF要求的Post方式还需要重刷页面。但JSF一直在改进,越来越科学完善。如今,配合CDI,JSF是企业应用开发的首选技术之一,大家可以研究一下Oracle的应用产品和ADF开发框架。
CDI是Seam框架的技术精华形成的JavaEE规范,在JavaEE7里面已经成为最重要的规范之一。和Hibernate最终形成JPA一样,CDI也是GavinKing构思,开发推动的。仔细分析就会发现,CDI几乎弥补了JavaEE在现代开发需求中,对象方面定义的绝大多数不足,比如和DI规范定义了注入,生命期管理和会话范围定义,完善了EJB对于普通POJO对于事务,异步通知机制的定义,还有注解的堆叠定义,装饰模式等等。有时候我就在想,假如JavaEE是GK从头打造,我们开发人员会少走很多弯路,因为他对企业应用的理解和用Java构建框架和定义规范,都是贴近一线开发人员需求。唯一遗憾的就是CDI还没有推动完成,他转移兴趣玩起语言了。关于JSF和CDI,我建议做相关产品的朋友,即便不用这样的组合,最好也对其技术基本内容有所了解,我想对思路扩展是非常有好处的。
10. Netty,NodeJs,Vertx和异步化趋势
Netty的领导者和Mina的主力开发者TrustLee,是一个说话慢条斯里的韩国人。面试时问我一个关于volatile问题,双方都觉得非母语很别扭,所以就都简单表达一下就算。可我没想到这个同龄的开发人员,日后对Java在互联网公司的地位提升,起到这么大的作用,这个项目就是Netty。我们都知道Java异步集合库的作者DougLea的功劳,Nio1代,对于Socket的异步化还不是很完善,即便是Nio2,工作重心还是文件系统的异步化处理,网络层的异步化设计逐步加强改进。因为Java的设计理念,正交化,接口堆叠,底层功能平台统一化等给异步分布式网络框架留出足够的空间去发挥,Netty,Mina,Grizzly等项目纷纷出现。Twitter宣布从Ruby转向Scala,并使用Netty让其大红大紫。
所谓异步网络框架,就是对网络层调用,进行异步化,并进行接口封装,使得容易理解和使用。异步能力还是通过Java虚拟机现有功能实现的,通过对数据流的处理和状态感知来进行处理,而不是传统的阻塞式的收发消息。这个符合我们生活中的感受,当你订票时,你会打电话告诉你需要什么,说订好票给我电话,然后你就去做别的事情,直到订票员通知你订好了来支付取票再进行下一步操作,如果订票是同步的,那你就要一直等待订票完成,遇到春运可能会搭上整天的时间。
为什么异步网络框架也受到重视,答案也是互联网,数以亿计的请求点击涌来时,传统的webserver顶不住了,采用一个线程服务一个请求模型的webserver,无法承受这么大的数据访问,特别对于Java这样的吃内存语言,一个请求占用了一个线程,同时也占用了相对应的若干资源。用企业应用的设计的整个架构面对互联网级别的应用时,有点崩溃的感觉。解决高并发大量请求的途径是高吞吐量加上可扩展的软件架构。异步化可以提升吞吐量,就和银行的排队机一样,顾客来了得到排队服务,当有可用的柜台服务时会主动通知顾客,我们可以设想,即使有再多的顾客,也可以通过增加业务柜台,少许增加排队机和少量人工协调处理来解决。
NodeJs是一个异步化的基于Javascript的开发框架,是当前的明星技术,符合了一些当前开发需求,如异步化,前端Js技术广泛应用,Js引擎能力极大提升,NoSQL的火爆,组件构建模式变化等。利用Js语言函数式编程能力,Js开发人员可以很轻松的利用已有的组件开发后端应用,前端可以直接用浏览器处理Js,别忘了Js是浏览器唯一能统一识别的脚本语言,或者用JQuery,AngularJS等流行框架,世界很清净,都是Js。
但我们需要了解在常驻内存服务型程序方面,Java等语言占有极大优势,Java社区很快出现了和NodeJs有相同设计思路的项目,Vertx就是其中的优秀代表。它充分借鉴了NodeJs和Erlang/OTP Actor模型的优秀设计,利用分布式消息机制进行对象间通信,利用Netty进行网络异步操作,方法调用倡导异步调用,有自己的模块化机制。这样,Java社区出现了和NodeJs竞争的技术框架,良好使用,可以解决大规模互联网应用的需求。
Java领域的异步化趋势可以说刚刚开始,我们看到Servlet和EJB都加入异步支持,Spring的Reactor,JBoss的undertow,随着Java8对函数语言能力的增强,可以预见又会有丛多的项目产生。我关注着异步化趋势和JavaEE开发方式的融合之路,相信那是Web开发的明天。