标题:j2ee的web和企业架构(wea)设计模式之一
作者: ganesh prasad, rajat taneja and vikrant todankar
翻译: javaduke(matrix id)
email:javaduke@263.net
qq:658155
msn:javaduke@hotmail.com
译者注:第一次接受翻译任务,由于能力和时间有限,可能有很多地方翻译的不恰当或者翻错,欢迎大家指正。欢迎给我来信告知。email:javaduke@263.net。工作qq:658155
编者注:在这篇文章中,编者打算提出下面五类模式:划分(partitioning),作用域(scope),安全(security),导航(navigation)和数据量控制(data volume control)。由于篇幅的限制,我们把文章划分为两部分。第一部分,阐述划分和范围模式。第二部分,将讲解剩下的三类模式。
由于gof(gamma, helms, johnson, and vlissides)的设计模式的广发普及,软件工程专家们找到了一个新的强有力的设计方法。什么是设计模式?他们这样定义:“设计模式就是描述一个反复出现的问题,以及解决这个问题的方案的核心。你可以重复使用这个解决方案而无须再做重复劳动。”一般来说,一个设计模式包括四个基本要素:模式名称,需要解决的问题,解决方案和使用带来模式的效果(或后果)。
在gof中描述的设计模式,诸如factory method, observer, façade等,在现在的应用设计领域已是人人皆知,家喻户晓。正像编者在先前说的那样,设计模式的命名与描述和一样起着相当重要的作用。在设计会议中人们使用设计模式的命名比使用他们枯燥乏味的描述节省工作量是可以用人小时估算出来的。
这本书出版七年以后,我们发现设计模式大致和从前是相对一致的。尽管后来也有人增加了一些设计模式,但远远不及起初gof的提出设计模式集合价值高。经试验证明,没有一个设计模式能达到最初的那23种设计模式的普及和声望。借用经济学的一个术语来说就是,新的模式的边际效用几乎趋近于零。因此设计模式科学是无非是一个一次性思想的静态集合。
正相反,从一个web领域应用程序设计者的经验来讲,我们发现一些历史经验(如果你愿意也可以叫模式)事实上是无法实施在应用程序级或子系统级上实现一套指定的方法集这样的需求,同样的方式,最初的设计模式就能完成这种低级别功能标准化的需求。
接下来我们讨论的内容其实也不是什么新东西。它们是一些许多有经验的开发人员所知道的并经常使用的简单,标准,通用的方法。仿照最初设计模式集的方式,我们对这些显而易见的方法分类和命名,希望可以使用这些命名(通过生动地捕捉这些方法的基本功能获得的)来证明它们是非常有价值的。我们把它们命名为“web和企业架构设计模式(web and enterprise architecture design patterns)”,简称“wea设计模式”一个应用程序级的设计模式的宏观命名。
作为一个j2ee的热衷者,我们仅仅关注与java相关的问题和解决方案上,尽管这样,许多概念对其他技术也还是相当有帮助的。(难道设计模式不是独立于语言的吗?这是一个相当吸引人的想法,但是确实存在争论,如gof的模式abstract factory and prototype对c++和smalltalk是非常有用的,而对java来说是多余的。因为java的class类和类的反射机制非常好的解决了这些问题。)
wea设计模式的分类和注意事项
回想gof,它把设计模式分为三类,通俗易懂,便于记忆:创建(creational),结构(structural), 和 行为(behavioral)。
秉承这一优良传统,我们把我们的模式分为划分(partitioning),作用域(scope),安全(security),导航(navigation)和数据量控制(data volume control)五类。这并不是一个详尽列表,而仅仅是最初的感觉比较适当的模式类型集。
模式描述
我们粗略地使用gof建立的描述结构来描述我们的模式。为了简便,我们将压缩处理为三个大标题。在“意图(intent)”标题下,我们用一行陈述使用这个模式的意图。我们在“问题和方案(problem and solution)”标题下阐述要解决的问题及其解决方案。最后,我们在“效果(consequences)”标题下详尽论述使用此模式带来的积极和消极的因素。
为了简洁,我们也省去uml类图描述。我们的模式是相当简单,并不需过多的描述。我们也省去了java代码样例。我们相信大多数j2ee开发人员都能明白这些模式。
划分模式(partitioning patterns)
在应用程序中,客户端(浏览器)和服务器都能执行逻辑,客户端通过javascript完成,服务器通过服务器端脚本语言如java或php执行。但由于各种原因应该把这两个层中应用程序逻辑分开。
1. 哑客户端(dumb client)
意图(intent)
不用客户端(浏览器)执行应用程序逻辑。
问题和方案(problem and solution)
许多应用程序采取一种避免使用javascript的策略。一个非常普遍的原因就是当用户
当关掉浏览器的支持javascript功能时,应用程序就不能正常的运转了。还有就是开发人员开发时还需要考虑对浏览器不同版本的支持。(尽管现在许多浏览器都改善了对w3c的兼容,但是这种考虑并没有消除)
如果有这些的原因其中一种,我就必须把所有的处理放到服务器上完成。即使是非常简单的属于前台的,而且使用javascript非常容易实现的操作也要放到服务器上执行。例如,许多电子商务应用程序在服务器端计算总数,尽管计算所需的信息都在客户端。
效果(consequences)
使用哑客户端模式给应用程序带来的好处就是可以在任何版本浏览器上运行,包括老以
前的版本。可以相当好的支持安全要求,不允许用户执行任何客户端脚本。
使用这个模式的短处就是增加了网络传输和服务器的负载。这可能对应用程序的性能造成不良的影响,尽管这种影响我们可以在用例级精确地评测出来。除此之外,许多操作不支持本地执行之后,操作会变得粗糙不流畅,使应用程序交互性变差,不友好。
2. 独立客户端(independent client)
意图(intent)
使用交互接口提高客户端和服务器的执行能力
问题和方案(problem and solution)
现在大多数web应用程序都是客户端和服务器都需处理逻辑的智能混合体。客户端使用javascript执行本地的表单验证来提高交互能力,服务器执行一些需要和后台交互的请求的处理。客户端和服务器代码单独编写,这样可能造成在两个层中一定程度的代码冗余。
效果(consequences)
使用独立客户端模式的优点就是使应用程序更自然,更舒服。许多操作可以不和服务器交互在很短的响应时间内就完成。网络传输降到最小,服务器负载降到最小。
使用此模式的缺点就是使两个层之间逻辑代码造成冗余。例如客户端的验证要比服务器端的验证更友好,因为它的更易给用户快速反馈。但它并不能代替服务器端验证,因为后台并不能依靠前台验证,后台必须执行自己的验证来保证不被错误数据侵害。这种冗余可能会造成异常和错误,尤其是在维护阶段逻辑发生变化的时候。由于java和javascript的差异很可容易使我们掉入陷阱。
3. 改良服务器客户端(server-modified client)
意图(intent)
通过少量服务器端处理来提供高级的客户端交互。
问题和方案(problem and solution)
有时,客户端的处理需要一些存储在数据库或后台的数据。应用程序可以预先把这些数据取出来放到一个数据结构中,当javascript需要时,就可以轻松的访问这个数据结构,而不需要每次都去和服务器交互一次。这样一旦一个页面被载入,客户端操作就可以迅速的访问他想要访问的数据了。例如,动态和有条件的装配一个下拉框,javascript就可以访问使用从后台数据库获得数据组装成的一个数组完成。
一些更复杂的应用程序可能需要后台来生成javascript函数。例如,用服务器控制客户端验证。
改良服务器客户端模式目的是为了处理javascript代码和使用web层java代码数据结构的变化。并不是用于生成html元素,那是jsp的基本功能。(当然,灰色域也是一种隐式商业逻辑,如有条件生成的html导航元素)
效果(consequences)
使用改良服务器客户端模式的优势就是,在没有冗余的情况下达到良好交互。使在一点控制客户端和服务器端逻辑成为可能。两个层之间的异常得以减少或消除。
使用这一模式的劣势在于增加了复杂度。因为生成javascript代码是相对简单,而维护生成这些代码的代码,复杂程度一般会增加一个数量级。
作用域模式(scope patterns)
作用域一般指一些信息的生命周期,经验告诉我们,我们遇到的作用域有下面几种:请求(request)、会话(session)和关系(relationship)。
一个请求作用域变量在客户端请求返回之前都是可以访问的。一个会话作用域变量从用户登陆到会话未结束之前一直可以访问。最后,一个关系作用域变量,只要在应用程序中存在这个用户的详细资料,这个变量就一直存在。关系作用域并不是jsp规范定义的一种作用域类型,而是根据现实中抽象出来的,诸如个性化。(我们并不去过多考虑jsp定义的page和application这两个作用域)
4. 请求访问器
意图(intent)
在多步骤的服务器端处理中,提供对请求作用域变量的统一访问的机制。
问题和方案(problem and solution)
大多数web开发的初学者会发现jsp的一个残酷而又明显的缺陷之一就是没有一个像httpservletrequest对象的getparameter()方法一样的设置器。这样就可能使请求在组件间传来传去时,在web层进行一系列操作变得特别头疼。有些操作可能还需要请求作用域变量进行修改,而缺少setparameter()方法,这将会变得极其糟糕。
请求对象的用于处理指定对象的getattribute()(与getparameter()方法相比,它将返回一个指定字符串)和setattribute()给了我们一线希望。可是,使用getattribute()方法从一个新来自浏览器请求对象中获得参数是无效的,还必须调用getparameter()方法。
请求访问器模式被设计为,使用一个兼容的接口来对请求对象的检索、存储和重检索进行管理。更简单的说,这个模式就是,工具类的一个静态方法(可以叫getattributeorparameter()方法),用于查找指定的httpservletrequest对象。先调用getattribute()方法,如果什么都没找到,就调用getparameter()方法。任何需要检索请求作用域的服务器端组件都可以使用这个方法。可以就迅速的一次性访问到从浏览器传来得参数。当这个变量是被改变了又放到请求对象中的话,必须先调setattribute()方法,然后,再调用请求访问器,就可以找到最新的被修改过的参数,而不是最初的原始数据。由于被传过来的参数都是字符串,而所有的字符串都是对象,当要检索的对象时,只要在请求访问器找到后,对字符串进行造型就可以了。
(在multi-part类型的表单中,当请求从一个传到另一个组件时,请求对象可能被扔掉并重造,过程相当复杂。这样导致所有的请求作用域的变量被丢失。例如,在这种情况就可以使用session对象(小心使用!!)把请求作用域变量传给组件。请求访问器也必须考虑到这种情况的方法。)
效果(consequences)
使用请求访问器模式的优遇就是提供一个在服务器端多步骤处理中访问请求作用域变量的简单方法。例如struts。
使用这一模式的缺憾就是要尽量避免使用属性名而带来的冲突。
5. 无状态通道
意图(intent)
把应用程序的状态管理从以web为中心的机制中独立出来。
问题和方案(problem and solution)
大多web应用程序对session的状态维护都是使用jsp引擎的隐式session对象来保存会话作用域变量的。尽管这样,多通道应用程序还是尽可能避免和以web为中心的机制缠在一起。人们更喜欢来维护客户端和应用程序服务期间点对点的状态。使中间web层(jsp引擎)保持无状态。这个方式使增加通道变得更加容易(例如ivr(interactive voice response)-交互声音响应),而无需复制维护状态逻辑。也有利于避免web会话和物理jsp引擎之间的耦合。使web层水平负载平衡方案更加容易实现,使用一个循环实现而不是使用簇。(簇相对而言是一个比较新的技术,好多旧的jsp引擎并不支持。)
无状态通道模式利于多通道应用程序中会话作用域变量的管理。当验证成功之后,应用程序服务器产生一个会话符号串,通过web层传到客户端(如浏览器),web层并不存储会话符号串,在httpsession对象也不存,其他任何地方都不存储会话符号串。客户端(浏览器)使用表单隐藏变量的形式或在一个超级链接中的一个get参数来暂存会话符号串,这样,当表单提交或链接被使用时,会话符号串会被传回web层,web层就可以处理它,(本地并不存储它),接着被传回到应用程序层验证,并检索会话作用域变量(和关系作用域变量)。这样,会话状态就被点对点维护,一种与通道完全独立的方式。因此命名为无状态通道。
效果(consequences)
使用无状态通道模式的最大优点就是可以不必给每个通道层重新开发状态管理就可以建立多通道应用程序。也可以通过简单的负载平衡方案(如循环)来实现一个具有水平比利缩放能力的通道层。
使用这一模式的主要缺点是增加了复杂度,还有使用会话对象时为避免冲突而进行的额外需求。一个纯粹的web开发者可能很难习惯这种方式。
编者注:下周我们将结束web和企业架构设计模式这个主题。编者将阐述剩下的三类模式:
安全(security)、导航(navigation)和数据量控制(data volume control)。
作者简介:
ganesh prasad: 澳大利亚第三大银行westpac banking corporation的架构师。
rajat taneja: sun公司澳大利亚负责人。
vikrant todankar:澳大利亚eds高级顾问,
被指派到澳大利亚第二大银行the commonwealth bank of australia。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器