`
cuiyi.crazy
  • 浏览: 52327 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java Web开发构想 (很好的文章,转)

阅读更多
Java Web开发构想
作者:buaawhl

1.背景、形势
能够进行Web开发的编程语言和技术很多
(1) 动态解释语言
PHP; Perl; Python (Zope, Plone); Ruby (Ruby on Rails);
(2) 编译语言
Java; .net

Java Web开发远非一枝独秀:
除了受到来自.net 这个重量级对手的最大挑战之外,更受到Zope, Ruby on Rail 等新式轻骑兵的冲击(当然,也继续受到老式轻步兵PHP, Perl的冲击)。

官方Java走的是复杂路线,Servlet -> JSP -> Taglib。.net走的也是复杂路线,依靠成熟友好的集成化开发环境取胜。Java阵营好容易应对过来,从纷纭复杂的各种开发框架基础上,发展出了重量级Web开发框架JSF,以及相应的集成化开发环境;渴望以此应对.net的攻势。胜负未分,前途未卜。这时,另一个方向又杀来了新式轻骑Zope, Ruby on Rail。
Python, Ruby等动态解释语言,面向对象特性更好,先天支持 动态绑定、AOP、函数式编程、“编程即配置”等时髦概念。开发速度更快,代码量更小,达到killer级别。

传统的HTML Web开发领域里面,Java已经是腹背受敌。领域外也展开了征战,Rich Client Architecture的兴起:AJAX(XMLHttp), Flash RIA, XUL, XAML, Smart Client(以及从前的ActiveX, Applet, Web Start)。

Web的发展趋势是 语义Web,最终目的是让整个Web成为一个巨大的数据库。
这意味着,未来的Web应用将更加的面向文本内容数据,更加搜索引擎友好 – Search Engine Friendly.
二进制的客户端插件,如Flash RIA, ActiveX, Applet, Web Start等,虽然交互性能最好,但不是以文本内容数据为中心,搜索引擎不友好。所以,我只是保持适当关注。我更关注基于文本的UI表现,如HTML, XUL, XAML等。XUL, XAML还没有广泛流行,只是保持一种有兴趣的关注。
当下关注的重点,还是 XHTML + CSS + Javascript少量的 AJAX(XMLHttp)增加更好的交互性。

我一直认为:轻量、简洁、高效 才是硬道理。后面阐述我对Java Web开发的理解和构想。

2. Web开发框架层次概述
从上到下,Web开发框架的层次如下:
(1) HTML, JavaScript, CSS等页面资源。
(2) 页面模板层。
如JSP, Freemarker, Velocity, XSL,fastm等。用来生成HTML, JavaScript, CSS等页面资源。
(3) Web框架。把HTTP Request调度分派到对应的Service Entry。
(4) Business Logic.
(5) O/R Mapping.
(6) JDBC
(7) DB

根据我的经验,一个典型的Web应用中的代码比例如下:
页面逻辑约占 50%,商业逻辑约占30%, O/R 约占20%。

但事实上,页面却是最不受重视的部分,从来都被认为是脏活,累活,杂活。典型的开发过程通常是这样:
页面设计人员迅速的用Dreamweaver等生成一堆文本杂乱无章的页面,然后交给JSP程序员加入更加杂乱无章的Java代码和Taglib。
当页面布局风格需要改变的时候,页面设计人员用Dreamweaver等生成一堆新的页面。JSP程序员再重新加入更加杂乱无章的Java代码Taglib。
至于页面中的脚本逻辑调试,更是一门精深的工夫了。

根据社会规则,通常来说,工作内容越轻松,收入越高;工作内容越脏月累,收入越低;Web开发也是如此:做着最脏最累的活的页面程序员,工资一般比不上后台业务逻辑程序员。

开发框架通常会带来这样的结果:让简单的东西,变得更简单;让复杂的东西,变得更复杂。
这其中的原因在于:
一般来说,一个应用中简单重复的东西占80%,复杂特殊的东西占20%。
简单重复的东西很容易摸清规律,进行包装,通用化。但是,在包装的同时,经常就阻挡住了底层的一些灵活强大的控制能力。在复杂特殊的需求中,确实又需要这些底层控制能力,那么为了绕开框架的限制,付出的努力要比不用框架 大得多。
打个比方,一个比较极端的例子。编译语言比汇编语言的开发效率高很多,但是却无法直接操作寄存器。当需要在编译语言中操作寄存器的时候,就非常的痛苦。比如Java,也许需要JNI,写C代码,还要在C代码里面嵌入汇编。编译、连接都很麻烦。
所以,一个框架的开发效率,就在于这个80%简单 与 20%复杂之间的平衡。
假如,不用框架来开发,简单的80%要消耗 80个资源数,复杂的20%要消耗20个资源数,总资源数是100;使用了某个框架,简单的80%只要消耗10个资源数,复杂的20%要消耗40个资源数,总资源数是50。那么,我们说,这个开发框架是有效率的。

我的思路是,同时应对复杂和简单。当然,为了应对复杂,简单的东西可能就应对得不那么好。比如,做这样一个开发框架,简单的80%要消耗20个资源数,复杂的20%要消耗10个资源数,总资源数是30。
这种开发框架是有可能实现的。而且是很有意义的。尤其是在复杂部分的比例提高的时候。越复杂的系统,这种开发框架就越有意义。

后面的关于Web各层开发的论述,主要就按照这个“应对复杂、让复杂更简单”的思路展开。

3.页面资源
也许有人会说,页面资源,不就是HTML吗?太简单,太低极了,没劲。Dreamweaver、Frontpage多简单阿。随便找个人来用就可以了。文本内容乱糟糟不要紧,浏览器里面显示出来的效果好看就行。要增加炫的、酷的动画效果,那就写JavaScript呗。写在HTML里面,看看在IE里面能不能运行就可以了呗。
这也正是大多数公司开发页面资源的方式。因为页面的需求变化是最多、最快的,而页面的制作成本很低,人们不愿意在上面投入更多的资源。

我的看法是,万丈高楼平地起。应用程序的每一个部分都应该完善管理,结构优美。越是需求变化多的地方,越是脏乱差的地方,越应该加大力度处理好。

页面结构方面,Javaeye论坛的Dlee做了很多工作。

(1) 在 2005 年我们如何写 JavaScript
http://forum.iteye.com/viewtopic.php?t=12973
(2)使用 Unordered Lists 制作的下拉菜单和树
http://forum.iteye.com/viewtopic.php?t=12995
从上面的Dlee的论述和给出的资料。可以看出,页面资源分为三部分:
(1) XHTML。结构,Structure。
XHTML里面的Tag部分只应该包括 <ul> <table> <p> <div><span>等结构布局Tag,或者<strong><emphasis>表示语义的Tag。
XHTML里面不应该包括风格信息,比如字体、颜色、大小、粗细等,也不应该包括<font> <b> <i> <h> 等字体信息。
XHTML里面不应该包括Javascript的定义和调用。

(2) JavaScript。行为,behavior。
JavaScritp应该存在于一个独立于XHTML文件的独立文件中。这样可以做自动化单元测试。JavaScript应该只改变HTML DOM的结构和内容,而不应该改变它的风格。

(3) CSS。Style,风格。或者说,Presentation,表现。
前面说了,XHTML里面不应该包括JavaScript的调用。那么,XHTML的元素是如何JavaScript事件绑定起来?就是在CSS里面指定的。
当然,众所周知,CSS的本职工作是处理页面风格。

页面资源方面,我完全认同Dlee的观点。从技术和资源积累的长远目标看来,这方面的初期投入的回报将是非常丰厚的。
即使将来HTML消亡了,进入了XAML, XUL, RSS时代,这些结构清晰的各部分,重用的可能性都非常巨大。JavaScript + CSS + XML UI的这种经典设计思路,将留存很久。混杂成一团的HTML的命运只能是全盘被抛弃。

4.页面模板层
页面模板层是指Server端运行的用来生成HTML(或JavaScript,CSS)的Server Side Template Engine。
这一层也是著名的脏乱差楼层。著名的HTML的Java代码污染事件,就发生在这个楼层。不仅JSP有这个问题,其他的template, 如freemarker, velocity, tapestry等含有逻辑的脚本,都不同程度上有HTML的Script Logic污染问题。

Dlee的做法很美。直接就不要页面模板层,不用Server Side Template Engine。直接用JavaScript更改HTML DOM的结构、内容、数据。同时,会用到少量的浏览器端XSL。
这样带来的结果,Template就是很干净纯粹的HTML,不含有任何Server Side Script。这个效果,和Servier Side Template 的 Jivan,XMLC达到的一样。只是一个是在浏览器端执行,一个是在Server端执行。

我研究比较了几乎所有的Server Side Template Engine,力图采众家之长,避众家之短,写了一个Server Side Template Engine -- fastm, 能够最优雅方便的实现页面模板层。关于fastm,我的Blog上有不少文章论述。
我的Blog,里面专门有个fastm 分类。
http://blog.csdn.net/buaawhl
http://buaawhl.blogdriver.com/

Fastm发布在java.net上。
https://fastm.dev.java.net/


我仍然对Server Side Template Engine持肯定态度。基于如下原因:
(1) JavaScript代码量大、文件多的时候,不容易管理,不容易进行语法检查,不容易跟踪调试。
这里有人会争辩,Server Side Template Engine也用到了很多脚本阿,比如Freemarker, Velocity, 而且嵌在HTML中,怎么管理,怎么调试?即使是JSP,也是Java Code嵌在HTML里面,怎么管理,怎么调试?
这里我要说,Jivan, XMLC, fastm,Wicket等Template Engine的逻辑都是在Java Code里面。

(2) 用JavaScript生成文本内容,搜索引擎不友好。
一般的网络蜘蛛程序,只根据URL获取HTML文本,搜索里面的文本内容,而不会执行里面的JavaScript脚本。

(3) JavaScript代码重用还是有些局限
比如,有两个HTML文件,一个是Table布局,一个是List布局。
我有同样的一批数据,要在这两种布局中显示。
这时候,就要给这两个HTML分别写两套JavaScript。这里面的DOM层次,元素,属性都不同,再怎么定义ID,Class,也无法用完全相同的一套JavaScript处理。
这里有人会争辩,Server Side Template Engine也无法做到。别说JSP, Velocity, Freemarker等要在两套HTML里面嵌入相同的代码,就是Jivan, XMLC, Wicket也要分别写不同的两套Java Code,因为它们的XML DOM Node / Model View (Table, List) 都是不同的。
这里我要说。fastm可以做到只用一套代码逻辑。而且只有fastm可以。fastm的代码重用率是最高的。

关于Ajax(XMLHttp),我的意见是必要时才用,而且最好采用粗粒度的用法 -- JavaScript发出一个URL请求,返回一整段HTML,直接替换到页面的某一块,而不是用JavaScript来做这样的把数据填充到HTML DOM中。如果你直接在浏览器里面输入那个URL,也可以获取那整段的HTML内容。
典型的应用场合是Portal。Portal页面的每个Portlet都含有这样的 Ajax(XMLHttp) javascript代码 -- 发出一个Portlet URL请求,返回一整段Portlet的内容,直接替换当前的Portlet块。
这样做的好处是:
(1) 减少JavaScript代码的量和复杂度。
(2) 搜索引擎友好。网络蜘蛛程序可以辨别JavaScript中的URL,并根据这个URL,获取整段处理好的HTML文本,进行内容搜索。
有人可能会争辩:如果URL请求返回的是XML数据,不是整段处理好的HTML,搜索引擎也可以进行内容搜索。
这点我同意。前提是XML数据的内容是足够连贯的,而不是散落的。比如,你返回的XML数据是“中国”。这个“中国”要放在HTML中的一个{country}位置,{country}足球。这个时候,结果HTML的内容含有“中国足球”。而XML数据中只含有“中国”。如果用户用“中国足球”作为关键字来搜索,就找不到这个URL。

从前面给出的fastm资料的连接中,可以得知。如同Jivan, XMLC, Wicket一样,fastm的template里面不含有逻辑,所有的逻辑都写在Java里面。
有人会争辩说:页面逻辑写在Java里面,我改变了页面逻辑,还需要重新编译。这也太不方便了。Velocity, Freemarker, JSP就不用重新编译。
这里我的看法是:业务逻辑代码改变了,不也需要重新编译吗?页面逻辑就不是逻辑了吗?HTML里面的脚本怎么语法检查、跟踪调试?业务逻辑需要语法检查、跟踪调试,页面逻辑就不需要语法检查、跟踪调试了吗?
对方可能会说:在我的应用中,页面逻辑的改动需求非常频繁,而且这些页面逻辑非常简单,不需要语法检查、跟踪调试。
这里我的意见是:
(1) 那就使用JSP, Velocity, Freemarker等脚本。
(2) fastm, Jivan, XMLC, Wicket的Java代码部分也可以写在脚本里面,比如,Server Side JavaScript, Jython(Python), Groovy, Bean Shell 等脚本语言都可以很方便的和Java相互调用。

fastm的生命周期将很长。
HTML, XUL, XAML都是,或将是可以在浏览器或可视化编辑工具里面显示的XML UI定义语言。Microsoft Office的Word, Excel, Powerpoint等格式都提供了相应的XML格式。这些XML文件都可以在Office里面显示,并编辑。
Adobe公司也提供了PDF的XML格式 -- XDP。可以在Adobe Designer里面显示并编辑。
由于fastm是Designer Friendly的XML UI所见即所得的模板技术。这方面具有很大的潜力。
根本不需要第三方花大力气专门做个IDE,来显示自定义的Tag。目标文件格式提供商自己的阅读编辑工具就可以直接用了,而且效果就是运行后产生的结果文件的效果。

即使没有可视化要求的场合。比如,Web Service需要的XML数据。fastm同样有用武之地。比如,
<!-- BEGIN DYNAMIC: users -->
<user>
<name>{name}</name>
<address>{name}</address>
</user>
<!-- END DYNAMIC: users -->

可以很容易的把一个Java Object List转化为XML数据。

另外,我不得不承认。浏览器端的JavaScript的页面逻辑,可移植性要高于Server Side Template Engine。因为Server Side Template Engine通常是特定语言相关的。
目前fastm是用Java实现的。由于实现很简单,移植到其它的语言,也很简单。如果是移植到Python, Ruby等动态解释语言,那就更简单了。我是有这个考虑,因为Zope, Ruby on Rails 的模板还是Logic 和 HTML混杂的,fastm这个思路有很大的用武之地。

前面讲了这么多。清理了两层有名的脏乱差的老大难的楼层 -- 页面资源层和页面模板层。让这两层变得和下面的楼层同样的优雅、清洁。

下面该讲到Web框架层了。在向下讲之前,由于前面提到了脚本,我想先插入一段关于“可配置”、“可编程”、“可热部署”、“脚本逻辑 vs XML Tag逻辑”的话题。把这个人们比较关心、讨论比较多的话题,先讲清楚。

5.可配置、可编程、可热部署、脚本逻辑 vs XML Tag逻辑
由于Java是编译语言,人们通常把变化的参数部分抽取出来,放到配置文件中。
这些配置文件通常是XML文件。这很好,没什么问题。XML很适合用来表达数据结构。
但是,对于某一种技术的狂热,通常引起对这种技术的过度使用,或者误用。
人们开始觉得,XML能够表达一切东西,包括for, if, else等逻辑。这方面的典型例子有 Workflow XML Definition,Logic TagLib, XSL Logic Tag等。
这点我不敢苟同。我的看法是,XML不适合表达逻辑,XML表达逻辑非常蹩脚。XML表达逻辑相当于自定义一门XML格式的脚本语言。

比如,Logic Tablib,很难自然的支持 if else, switch。只能蹩脚地支持一堆 <logic:if> <logic:ifNot> <logic:exists> <logic:notExists> <logic:ifNull> <logic:notNull>。
(注,好久没有接触过Taglib了。这些Tag Name都是凭以前的使用印象写的,也许名字不对,但表达这些意思的TagLib都还是有的)
如果要表达if () else if() else 就更蹩脚了。要进行非常麻烦的嵌套。

再比如,XSL 支持if, else 也非常蹩脚。非要多出来一个层次才行。
<xsl:choose>
<xsl:when test="…">
…. If ….
</xsl:when>
<xsl:otherwise>
… else …
</xsl:otherwise>
</xsl:choose>

同样,如果要表达if () else if() else 就更蹩脚了。
<xsl:choose>
<xsl:when test="…">
…. If ….
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="…">
…. If ….
</xsl:when>
<xsl:otherwise>
… else …
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>

可以看到,XML Tag 表达逻辑,非常麻烦,可读性很差,完全是一种误用,没有半点优势。当然,逻辑简单的情况下,还是可以接受的。
有人会说:XML表达逻辑,可以免编译阿。
那么我说:语法检查呢,跟踪调试呢?
对方说:只是一些简单的逻辑,不需要语法检查、跟踪调试。
我说:如果只是为了免编译,前面列出的那么多的解释执行的脚本语言更适合。XML表达的逻辑,比Java等编译语言还要麻烦很多,而脚本语言比Java等编译语言简洁多了,可读性非常好,而且脚本语言和Java语言有很好的交互性,可以相互调用。重用、结构方面都具有优势。

有人会举出Spring IoC为例子,说:你看,Spring IoC的配置文件不都是XML格式吗?
我说:
(1) Spring IoC的配置文件基本都是属性设置,Bean ID声明。没有逻辑。
(2) 我也不是很赞同Spring IoC在XML配置文件里面引用Java类的做法。这方面,其它的容器如 Pico, Nano都支持多种配置方式,其中包括了不少脚本方式。我觉得,在脚本里面定义生成Java Object,比在XML中要好。当然,Web.xml里面也引用了Java Class名字。但那是非常简单的情况。没有嵌套引用、属性赋值、构造参数等复杂的定义方式。XML适合描述一些通用的资源、数据、结构。比如,HTML, XUL, XAML,RSS就是XML用的恰当的例子。

所以,我的基本观点是这样。
(1) 纯数据,不用说,应该定义在XML中。
(2) 如果是系统中一些Java Object要用到的基本属性。比如,连接池大小等。定义在properties, XML, Script中都可以。如果定义中没有出现具体的Java Class名,倾向于定义在properties, XML文件中。如果出现了具体的Java Class名,倾向于定义在Script中。这个界限不那么明显,两者皆可。
(3) 复杂结构的Java Bean的构造生成,那是肯定会出现具体的Java Class名,应该定义在Script中。

关于“可配置 vs 可编程”,有一点要明确:只要是可编程的,一定是可配置的。但如果是可配置的,却不一定是可编程的。
这里的可编程,是指框架给程序员提供了API;可配置,是指框架给程序员提供了配置文件的格式写法。
“可编程”一定是“可配置”的。
(1) 用户至少可以自己定义配置文件,读取参数,调用API。
(2) 有那么多的解释脚本可以直接和Java互操作,完全可以直接用来当作配置文件,定义参数。
“可配置” 却不一定“可编程”的。
如果框架只给你提供了配置方式,而没有API,那意味着,你只能进行参数的静态配置。很难在动态期间改变这些参数了。你总不能尝试着用代码去改变配置文件的内容吧?即使你改动了,如果框架不进行文件的时间戳检查,就是一开始装载进来,就不再检查更改了,你不就一点办法都没有了吗?
比如,Struts Tiles的XML定义,你只能静态配置,你想在运行期间改变布局,没有办法。Site Mesh也是如此。而我们可以在运行期间任意操作XML DOM Node,别说布局了,任何东西都可以改变。
所以,一个框架首要注重的是提供API,而不是提供配置方式。这是一个重要的原则。

讨论完了“可编程”、“可配置”问题,我们来看“热部署”问题。
XML配置文件、脚本文件支持“热部署”当然要比编译语言程序的热部署容易得多。只要解释执行前,检查一下时间戳就可以了。要注意的问题,只是做好测试,因为没有编译期的语法检查。
不过,Java程序也是可以“热部署”的。只是稍微麻烦一点。典型的例子是JSP, EJB Jar等。JSP修改之后,会自动编译执行;EJB Jar丢到EJB Container里面,会被检测到并装载到JNDI命名空间。
编译语言Java程序的热部署的一个可能的技术难点是,Class或者Jar已经存在,如何监测到Class或者Jar的更改,并装载这个新版本,替换旧版本。
这个问题我具体没有研究过。从道理上讲,应该在Class Loader上下功夫。如果需要,可以参阅开源EJB Container的相关实现部分。Java还有一种“Hot Swap”技术,专门解决这个问题,可以搜索查阅一下。

这段小插曲,就到这里。下面讨论Web框架。

6.Web框架
Web框架层是一个清洁的楼层。很多优秀的程序员在这一层大展身手,做出了很多好作品。我感觉不错的有Spring MVC, Web Work。
对于Web应用来说,Web框架层是最重要的一层。SOA、Semantic Web等效果都要在这一层实现。
首先,我们来讨论,框架的编程结构。
我的Blog中有一篇《Java Web框架综述》的文章。讲解了一些流行的Web框架的编程结构,很多重复的内容不再赘述。
http://blog.csdn.net/buaawhl

Java Web框架综述
http://blog.csdn.net/buaawhl/archive/2004/12/21/224069.aspx

Spring MVC的编程接口是最清晰的。大多数简单情况下,Web Work的用法是最简单有效的,编程结构比较特殊,可以说具有一定的变革意义。
Spring MVC的Controller接口相当于Struts Action,也具有Request, Response两个参数,虽然编程接口非常清晰优雅,但是本质上没有什么变化。
WebWork的Action则失去了Controller的身份,只相当于FormBean的身份,或者说相当于ActionBean的身份。WebWork Action不具有Request, Response两个参数,它只具有属性,并通过属性Setter获取HTTP Request的参数,通过属性getter把结果数据输出到HTTP Response。
可以说,WebWork的这个把握是相当到位的。95%以上的情况下,程序员是不需要Request, Response参数的。当需要这些参数的时候,WebWork并没有挡住路,可以通过实现RequestAware,ResponseAware等接口来获取,或者通过一个Thread Local获取。这种情况下,编程结构的约定,就不那么清晰了。

我从Canonical的帖子和Blog受到了很多启发。
http://canonical.blogdriver.com/

jsplet:对Model 2模式的批判
http://canonical.blogdriver.com/canonical/591479.html

jsplet与webwork的概念对比
http://canonical.blogdriver.com/canonical/594671.html

从级列理论看MVC架构
http://canonical.blogdriver.com/canonical/579747.html

从Canonical的文章可以看出。JSPLet用JSP文件作为Dispatcher,然后在JSP里面注册并调用对应的Object。这个寻访Object的过程,完全是根据丰富的URL定义来做的。URL里面包括Object Scope, Object Name, Method Name, Method Parameters,天生就对事件机制有良好的支持。

Zope的一些做法也有异曲同工之妙。
Zope Object Publishing
http://www.zope.org/Documentation/Books/ZDG/current/ObjectPublishing.stx
http://www.plope.com/Books/2_7Edition/ZopeArchitecture.stx#2-3

这种通过URL获取Published Object的服务的思路,是一种实现SOA效果的有效思路。

我们首先来看Web Service的现状。目前Web Service主要分为两大阵营。SOAP和REST。关于REST,请参阅
http://www.xfront.com/REST-Web-Services.html
关于SOAP和REST的比较、互操作,网上有很多文章。如果需要请搜索查阅。

我个人比较倾向于REST风格的Web Service。
因为SOAP是一门固定的协议,如果用SOAP来编写Web Service程序,需要一个SOAP协议的解析库 ,也许还需要一些专门的“SOAP 数据 -- 编程语言”映射库,如同CORBA IDL的多语言映射一样。如果你要让自己的Web应用支持SOAP,你需要把发布的服务对象、方法都包装为SOAP协议,这需要一些编程语言相关的数据结构的映射工作。
REST则只是一种风格,而不是一个协议。中心思想是简单的通过丰富的URI定义 (如XLink + XPointer等) 获取资源。如果你要让自己的Web应用支持REST,那么很简单,只要在URI上下功夫就可以了,比如,多增加一个参数format=REST,在程序中多增加一种XML输出格式就可以了。(从道理上来说,SOAP也可以这么实现,但SOAP的输入和输出都要遵守SOAP协议,SOAP的输入参数一般都包装在SOAP信封里面)

关于HTTP Get和Post,我表述一下自己的看法。
我认为,Web的精髓在于Get,而不是Post,在于获取服务器的输出,而不是输入到服务器。即,Web的精髓在于以小搏大,四两拨千斤。最经典的用法就是用一个URL,获取一个长篇的文本内容,这个内容里面充满了其他更多的资源连接。这也是超文本连接HTML发明的初衷。
至于HTTP Post,则是这上面的一个扩展。B/S结构如此流行,很多应用都要转移到Web上面,怎么办,应用总是交互的,总要让用户输入数据吧,就增加了HTTP Post协议。
HTTP Get经典、简单、有效。可以用丰富的URI定义把这个优势发挥到极致。这个实现也比较简单、优雅。就不多说了。主要的难点在于HTTP Post。下面的讨论主要应对“HTTP Post”这个复杂现象。
HTTP Post从来就不让人们满意。当输入逻辑复杂到一定程度,表单数据的繁杂、凌乱、散落,到了服务器端很难组织起来。输入方面B/S结构确实和C/S结构难以匹敌。于是,出现了XMLHttp,能够把参数在浏览器里面组织成为一个统一的XML数据结构(或其他格式),发送到服务器端,一次解析出来。SOAP做这个方面,更是拿手好戏。所以,很多XMLHttp程序直接采用SOAP作为通信协议。而REST风格的HTTP Post则和HTML Form Post没有太大的本质区别。
REST在HTTP Get方面更胜一筹,SOAP在HTTP Post方面更胜一筹。可以根据Web应用的特点,根据HTTP Get / HTTP Post 页面的比例,选择适合的技术。
我们再进一步分析HTTP Post的数据内容。HTTP Post的数据,可能包含三种类型:
(1) 需要存档在服务器的数据
比如,用户注册时候,输入的基本信息,用户名、密码、电子邮件等。这些信息要存放到服务器的数据库。
对于这种基本信息,HTTP Post,XMLHttp,SOAP处理起来,难度都不大,没有很大区别。
B2B的数据交换,也属于这个类别。用何种技术区别不大。一般采用SOAP,因为SOAP是一种流行的标准协议。
(2) 服务调用参数
比如,用户进行复合条件查询的时候,输入的查询条件。这个时候,HTTP Post处理起来就非常蹩脚。而XMLHttp,SOAP则具有很大的优势。可以把复杂的查询条件很好组织成XML数据,发送到服务器端统一处理。SOAP里面甚至可以定义对象名、方法名等详细的调用信息。
(3) 指令
这种情况比较少见。上面的参数类别中提到的“对象名、方法名等详细的调用信息”,和这个指令类别有些交叉。
假如一个SOAP调用方法里面的参数也是一个自定义的对象,这个自定义对象的属性数据在SOAP信息中进行了定义。到了服务器端之后,服务端程序首先调用这个自定义参数的构造函数,生成这个参数对象,然后调用对应的服务对象,把这个参数传给服务。这个过程可以看作是一个顺序指令:[1]构造参数[2]调用服务。
这只是最简单的情况。而目前的Web Service一般也就支持到这个程度。
我的看法是,一不做,而不休。既然都把调用信息定义到这个程度了,不如做的更彻底一些,全面完善的支持指令。这个指令则意味着逻辑。前面讲过了,我不赞成用XML Tag表示逻辑,而赞成脚本。这里比较适合的脚本是JavaScript,因为JavaScript比较通用,客户端、服务器端都可以解释执行。注意,这里和一般的做法正好相反:一般的Web应用总是把JavaScript从服务器传到浏览器里面执行,而这里是把JavaScript在浏览器里组织好,发给服务器端处理;这个JavaScript将会在服务器端执行,调用服务器端的对象。举个SOAP含有JavaScript指令的例子 (只是示意,非标准格式) :
<soap envelope>
<XML Data>
<a>
<b>12</b>
</a>
<c>
<d>21</d>
</c>
<e>
<e>16</e>
</e>
</XML Data>

<script>
final_result = default;
result1 = service1.service(a.b);
if(result1.ok){
result2 = service2.service(c.d);
if(result2.ok)
final_result = service3.service(e.f);
}
</script>
< /soap envelope >

这个好处是:
[1] 发布了更多的基本Service。给客户提供了更大的灵活度。
比如,这里就发布了3个Service。由用户自己组织逻辑。
按照传统的做法,上述流程将整个包装在服务器端执行。发布给用户的Service只有最外面的一个Service,而且高度耦合(if, else, if, else流程hard code在服务器端),不灵活,不通用。
这里的方法,就可以让客户端随意组织service1, service2, service3的调用顺序和方式。
[2] 减少了通信次数。
假如这段Script在客户端执行,那么和服务器要进行3次通信。

传统Web的权限控制一般在URL级别,这种script -> server方式的权限控制则要在对象级别、方法级别、Code片断级别了,复杂很多,也许要大量应用Java的Code权限认证机制。

以上展开讨论了 Web Service, HTTP Get/Post。下面我们回到Web框架层。
前面说了,JSPLet给了我很大的启发。很多思路可以借鉴。
当然,我并不赞成用JSP作Dispatcher, Controller。(1) 因为JSP要编译成Servlet,而Servlet是Web Server管理的比较昂贵的资源。一个Web系统中JSP达到几千个,就会遇到性能瓶颈。(2) JSP中的代码重用很成问题。一般只能通过include file的方式。
可以借鉴的思路。(1) JSPLet 的入口是JSP文件,这一步的URL到处理程序的映射是Servlet/JSP Container自然支持的。这是免配置的。(2) 丰富的URL参数定义,良好的对象方法寻址能力。

我开发的开源Web框架lightweb,将具备如下特性:
(1) 支持两个层次的编程接口。
interface Action { void service(request, response, servletContext); }
这个Action比Struts Action, Spring MVC Controller高一个级别。相当于Dispatcher, 相当于JSPLet的JSP控制文件。这个用来做最外层的入口控制。
同时,也支持简单的JavaBean.method的直接调用。相当于WebWork Action,JSPLet Registered Object。这个用来做具体的事情。

(2) 支持丰富的对象寻址URI,比如http://my.com/myProject/myModule/myEntry.action?object=calculator&method=add&p1=1&p2=3
这表示要通过 myEntry.acion这个入口,调用caculator.add(1, 2)方法。
如果用URL Rewriter可以美化为
http://my.com/myProject/myModule/myEntry/calculator/add/1/3
看起来就很象XLink + XPointer了。

(3) 免配置。或者说极少的配置。
框架根据一定的匹配准则,把myModule/myEntry.action映射到
com.mycompany.mymodule.MyEntryAction 这个类的service方法。
这个service方法负责根据object, method的名字,寻找到对应的bean,并根据参数进行属性设置验证,并执行对应的bean.method。然后,把这个bean作为Model和template结合,输出结果。
同样,template的获取也是根据一定的匹配准则,根据myModule/myEntry找到
Mymodule/myentry.html 或者Mymodule/myentry/calculator.html。

这样的lightweb就能够同时对应简单和复杂。复杂控制的需求交给Action接口来做,简单的一般具体任务交给普通Java Bean去做。
Web框架层可以做的非常复杂,可以做的非常简单。Lightweb的目标,就是分成多个简单的部分;各部分合起来就能够完成从非常简单到非常复杂的需求。
接下来,我们来看O/R。

7.O/R
Hibernate, EJB Entity Bean产品,JDO产品,iBatis是比较流行的几种O/R Mapping Framework。
我做的一些工作中,经常涉及到复杂的优化过的native SQL,并且涉及到大量的批量复杂逻辑处理,现有的O/R框架都不能满足功能和性能要求。

我做出这样一个lightor框架,思路借鉴了Martin Fowler的《企业架构模式》里面讲述的一些O/R的Row Mapper, Column Mapper等概念。

最经典的用法是:
ResultSet rs = ps.executeQuery( a long complex native sql);
//will return a lot of records
A a = new A();
B b = new B();
IMapper aMapper = MapperService.getMapper(A.class);
IMapper bMapper = MapperService.getMapper(B.class);

While(rs.next()){
aMapper.populate(a, rs);
bMapper.populate(b, rs);

businessLogic(a, b);
}

可以看到,Lightor不需要一下子把所有纪录都放到一个Object List里面。完全可以随取随用。整个过程中,a, b只有一份,极大的节省了空间、时间,也极大的提高了开发效率,减少了重复代码。
没有任何一个其它O/R能够支持这种用法。这里面,lightor的mapper的populate方法需要ResultSet参数。一般的O/R不屑于这么做的,别说ResultSet,连Connection都想包装起来不给你看。

Lightor的设计思路也是同时应对简单和复杂。Lightor的Mapper实体部分是自动生成代码。类似于JDO的静态Enhance。不同的是,JDO静态Enhance直接修改bean class。而Lightor则不动原有的bean,只是多生成了对应的Mapper Source/Class。这种方式是最利于跟踪调试的。至于发布部署,和JDO的情况差不多,不如Hibernate的动态代码增强。
这里我很羡慕Python, Ruby等动态解释语言的

这一层我主要关注的是性能,缓存策略等等,而不是简便。我觉得,一个应用系统的瓶颈主要存在于O/R, DB层。不应该单纯为了追求OO结构的优雅,或者编程的方便,而牺牲了一些可能优化的地方。

关于Lightor的缓存策略, 我的Blog上有几篇文章。
http://blog.csdn.net/buaawhl

数据库对象的缓存策略
http://blog.csdn.net/buaawhl/archive/2004/12/21/224184.aspx

分页 & QueryKey & 定长预取
http://blog.csdn.net/buaawhl/archive/2005/01/08/245005.aspx

8.总结
我理想中的Web开发架构是这样的:
开发速度快,运行速度快,结构清晰优雅。
具体到每一层。
Web框架层主要追求 开发速度快。
O/R层主要追求 运行速度快。
页面资源层和页面模板层主要追求 结构清晰优雅。



crazycy 2007-05-01 22:54 发表评论
分享到:
评论

相关推荐

    PythonWeb开发实战(董伟明著)

    《PythonWeb开发实战》一书详细介绍了使用Python语言进行Web开发所需掌握的全方位技能。Python作为一门具有开发快速、适合多人协作、库资源丰富以及社区支持成熟的编程语言,在Web开发领域拥有广泛的应用,例如国外...

    电竞大数据发展探析——以卡牌类竞技游戏辅助工具开发构想为例.pdf

    本篇论文以卡牌类竞技游戏辅助工具开发构想为例,深入探讨了大数据在电竞领域的发展潜力及应用前景。 卡牌类竞技游戏,诸如游戏王、万智牌、炉石传说和皇室战争,这些游戏在全球范围内都有着庞大的玩家群体。为了使...

    Web移动应用框架构想.docx

    iUI等框架在这方面提供了很好的实践,通过精简Ajax请求来优化性能。 6. **手势操作** 移动手势如touchstart、touchend、touchmove等是移动应用的关键组成部分,它们取代了传统的鼠标事件。框架需要监听和处理这些...

    基于MAPGIS构想的CAD VBA绘图开发及转换技术

    ### 基于MAPGIS构想的CAD VBA绘图开发及转换技术 #### 一、概述 随着地理信息系统(GIS)技术的发展及其在各行各业的应用不断深入,如何将常用的设计软件AutoCAD与专业的GIS软件MAPGIS有效结合,成为了提高工作...

    基于Java语言开发手机软件控制折叠手机研究.pdf

    文章提出了基于分屏技术的构想,这种技术将使手机能够在展开状态下实现多任务操作,例如,在大屏模式下,能够同时运行多个应用程序,实现真正的多屏分屏效果。 分屏技术的引入,提高了手机的使用效率,使得用户可以...

    全国省级行政区电费计算模块后端开发初步构想.docx

    全国省级行政区电费计算模块后端开发初步构想:该文档帮助大家实现基础扫盲,有助于对于业务的理解。

    方配WMS框架快速Web应用开发教程

    很多的同学认为学习.NET 开发要比学习 JAVA 做项目要容易吧,不过用.NET 做一个小程序很简单, 但要你开发一个商业化系统就没那么容易了,而这套框架的目的就是让新手开发一个系统,就像他 们开发一个“计算器”小...

    船闸计算机辅助设计软件的开发构想.pdf

    文章还提到了混合编程的思想,这是指在开发过程中,结合多种编程语言或工具,发挥各自优势,以达到更好的开发效果。例如,以AutoCAD作为开发平台,结合其强大的图形处理能力和相对完善的二次开发接口,可以有效地...

    基于VB6与EXCEL的物流软件的开发构想

    基于VB6与EXCEL的物流软件的开发构想

    立体化顶岗实习解决方案开发构想.doc

    立体化顶岗实习解决方案开发构想.doc

    点到系统开发构想.docx

    【点到系统开发构想】 随着信息技术的飞速发展,特别是在互联网领域的广泛应用,传统的课堂点名方式已经不能满足现代教育的需求。针对当前大学逃课现象的严重性,我们提出了一种基于云技术的课堂点到系统开发构想,...

    基于云计算英语阅读平台的开发构想.pdf

    综上所述,基于云计算的英语阅读平台的开发构想,紧密结合了现代技术与教育需求,旨在通过云计算的优势,打破传统教学模式的局限,提供丰富多样的学习资源,促进个性化教学和学习,并支持移动学习,最终达到提高学生...

    基于Web-GIS的森林资源管理信息系统构想

    《基于Web-GIS的森林资源管理信息系统构想》是一篇探讨如何利用现代信息技术提升森林资源管理效率和质量的学术文章。Web-GIS(Web Geographic Information System)是将地理信息系统(GIS)与互联网技术相结合,实现...

    电竞大数据发展探析——以卡牌类竞技游戏辅助工具开发构想为例.zip

    本文将深入探讨电竞大数据的发展趋势,特别是以卡牌类竞技游戏为背景,阐述辅助工具开发的重要性和可能实现的技术构想。 一、电竞大数据的概念与价值 电竞大数据指的是通过收集、分析和利用电子竞技过程中的海量...

    javaSpecification(1,2,3)

    通过阅读这三个版本的规范,可以了解到Java从最初的构想到逐渐成熟的过程,以及语言如何适应不断变化的软件开发需求。同时,这也是一种回顾历史、理解技术演进的好方式。无论是初学者还是经验丰富的开发者,都应该...

    如何选择适合的Java成品网站开发团队?

    本文将探讨Java成品网站的特点、优势以及如何选择合适的开发团队来实现您的网站构想。 Java成品网站挑选:12129.cc Java成品网站以其稳定性、安全性和高度可扩展性成为众多企业选择的首选。无论您是需要建立电子...

    周家坳企业家乡村俱乐部开发构想.ppt

    【周家坳企业家乡村俱乐部开发构想】 周家坳企业家乡村俱乐部的开发构想主要集中在对项目本体的研究、发展机遇的研判以及项目的战略定位和功能布局上。该项目位于湖南省衡阳市珠晖区东阳渡镇周家坳,地理位置优越,...

    大数据时代“私人创意衣柜”穿搭APP开发构想.pdf

    "大数据时代‘私人创意衣柜’穿搭APP开发构想" 本文将围绕“私人创意衣柜”穿搭APP开发构想进行详细的知识点总结,涵盖从APP的市场前景、开发可行性到大数据时代对APP数据库的建立提供保障等多个方面。 一、APP...

    Web3.0视角下的地方志信息化平台建设构想.pdf

    【标题】:Web3.0视角下的地方志信息化平台建设构想 【描述】:本文并未直接涉及Web3.0技术或地方志信息化平台建设,而是关于小小说标题艺术的探讨。 【标签】:Web开发 开发技术 互联网 网页技术 专业指导 ...

Global site tag (gtag.js) - Google Analytics