原文
许多人认为JSP是JAVA向微软ASP挑战的成功产品,到今天,围绕着JSP方案发展出了TAG/EL等技术,JSP作为JAVA的BS前台界面方案看来已经是无法逆转。但在我看来,JAVA选择JSP这种表达形式,恰恰是它最失败的地方,是对ASP的一种拙劣的模仿,它本来可以做得更好的,甚至可能据此让微软彻底退出服务器领域,但最终,却可能成为足以令JAVA最终失败的重大战略方向性错误。
JAVA到今天仍具有微软所有语言所不具备的优点,就以C#而言,只不过是形似而神不似。java最根本的地方不在于它的OOP,不在于它是C++的语法优化,这些都不重要,而在于它的虚拟机机制,使它成为最佳的跨平台的服务器语言;而C#无论多么语法相似,都无法改变这样一个现实:它只是微软CLI中的语言中的一种,它再成功,也充其量是取代了在windows运行的JAVA;某种程度上,C#是一种注定没有必要存在的语言,在CLI中,只需要一种就够了,象VB.net。
JAVA到软件世界带来的最大的影响是令软件真正出现了分层开发,出现真正的三层结构。尽管有些家伙吹嘘他们的软件是N层结构(真不要脸!),其实究其实则,都只不过是传统的CS式的两层结构的变种,不能把函数每加一个就称为一层噢!JAVA出现体现了软件的创造性思维,但JAVA犯的错误最大的地方就在于他毫无创造性地模仿了ASP,并且,竟然把JSP作为中间件的主要访问手段加以发展。这是一个重大的失误,也许,如果有一天JAVA死掉的话,就死在这个失误上面。
ASP的是模仿最早的livewire式的jsp和cofusion,livewire也是本人最早在项目中接触的jsp,与后来的java jsp毫无相同之处。这种netscape公司的"jsp"与asp有共同的特点,就是完全没有面向对象的特性,是纯粹的解析性脚本语言,后来的PHP也是这样的产品,PHP本质上可以看作是Cscript。这些语言的出现原意是要满足那些不懂计算机语言,从HTML美工转行的半吊子程序员的能力需要,美其名为让美工可以写动态网页程度。不过,这个开发假想成了互联网出现以来最大的笑话之一,美工式的程序员始终不能写真正的动态网页,反而让真正的程序员去做了美工的活了,最典型的产品就是struts。
java与此完全不一样,它是一种需要编译的语言,具有完全的面向对象的能力;所以,它如果能够发挥这种特点,打败其他的几种脚本是毫无困难的。结果,SUN的天才的笨蛋们(我觉得这种称呼最客观,既是天才,也是笨蛋),选择了用坦克车去和捷达争夺出租车市场,做起了JSP。而我认为, servlet才应该是它最佳的发展方向。今天,我已经忘记了当初是什么原因令我放弃了jsp而使用servlet作为项目解决方案的;只记得后来完全放弃jsp是由于兼顾两种形式在传递变量和地址时非常复杂,还不如光用一种。今天当我以为我当初错了,而标签/EL等技术的出现会令JSP不同往昔而再次在重大项目中选用JSP时,(其中一个原因也是那个笑话的延续,希望不懂JAVA的维护人员可以在交货后自已维护系统前台),随着项目的进入,我记起了当初放弃JSP的原因:一个是当时的代码管理非常困难,JSP系统基本上与其他PPP类程序一样是不可维护的;另一个原因就是JSP无法基于模板进行维护。前者由于tag等的出现而缓解了,(从前也可以使用include sevlet的办法达到接近的效果),后者仍然一样,关键就在于不能复盖已有的代码。而在servlet中,重载一个方法是很容易的。
许多人以为servlet难写,在doget/dopost/init/等中需要塞进那么多的方法;其实,这是一种误解,这种误解是没有认识到 servlet本质上是一种java class,可以轻易公有私有的方法,也可以继承,可以重载等等。因此,在servlet中很容易就可以形成一个全系统追随的模板,一改一起改。相反,以为写servlet就是在doget中用out.println输出的,是把写JSP的理解带进了servlet;JSP编译成servlet后,也正是这个样子的。所以它不存在继承的价值。
那么对于复杂的html界面如何达到与jsp同样的简洁嵌入呢?其实很简单。我当时的解决方案是使用${xxx}标记预置默认的方式,然后把这些带有大量html代码的标记的文件存在某个目录;在sverlt初始化时通过文件字节流读入,使用一个字符串分析的组件(今天还在用呢)把标记转化为相应的实际动态变量。这恰恰就是今天的号称最先进的EL 表达式语言的解决方法。真的,我一点都不觉得有写servlet比一般的网页程序难在什么地方。某种程度上,我觉得自已做了一个jsp解释引擎出来了。
那么这种土产的jsp和真正的jsp有什么区别呢?最大的区别就在于它是把jspp仅仅看成是为servlet服务的html代码库,而不是 serlvet为jsp服务。换言之,这里的jsp是类似于今天的tile/Jspfragment的东西。一个小小的差别,带来的效果完全不一样,因为它可以完整的发挥出java面向对象和继承的特点;甚至可以象PB那样将整个项目前台作为一个类"继承"出来,再扩展和重整需要修改的地方。而这种能力,是那些"P"语言永远不可能做到的。但是,SUN偏偏跟在微软屁股后面去拙劣地模仿JSP。
不妨回顾一下在BS前台最常见到的架构是什么? 是一个大的网站上大部分版面具有类似的框架布局,每个分栏中只有其中某处不一样。JSP可以很容易地共用其中一样的部分;但对于其中不一样的部分就无能为力。由于JSP不能形成顶级模板,而每一个大分栏中部内容不一样,所以唯一的办法就是每一个大分栏拷贝出一个jsp文件来获得一个顶级框架模板;显然,这意味着对每一个文件的相同框架部分进行维护;项目越大,这样日后更改的工作量越大。这时侯真的有点怀念servlet的功能了,对这种需求,只需要写好一个 servlet,其他的servlet继承它,然后重载它的中央内容方法,就搞惦了。当前要达到类似要求的唯一办法,似乎只能是在顶级页面中使用if-else/equal-notequal判断里include不同的内容文件。舍此,还有什么好办法吗?
JAVA的BS前台的正确的思路应该是以一个可以订制继承方法的servlet为核心,然后可以分解一些象jsp这样的文件,类似今天的jsp中技术都可以用到这些JSP文件中。也就是说,核心应该是一个可以定制的servlet,而不是提供一个工具,把jsp编译成不可变的servlet。顶级文件应该是servlet,而不应该是JSP,这就是我所说的。
我一个人是不可能与整个JSP社区作对的,不可能一个人完成SUN几千个开发工程师的工作,既然SUN的某个天才大笨蛋选择了JSP作为JAVA在 BS的表达主流,到今天,如果我仍使用JAVA作为前台界面程序的话,最好就是随大流标准,而在几年前,JSP完全不是标准,情况是不一样了。不过,从今天实际的体验来说,我仍然强烈地觉得,SUN犯了一个严重的方法性错误。更为遗憾的是,SUN没有做到的事情,让微软在ASP.net中有所体现了,所幸微软的东西从来不打算跨平台移植的,所以SUN还有一点机会。