??xml version="1.0" encoding="utf-8" standalone="yes"?> 查看源码。得知?/p>
那么控制C(x)把这个异常打Cơ,实际上显CZơ就够了(jin)?/p>
如果你在BaseAction的ActionForward xxx()中有异常抛出
那么?x)执行到ActionExceptionHandlerq个cȝexecute()Ҏ(gu)?br>
q个Ҏ(gu)有两行代码值得注意
super.execute()
log.Exception()
log.Exception()Ҏ(gu)是打印[ERROR]日志的?br>
那么Z么会(x)出现两次呢?br>
{案在super.execute() q个cLl承?jin)Struts的ExceptionHandlercR?br>
而在ExceptionHandlercM的execute()Ҏ(gu)中,已经调用?log.Exception()
所以导致会(x)出现打印两次error的情c(din)?br>
解决办法是把ActionExceptionHandler.execute()Ҏ(gu)中的调用log.Exception()的这句注释掉。那么就正常?jin)?br>
PSQ发?jin)一邮件给Matt(Appfuse's author)很快得到回信Q然后就把这个bug提交l了(jin)Appfuse的JIRA?br>
http://issues.appfuse.org
谢谢 liusong1111Q解军_法是他听?jin)我的描qC后告诉我的:(x)Q?br>
作者:(x)冉翔
W一部分 持久?/SPAN>
W一?/SPAN> 面向应用的持久层设计
C的应用系l设计中Q?SPAN lang=EN-US>MVCQ?SPAN lang=EN-US>Model-View-ControlQ作Z系l架构模式之一Q诏I了(jin)整个设计程?SPAN lang=EN-US>MVC中的MQ也是所谓的ModelQ则可以说是与业务逻辑和数据逻辑兌最为紧密地部分。而持久层作ؓ(f)Model层面中的主要l成Q其设计的优劣必对系l的整体表现产生臛_重要的媄(jing)响?SPAN lang=EN-US>
1.1 持久层概q?/SPAN>
持久Q?SPAN lang=EN-US>PersistenceQ。简单来Ԍ也就是把数据保存到可掉电(sh)式存储设备中供之后用?SPAN lang=EN-US>
所谓“持久层”,也就是在pȝ逻辑层面上,专注于实现数据持久化的一个相对独立的领域Q?SPAN lang=EN-US>DomainQ?SPAN lang=EN-US>
1.2 持久层设?/SPAN>
1.2.1 持久层设计与解耦合
1.2.1.1 何谓耦合Q何谓解耦合
何谓耦合Q通俗地讲Q就是事物之间的怺兌关系?SPAN lang=EN-US>
何谓解耦合Q即采用一些手D降低关联的紧密E度?SPAN lang=EN-US>
1.2.1.2 解耦合思想的自然演?/SPAN>
1.2.1.3 解耦合设计的目?/SPAN>
·应用层解耦合――应用逻辑与数据逻辑相分?SPAN lang=EN-US>
·资源曾解耦合――逻辑l构与物力结构相分离
1.2.1.4 持久层解耦合?SPAN lang=EN-US>DAO模式
DAOQ?SPAN lang=EN-US>Data Access ObjectQ模式实际上是两个模式的l合。即Data Accessor模式?SPAN lang=EN-US>Active Domain Object模式Q其?SPAN lang=EN-US>Data Accessor模式实现?jin)数据访问和业务逻辑的分,?SPAN lang=EN-US>Active Domain Object模式实现?jin)业务数据的对象化封装,一般我们将q两个模式组合用?SPAN lang=EN-US>
DAO模式通过对业务层提供数据抽象层接口,实现?jin)以下目标?x)
1. 数据存储逻辑的分?SPAN lang=EN-US>
2. 数据讉K底层实现的分?SPAN lang=EN-US>
3. 资源理和调度的分离
4. 数据抽象
Data AccessorQ即数据访问的实现机制加以装Q与数据的用代码相分离Q从外部来看Q?SPAN lang=EN-US>Data Accessor提供?jin)黑盒式的数据存取接口?SPAN lang=EN-US>
Domain ObjectQ则提供?jin)对面向领域内对象的装?SPAN lang=EN-US>
Data Accessor ObjectQ?SPAN lang=EN-US>DAOQ?SPAN lang=EN-US>= Data + Accessor + domain Object
所?SPAN lang=EN-US>Domain ObjectQ简单来讲就是对领域内(DomainQ设计的各个数据对象Q反映到代码Q就是一个拥有相兛_性的getterQ?SPAN lang=EN-US>setterҎ(gu)?SPAN lang=EN-US>Java ClassQ?SPAN lang=EN-US>Java BeanQ?SPAN lang=EN-US>
1.2.1.5 DAO模式的进一步改?/SPAN>
· Factory模式的引?SPAN lang=EN-US>
· Proxy模式的引?SPAN lang=EN-US>
1.2.2 持久层设计与资源理模式
1.2.2.1 Connection Pool
数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,q对外暴露数据库q接获取和返回方法?SPAN lang=EN-US>
数据库连接池技术带来下面的优势Q?SPAN lang=EN-US>
1Q?/SPAN> 资源重用
2Q?/SPAN> 更快的系l响应速度
3Q?/SPAN> 新的资源分配手段
4Q?/SPAN> l一的连接管理,避免数据库连接泄?SPAN lang=EN-US>
·Decorator模式
Decorator模式的主要目的是利用一个对象,透明Cؓ(f)另一个对象添加新的功能?SPAN lang=EN-US>
单来Ԍ是通过一?SPAN lang=EN-US>Decorator对原有对象进行封装,同时实现与原有对象相同的接口Q从而得C个基于原有对象的Q对既有接口的增强性实现?SPAN lang=EN-US>
·Dynamic Proxy模式
严格来讲Q?SPAN lang=EN-US>Dynamic Proxy本nq一U模式,只能是Proxy模式的一U动态实现方式?SPAN lang=EN-US>
·他山之石
·Apache Jakarta Commons DBCP
·Proxool
1.2.2.2 Statement Pool
1.3 持久层设计与ORM
1.3.1 ORM概述
ORM ?Object/Relation MapperQ对象-关系型数据映组件?SPAN lang=EN-US>
O/R Mapping描述的是一U设计思想或者实现机Ӟ?SPAN lang=EN-US>O/R Mapper一般指Ҏ(gu)O/R原理设计的持久化框架Q其中包含了(jin)?SPAN lang=EN-US>O/R本n之外的更多内容,?SPAN lang=EN-US>SQL自生成,事务理Q?SPAN lang=EN-US>Cache理{?SPAN lang=EN-US>
1.3.2 持久层实现类?/SPAN>
· h模式
q种模式的优点在于开发的q速便捗对于原型系l或者小型应用而言昑־别具意义。但Zq种模式开发的pȝQ其l护性和扩展性较差,对象属性,数据库结构的变动都将直接D业务逻辑代码的修攏V?SPAN lang=EN-US>
· ZData Class的持久层实现模式
DAO模式是q种模式的一U典型实现?SPAN lang=EN-US>
在这U模式中Q我们实C(jin)业务逻辑与此曾数据结构之间的分离?SPAN lang=EN-US>Data Class作ؓ(f)一个相对独立的逻辑层次。较为清晰的体现?jin)所谓持久层的概c(din)底层关pL据的l构变化Q可以较好地屏蔽在数据类q个层次。从而避免对上层的业务逻辑造成影响?SPAN lang=EN-US>
~点Q随着设计层次的增多,~码量的增加相当可观。相对地一U杂模式而言Q系l结构上得到较大提升的同Ӟ目设计和开发成本也相应增高?SPAN lang=EN-US>
· Z现有持久层框架的实现模式
q种模式是第二种模式的眼?SPAN lang=EN-US>Data Class所包含?SPAN lang=EN-US>Data Accessor?SPAN lang=EN-US>Domain Class数量q没有减?SPAN lang=EN-US>
只是把其中最为繁琐的工作――基?SPAN lang=EN-US>JDBC?SPAN lang=EN-US>OR映射工作Q交l第三方l徏完成?SPAN lang=EN-US>
Data Accessor中的J琐~码工作因此得到?jin)空前简化,而与此同Ӟ伴随持久层框架而来的辅助工具也大大减轻?SPAN lang=EN-US>Domain Class的编码负担?SPAN lang=EN-US>
1.4 持久层框架概q?/SPAN>
一个成熟的持久化框架能为我们作些什么?
· 减少乏味的代?SPAN lang=EN-US>
· 更加面向对象的设?SPAN lang=EN-US>
· 更好的性能
· 更好的移植?SPAN lang=EN-US>
1.5 L持久层框架综q?/SPAN>
· Apache OJB
· Hibernate
· iBatis
· TopLinkQ是Oracle的商业品)(j)
1,先在一?/SPAN>Action中,调用saveToken(HttpServletRequest request)Ҏ(gu)。然后{向带有表单的JSP面?/SPAN>
2Q在JSP面提交表单l一?/SPAN>ActionQ再q个Action中进行是否ؓ(f)重复提交的判断?/SPAN>
1Q?SPAN style="FONT: 7pt 'Times New Roman'"> q一?/SPAN>Action调用saveToken(HttpServletRequest request)Q这个方法内部实现如下:(x)
token.saveToken(request);
q个Ҏ(gu)的实现如下:(x)
q个Ҏ(gu)调用generateTokenҎ(gu)实现如下Q?/SPAN>
generateToken完毕后,得到的唯一?/SPAN>setAttribute?/SPAN>session中?/SPAN>
Globals.TRANSACTION_TOKEN_KEY的值是Q?/SPAN>?org.apache.struts.action.TOKEN?/SPAN>
然后跌{?/SPAN>JSP面?/SPAN>
2Q?SPAN style="FONT: 7pt 'Times New Roman'"> JSP面?/SPAN>Struts自定义标{?/SPAN> <html:form>的标{Q?/SPAN>org.apache.struts.taglib.html. FormTag
q个cȝdoStartTag()Ҏ(gu)?x)调用本cȝrenderToken()Ҏ(gu)?/SPAN>
q样子会(x)生成cM?/SPAN>
的隐藏标{?/SPAN>
然后提交C?/SPAN>Action中,?/SPAN>Action中用isTokenValid()Ҏ(gu)q行比较session?/SPAN>?org.apache.struts.action.TOKEN?/SPAN>的这?/SPAN>key所对应的值和提交来的request中的?org.apache.struts.action.TOKEN?/SPAN>的这?/SPAN>value是否一致?/SPAN>
如果?/SPAN>trueQ那么证明可以提交。如果ؓ(f)falseQ证明已l重复,不允许提交?/SPAN>
一个好的Y件框架应该具备可扩展Ҏ(gu)。在Struts框架中提供了(jin)许多可扩展之处,不放其UCؓ(f)可扩展点Q?span lang="EN-US">Extension PointQ。以下是Struts的扩展点Q?span lang="EN-US">
· 一般性扩展点Q?span lang="EN-US">Struts插gQ?span lang="EN-US">PlugInQ、扩?span lang="EN-US">Struts配置cR?span lang="EN-US">
· 控制器的扩展点:(x)扩展ActionServletcR?span lang="EN-US">RequestProcessorcdActioncR?span lang="EN-US">
· 视图的扩展点Q扩?span lang="EN-US">Struts客户化标{?span lang="EN-US">
· 模型的扩展点Q扩?span lang="EN-US">SessionContainercdApplicationContainercR?span lang="EN-US">
1.
Struts插gQ?span lang="EN-US">PlugInQ?span lang="EN-US">
Struts1.1框架提供?jin)动态插入和加蝲lg的功能,q种lg被成?span lang="EN-US">Struts插g?span lang="EN-US">Struts插g实际上就是一?span lang="EN-US">Javac,它在Struts应用启动时被初始化,在应用关闭时被销毁。Q何作为插件的Javac都应该实现org.apache.struts.action.PlugIn接口?span lang="EN-US">PlugIn接口包括两个Ҏ(gu)Q?span lang="EN-US">
public interface PlugIn {
/**
* Notification that the
specified application module is being started.
*/
public void
init(ActionServlet servlet, ApplicationConfig config)
throws
ServletException;
/**
* Notification that the
application module is being shut down.
*/
public void destroy();
}
一?span lang="EN-US">Struts应用可以包含一个或多个插g。在Struts应用启动ӞStruts框架调用每个插gcȝinit()Ҏ(gu)q行初始化。在插g的初始化阶段Q可以完成一些初始化操作Q如建立数据库连接,或者和q程pȝ的连接等?span lang="EN-US">
当应用被关闭ӞStruts框架׃(x)调用每个插gcȝdestroy()Ҏ(gu)Q?span lang="EN-US">destroy()Ҏ(gu)可以用来完成释放资源的h物,如关闭数据库q接或远E系l连接等?span lang="EN-US">
除了(jin)创徏插gcdQ还需要在Struts配置文g中配|插ӞStruts框架在启动时根据相关的配置信息来初始化插g。与插g对应的配|元素ؓ(f)<plug-in>?span lang="EN-US">
Ҏ(gu)Struts配置文g?span lang="EN-US">DTD定义Q在Struts配置文g中,<plug-in>元素必需位于其他配置元素的后面。此外,如果在配|文件中配置?jin)多个插Ӟ?span lang="EN-US">Struts框架按照它们在配置文g中的先后序来一ơ初始化他们?span lang="EN-US">
2.
扩展Struts的配|类
?span lang="EN-US">Struts应用启动ӞStruts配置文g中的所有信息都?x)被d内存中,q些信息存放?span lang="EN-US">org.apache.struts.config包的相应配置cȝ实例中?span lang="EN-US">
多数配置元素都由一?span lang="EN-US">className属性,q个属性用来设|和配置元素对应的配|类。每个配|元素都有默认配|类Q?span lang="EN-US">Struts框架允许对这些莫?dng)那配置c进行扩展?span lang="EN-US">
3.
控制器扩展点
Struts框架在控制器中提供了(jin)许多可扩展之处,允许扩展ActionServlet?span lang="EN-US">RequestProcessor?span lang="EN-US">Actionc,来实现各U客户化功能?span lang="EN-US">
3.1 扩展ActionServletc?span lang="EN-US">
?span lang="EN-US">Struts1.1以前的版本中Q?span lang="EN-US">Struts应用通常都需要扩?span lang="EN-US">ActionServletc,来实现各U定制的控制功能。在Struts1.1中,扩展ActionServletcM再是必需的。不q在某些情况下,Ҏ(gu)实际情况需要,可不妨扩?span lang="EN-US">ActionServletcR?span lang="EN-US">
?span lang="EN-US">Struts应用启动时会(x)加蝲ActionServletcdƈ调用它的init()Ҏ(gu)Q来?span lang="EN-US">Struts框架q行初始化。如果需要修?span lang="EN-US">Struts框架的初始化行ؓ(f)Q可以创Z?span lang="EN-US">org.apache.struts.action.ActionServletcȝ子类Q然后覆盖它?span lang="EN-US">init()Ҏ(gu)?span lang="EN-US">
接下来,应该?span lang="EN-US">web.xml文g中对自定义的ActionServletq行配置?span lang="EN-US">
?span lang="EN-US">Struts1.1中,预处?span lang="EN-US">HTTPh的具体操作由RequestProcessorcL完成。因此,如果需要对预处?span lang="EN-US">HTTPh的方式进行客户化Q可以扩?span lang="EN-US">RequestProcessorcR?span lang="EN-US">
3.2 扩展RequestProcessorc?span lang="EN-US">
如果扩展?span lang="EN-US">RequestProcessorc,应该?span lang="EN-US">Struts配置文g中通过<controller>元素对自定义?span lang="EN-US">RequestProcessorc进行配|?span lang="EN-US">
<controller>元素?span lang="EN-US">processorClass属性用来指定用的RequestProcessorcR?span lang="EN-US">Struts框架在启动时?x)创?span lang="EN-US">RequestProcessorcȝ实例Qƈ利用它来处理所有的HTTPh。由于每个子应用模块都有各自的配|文Ӟ因此可以为每个子应用模块配置不同?span lang="EN-US">RequestProcessorcR?span lang="EN-US">
RequestProcessorcȝ一个扩展点?span lang="EN-US">processPreprocess()Ҏ(gu)。在RequestProcessor基类中,该方法不执行M操作Q志军诶q回true?span lang="EN-US">
RequestProcessorcdprocess()Ҏ(gu)中处理请求,Process()Ҏ(gu)在调?span lang="EN-US">Action?span lang="EN-US">execute()Ҏ(gu)之前Q就?x)调?span lang="EN-US">processPreprocess()Ҏ(gu)Q如?span lang="EN-US">processPreprocess()Ҏ(gu)q回trueQ则表示l箋按正常的程处理h?span lang="EN-US">
在自定义?span lang="EN-US">RequestProcessorcMQ可以覆?span lang="EN-US">processPreprocess()Ҏ(gu)来执行特定的逻辑。如果在某些条g下希望终止处理请求,只需?span lang="EN-US">processPreprocess()Ҏ(gu)false卛_。在q种情况下,仍需要以~程的方式来军_如何转发或重定向h?span lang="EN-US">
Servlet 2.3 API提供?span lang="EN-US">Servletqo(h)器,它可以实现和processPreprocess()Ҏ(gu)相同的功能?span lang="EN-US">Servletqo(h)器也可以用来执行客户化的预处理请求操作,Web容器先调?span lang="EN-US">Servletqo(h)器,再把h转发l?span lang="EN-US">Struts控制器?span lang="EN-US">
与扩?span lang="EN-US">RequestProcessorcȝ比,通过Servletqo(h)器来预处理请求有两大qQ?span lang="EN-US">
3.3 扩展Actionc?span lang="EN-US">
Struts框架?span lang="EN-US">ActioncL最频繁的扩展点。对于具体的Struts应用Q可以先为应用创Z个扩?span lang="EN-US">Struts ActioncȝAction基类Q在q个Action基类中定义应用中所?span lang="EN-US">Action的一些公共逻辑Q它可以作ؓ(f)其他Action的父cR这U处理方式可以提高代码的可重用性,减少代码的重复?span lang="EN-US">
4.
扩展视图lg
一般说来,没有必要扩展视图lgQ因Z同的应用有不同的外观和界面,一个应用的JSP面不大可能适用于另一个不同的应用。不q,可以扩展Struts客户化标{,因ؓ(f)标签处理器ؓ(f)常规?span lang="EN-US">Javac,可以通过定义子类的方式来扩展它们Q这些扩展后的客户化标签能够被不同的应用重用?span lang="EN-US">
Struts HTML标签库中的标{֯视图内容的媄(jing)响最大。因此可以扩展这些标{来创徏客户化的应用外观。当扩展?jin)标{Q应该定义存放这些标{标签库。尽可以把自定义的标签加入到标准的Struts标签库中Q但是这?x)ɞ应用升U到新的Struts版本变得更加ȝ(ch)。所以徏议定义单独的标签库,来存攑֒特定应用相关的客户化标签?span lang="EN-US">
一旦ؓ(f)客户华标{ֺ创徏?span lang="EN-US">TLD文gQƈ且在web.xml中注册了(jin)标签库,可以在JSP文g中方便地使用q些标签?jin)?span lang="EN-US">
5.
扩展模型lg
Struts框架本n没有在模型层提供现成的模型组Ӟ因此扩展模型lg不属?span lang="EN-US">Struts技术?span lang="EN-US">
6.
结
本篇文档归纳?span lang="EN-US">Struts框架的所有可扩展炏V?span lang="EN-US">Struts框架的可扩展性开发者可以方便地定制客户化功能,提高应用的灵zL和多各U需求的可适应性。然而,实现更多的功能要花Ҏ(gu)大代L(fng)Q应该避免滥?span lang="EN-US">Struts的可扩展Ҏ(gu)?span lang="EN-US">Struts由核?j)包加上很多工具包构成。它们已l提供了(jin)很多现成的功能。因此不要盲目地扩展Struts框架Q在军_~写扩展代码前,务必先确?span lang="EN-US">Struts没有提供现成的?zhn)需要的功能。否则,重复的功能会(x)D应用l构的乱,来q得p额外的经历来清除重复功能?span lang="EN-US">
此外Q必需考虑扩展后的框架是否?x)和来的新?span lang="EN-US">Struts版本兼容Q从Struts 1.0?span lang="EN-US">Struts 1.1发生了(jin)很大的改动。在先有?span lang="EN-US">Struts版本?span lang="EN-US">API中,如果有的cȝҎ(gu)已经声明要被废弃,应该量不要覆盖q些Ҏ(gu)Q否则,当采用新?span lang="EN-US">Struts版本Ӟ׃得不对应用做相应的升U?span lang="EN-US">
模型代表应用的业务数据和逻辑?/span>Struts框架q没有ؓ(f)设计和创建模型组件提供现成的框架。不q,Struts允许使用其他模型框架来处理应用的业务领域Q如EJB(Enterprise JavaBean)?/span>JDO(Java Data Object)Q以?qing)常规?/span>JavaBean?/span>ORM(Object-Relation Mapping)?/span>
1 模型?/span>MVC中的C
模型是应用中最重要的一部分Q它包含?jin)业务实体和业务规则Q负责访问和更新持久化数据。应该把所有的模型lg攑֜pȝ中的同一个位|,q有利于l护数据的完整性,减少数据冗余Q提高可重用性?/span>
模型应该和视图以?qing)控制器之间保持独立。在分层的的框架l构中,位于上层的视囑֒控制器依赖于下层模型的实玎ͼ而上层模型不应该依赖于上层的视图和控制器的实现?/span>Struts应用的各个层ơ之间的依赖关系Q?/span>
从上CQ依赖关pd强;从下CQ依赖关pd弱?/span>
视图?/span> |
控制?/span> |
模型?/span> |
持久化层 |
|络?/span> |
如果在模型组件中通过Java?/span>import语句引入?jin)视囑֒控制器组Ӟq就q反?jin)以上原则。下层组件访问上层组件会(x)使应用的l护、重用和扩展变得困难?/span>
2 模型的概念和cd?/span>
在科学和工程技术领域,模型是一个很有用途的概念Q它可以用来模拟一个真实的pȝ。徏立模型最主要的目的是帮助理解、描q或模拟真实世界中目标系l的q{机制?/span>
在Y件开发领域,模型用来表示真实世界的实体。在软g开发的不同阶段Q需要ؓ(f)目标pȝ创徏不同cd的模型。在分析阶段Q需要创建概忉|型。在设计阶段Q需要创计模型。可以采用面向对象徏模语aUML来描q模型?/span>
2.1 概念模型
在徏立模型之前,首先要对问题域进行详l的分析Q确定用例,接下来就可以Ҏ(gu)用例来创建概忉|型。概忉|型用来模拟问题域中的真实实体。概忉|型描qC(jin)每个实体的概念和属性,以及(qing)实体之间的关pR但在这个阶Dƈ不描q实体的行ؓ(f)?/span>
创徏概念模型的目的是帮助更好地理解问题域Q识别系l中的实体,q些实体在设计阶D很有可能变成类?/span>
概念模型清楚地显CZ(jin)问题域中的实体。不是技术h员还是非技术h员都能看得懂概念模型Q他们可以很Ҏ(gu)地提出概忉|型中存在的问题,帮助pȝ分析人员?qing)早?gu)型进行修攏V在软g设计与开发周期中Q模型的变更需求提出得晚Q所耗费的开发成本就大?/span>
2.2 设计模型
概念模型是在软g分析阶段创徏的,它帮助开发h员对应的需求获得清晰精的理解。在软g设计阶段Q需要在概念模型的基上创计模型。可以用UMLcL图,zd图以?qing)状态图来描q设计模型?/span>
Ҏ(gu)UML语言Q类直接存在四种关系?/span>
1 兌(Association)
兌指的是类之间的引用关pR?/span>
2 依赖(Dependency)
依赖指的是类之间的访问关pR?/span>
3 累积(Aggregation)
累积指的是整体与个体之间的关p,可以把篏U看作一U强兌关系?/span>
4 一般化(Generalization)
一般化指的是类之间的承元素?/span>
3 业务对象(BO)
业务对象Q即Business Object(BO)Q是对真实世界的实体的Y件抽象。它可以代表业务领域中的人、地炏V事物或概念?/span>
业务对象包括状态和行ؓ(f)?/span>
判断一个类是否可以成ؓ(f)业务对象的一个重要标准,是看q个cL否同时拥有状态和行ؓ(f)?/span>
3.1 业务对象的特征和cd
如果一个类可以作ؓ(f)业务对象Q它应具有以下特征:(x)
· 包含状态和行ؓ(f)
· 代表业务领域的h、地炏V事物或概念
· 可以重用
业务对象可分ZU类型:(x)
· 实体业务对象
· q程业务对象
· 事g业务对象
实体业务对象要算是最Zh们所熟?zhn)的。实体对象可以代表h、地炏V事物或概念。通常Q可以把业务领域中的名词Q例如客戗订单、商品等作ؓ(f)实体业务对象。在J2EE应用中,q些名词可以作ؓ(f)实体Bean。对于更普通的Web应用Q这些名词可以作为包含状态和行ؓ(f)?/span>JavaBean?/span>
q程业务对象代表应用U的业务q程或流E,它们通常依赖于实体业务对象。可以把业务领域中的动词。例如客户发单、登入应用等作ؓ(f)q程业务对象。在J2EE应用中,它们通常作ؓ(f)?x)?/span>Bean或者消息驱?/span>Bean。在?/span>J2EE应用中,他们可作为常规的JavaBeanQ具有管理和控制应用的行为。过E业务对象也可以拥有状态,例如?/span>J2EE应用中,?x)?/span>Bean可分为有状态和无状态两U?/span>
事g业务对象代表应用中的一些时_(d)如异常、警告或时Q。这些时间通常ql中的某U行为处|。例如,?/span>Java Swing应用中,当客h下一个按钮,׃(x)有一个事件业务对象生,以便通知框架调用相关的时间处理器来处理事件?/span>
3.2
业务对象的重要?/span>
? 应用中用业务对象有许多好处Q最重要的一点就是业务对象提供了(jin)通用的术语和概念Q不是技术h员还是非技术h员都可以׃nq理解他们。它们可以直观地? 表真实世界中的概念,开发小l的所有成员都能理解他们。如果正对同一个业务领域需要开发出多个应用Q那么这些应用可以共享这些业务对象。业务对象的可重? Ҏ(gu)可以提高应用开发速度。减冗余?/span>
此外Q业务对象可以隐藏实现细节,对外只保露接口。例如,如果业务对象的某个方法需要传?/span>java.util.ArrayListcd的参敎ͼ那么应该把参数定义ؓ(f)java.util.List接口cd。这P假定q个Ҏ(gu)的实现发生改变,?/span>LinkedList取代ArrayList来实现原有的功能Q这U概念不?x)对?gu)调用者造成M英雄?/span>
在充分了(jin)解到业务对象在应用中的重要性后Q接下来需要关?j)的问题是,q些业务对象的状态从何而来Q当应用中指q行Ӟq些状态被存放C么地斏V这涉?qing)到了(jin)对象的持久化问题?/span>
4 业务对象的持久化
通常Q持久化意味着通过手工或其他方式输入到应用中的数据Q能够在应用l束q行后依然存在。即使应用运行结束或者计机关闭后,q些信息依然存在。不是大、中或、小型的应用Q都需要数据的持久化?/span>
4.1 对业务对象进行持久化的作用?/span>
当应用中的业务对象在内存中创建后Q它们不可能永远存在。最后,他们要么从内存中清楚Q要么被持久化到数据存储库中。内存无法永久保存数据,因此必需对业务对象进行持久化。否则,如果对象没有被持久化Q用户在应用q行时发出的订单信息在应用l束q行后随之小时?/span>
关系型数据库被广泛用来存储数据。关pd数据库中存放的是关系型数据,它是非面向对象的。把业务对象映射到非面向对象的数据库中,存在着L不匹配(impedance mismatchQ,因此对象q态和行ؓ(f)l成Q而关pd数据库则pl成Q对象之间的各种关系和关pd数据库中表之间的关系q不一一对象。例如对象之间的l承关系׃能直接映到关系型数据库中?/span>
4.2 数据讉K对象Q?/span>DAOQ设计模?/span>
面向对象的开发方法是当今的主,但是同时不得不用关pd数据库,在企业应用开发的环境中,对象Q关pȝ映射Q?/span>Object-Relation MappingQ简U?/span>ORMQ是一U耗时的工作。围l对象-关系的映和持久化数据的讉KQ在软g领域中发展v来了(jin)一U数据访问对象(Data Access ObjectQ简U?/span>DAOQ设计模式?/span>
DAO模式提供?jin)访问关pd数据库系l所需的所有操作的接口Q其中包括创建数据库、定义表、字D和索引Q徏立表间的关系Q更新和查询数据库等?/span>DAO模式底层数据访问操作与高层业务逻辑分离开Q对上层提供面向对象的数据访问接口。在DAO的实CQ可以采?/span>XML语言来配|对象和关系型数据之间的映射?/span>
对于Java应用Q可以直接通过JDBC~程来访问数据库?/span>JDBC可以说是讉K持久数据层最原始、最直接的方法。在企业U应用开发中Q可以通过JDBC~程Q来开发自qDAO APIQ把数据库访问操作封装v来,供业务曾同一调用?/span>
如果数据模型非常复杂Q那么直接通过JDBC~程来实现持久化框架需要有专业的知识。对于企业应用的开发h员,p大量旉从头开发自q持久性框架不是很可行。通常Q可以直接采用第三方提供的持久化框架Q如ORM软g产品。许?/span>ORM框架都采?/span>DAO设计模式来实玎ͼ为模型层提供?jin)访问关pd数据库的API?/span>
4.3 常用?/span>ORM软g
有许?/span>ORM软g可供选择。有些是商业化的Q有些是免费的?/span>
TopLink |
|
Torque |
|
ObjectRelationalBridge |
|
FronierSuite |
|
Castor |
|
FreeFORM |
|
Expresso |
|
JRelationalFramework |
|
VBSF |
|
Jgrinder |
|
Hibernate |
不管是用商业化产品Q还是非商业化品,都应该确保选用?/span>ORM框架没有“渗透”到应用中,应用的上层组件应该和ORM框架保持独立。有?/span>ORM框架要求在业务对象中印入它们的类和接口,q会(x)带来一个问题,如果日后x用其他的ORM框架Q就必需修改业务对象?/span>
5 结
q篇文介绍?jin)模型的实现?gu)?/span>Struts框架q没有在模型层提供线E可用的lg。模型的实现应该?/span>Struts应用的控制层以及(qing)视图层保持独立?/span>
模型采用业务对象来描q状态和行ؓ(f)Qؓ(f)?jin)业务对象持久化,需要把业务对象映射到关pd数据库?/span>
模型向客L(fng)序提供了(jin)业务代理接口Q业务代理接口直接访问持久化框架Q处理实际的业务逻辑?/span>Struts应用?/span>Actioncd以用这个业务代理接口,而不必直接和持久化框架交互。这U做法有助于削弱上层Web应用和持久化框架之间的关p,提高持久化框架的相对独立性?/span>
阅读材料Q《精?/span>StrutsQ基?/span>MVC?/span>Java Web设计与开发?br>
2005q?5?2?1:20 AM
Web.xml文g对于配置MJava Web应用都是必须?/span>.当配|?/span>Struts应用?/span>,q应该在web.xml文g中配|和Struts相关的配|选项.一下讲q配|?/span>Struts应用的必要步?/span>.
1·配置Struts?/span>ActionServlet
W一步用<servlet>元素来声?/span>ActionServlet?/span>
?/span><servlet>的子元素中,l常用到的有Q?/span>
·<servlet-name>元素用来定义Servlet的名U?/span>
·<servlet-class>元素用来|顶Servlet的完整类名?/span>
·<init-param>元素用于配置Servlet初始化参数?/span>
W二步ؓ(f)配置<servlet-mapping>元素Q用来指?/span>ActionServlet可以处理哪些URL?/span>
有子元素<servlet-name>?/span><url-pattern>Q注意,q里?/span><servlet-name>必须?/span><servlet>元素中的<servlet-name>匚w?/span>
**提示**
不管应用中包含多子应用Q都只需要配|一?/span>ActionServlet。有些开发者希望设|多?/span>ActionServletcL处理应用中不同的功能Q其实这是不必要的,因ؓ(f)Serlvet本n支持多线E。而且Q目前的Struts框架只允许在应用中配|一?/span>ActionSerlvet?/span>
2·配置Ƣ迎文g清单
<welcome-file-list>元素中可以包含多?/span><welcome-file>子元素,?/span>Web容器调用Web应用的欢q文件时Q首先寻扄一?/span><welcome-file>指定的文件。如果这个文件存在,把q一个文件返回给客户Q如果这个文件不存在Q?/span>Web容器依ơ寻找下一个欢q文Ӟ直到扑ֈ为止Q如果都不存在,服务器将向客戯回?/span>HTTP
3·配置错误处理
<error-page>
<error-code></error-code>
<location></location>
</error-page>
如果?/span>web.xml文g中做?jin)以上配|,?/span>Web容器捕获到错误时Q如Q?/span>HTTP 404?/span>HTTP 500Q,根据错误代码减~?/span><error-page>的子元素<error-code>Q如果有匚w就q回<location>子元素指定的文g?/span>
也可以ؓ(f)Web容器捕获?/span>Java异常配置<error-page>元素Q这是需要设|?/span><exception-type>子元素,它用于指?/span>Java异常cR?/span>Web容器可能捕获如下异常Q?/span>
·RuntimeException?/span>Error?/span>
·ServletException或它的子cR?/span>
·IOException或它的子cR?/span>
q里的配|信息如下:(x)
<error-page>
<exception-type></exception-type>
<location></location>
</error-page>
4·配置Struts标签?/span>
<taglib>元素有两个子元素Q?/span><taglib-uri>?/span><taglib-location>?/span><taglib-uri>元素指定标签库的相对或者绝?/span>URI地址Q?/span>Web应用根据这一URI来访问标{ֺQ?/span><taglib-location>元素指定标签库描q文件在文g资源pȝ中的物理位置?/span>
如果Web应用中没有?/span>Struts标签库,没有必要在web.xml文g中配|它。此外,也可以按以上方式?/span>web.xml文g中配|用戯定义的客户化标签库?br>
2005q?4?8?6:18 PM