??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲av激情无码专区在线播放,国产精品亚洲专区无码不卡,久久亚洲中文字幕精品有坂深雪 http://www.tkk7.com/Victor/category/5620.html享受喧嚣 安于q静zh-cnTue, 27 Feb 2007 10:22:42 GMTTue, 27 Feb 2007 10:22:42 GMT60XML alphabet souphttp://www.tkk7.com/Victor/articles/27524.htmlVictorVictorWed, 11 Jan 2006 02:07:00 GMThttp://www.tkk7.com/Victor/articles/27524.htmlhttp://www.tkk7.com/Victor/comments/27524.htmlhttp://www.tkk7.com/Victor/articles/27524.html#Feedback0http://www.tkk7.com/Victor/comments/commentRss/27524.htmlhttp://www.tkk7.com/Victor/services/trackbacks/27524.html[文章信息]
 
作? kissjava.com?
旉: 2005-05-12 12:31:15
出处: KissJava.com
责Q~辑: Icy

[文章D]
 
目前讉KXML文档的API分成两种讉K方式Q顺序的和Q意的讉KQ分别是QSAX和DOM。确认XML的合法性的规范是DTD (最初的机制Q作为XML规范被定?和不同的概要标准提案Q一U更新的机制Q它使用XML语法来做描述合法性准则的工作Q?nbsp;

XML和相兌|(x)消化字母汤(“字母汤”alphabet soup是一U罐头汤Q里面是切成ABC字母图案的细面条Q让朋友边喝汤Ҏ(gu)里面的字母排成单词来玩)

现在Q你已经对XML有了一个基本的理解Q需要对与XML相关的羃写单词代表的意义有一个更q认识。有很多的基于XML的工作要做,所以你需要学?fn)很多的知识?/P>

目前讉KXML文档的API分成两种讉K方式Q顺序的和Q意的讉KQ分别是QSAX和DOM。确认XML的合法性的规范是DTD (最初的机制Q作为XML规范被定?和不同的概要标准QSchema StandardsQ提案(一U更新的机制Q它使用XML语法来做描述合法性准则的工作Q?/P>

其它的一些未来的标准已经接近完成Q包括XSL标准Q一U徏立XML文档转换-例如XML文档转换到HTML或其他的XML文档Q?和指C文档如何提交的机制Q。XSL标准的{换部分(XSLT (+XPATH)Q已l完成ƈ且包含在本指南中。其他的接近完成的成果是XMLq接语言QXML Link LanguageQ规范(XML LinkingQ,q个规范可以在XML文档之间做连接?/P>

以上q些是你将要了解的初步内容。这部分也纵览了一些其它的感兴的提案Q包括HTMLcM标准QHTML-lookalike standardQ?- XHTML 和描qXML包含的信息的元标?- RDF。有些标准成果扩展了XML的能力,比如Xlink和Xpointer?/P>

最后,有很多的感兴的标准和标准提案徏立在XML之上Q包含同步的多媒体综合语aQSynchronized Multimedia Integration LanguageQ?- (SMIL)Q数学标记语aQMathematical Markup LanguageQ?- MathML Q可伸羃的向量图形(Scalable Vector GraphicsQ?- SVGQDrawML和许多的?sh)子商务标准?/P>

余下的部分你了解这些初步的更详l的l节。ؓ(f)了保持连贯性,q部分被分ؓ(f)如下斚wQ?BR>1. 基本标准
2. 概要标准
3. q接和显C标?BR>4. 知识标准
5. 建立在XML上的标准
基本标准
一些你需要熟(zhn)的基本标准?BR>SAX
针对XML的简单API(Simple API for XML)

q个API实际上一个协作品,它不是W3C的品。它被包含在里面是因为它拥有W3C的特征?/P>

你也可以把这个标准想象ؓ(f)XML的连l访问协议。它拥有在服务器中读写XML数据的最快的执行机制。也可以U它Z仉动协议,因ؓ(f)q个技术将在SAX parser中注册你的操作,注册完后Q当parser看到一个新的XML标记Ӟ或者遇C个错误,或者parser惛_诉你其他的事情)Qparser׃(x)调用你的回调Ҏ(gu)?/P>

DOM

文档对象模型QDocument Object ModelQ?BR>文档对象模型协议一个XML文档转换成一个对象集。然后你可以操作随意的操作这个对象模型。这个机制被UCؓ(f)“随意访问”协议,因ؓ(f)你能够在M时候访问数据的L部分。然后,你可以修攏V删除和插入数据?/P>

JDOM and dom4j
当文档对象模型(DOMQ提供非常强大的面向文档的处理的时候,它却不能提供更多的面向对象的化。Java开发者会(x)做更多的面向数据处理Q而不是面向书c、文章和其他的完全的文档Q他们发现面向对象的APIQ如:JDOM和dom4jQ更Ҏ(gu)使用和符合他们的需要?/P>

下面是JDOM和dom4j的不同:(x)
1. JDOM是更整齐、更y的API。在代码风格Qcoding styleQ重要的时候,JDOM是一个不错的选择?BR>2. JDOM是一个Java团体处理QJava Community Process--JCPQ初步。当完成Ӟ它将是一个认可的标准?BR>3. dom4j是一个更y、更快的实现Q它使用的范围很qѝ?BR>4. dom4j是一个基于制造商Qfactory-basedQ的实现。它更容易修改复杂的、特D目的的应用E序。在dom4j~写的时候,JDOMq没有用利用工厂(factoryQ来事例化分析器对象。所以,使用JDOMQ你L得到原始的分析器?/P>

关于JDOM的更多的信息Q?A >http://www.jdom.org/.
关于dom4j的更多的信息Q?A >http://dom4j.org/.

DTD
文档cd定义QDocument Type DefinitionQ?/P>

DTD规范是XML规范的一部分Q而不是一个单独的实体。另一斚wQ它是可选的?你可以一个没有DTD的XML文档。有很多的概要(SchemaQ标准提案来提供更灵zȝ规范。所以,你完全可以将它看成是单独的部分?/P>

一个DTD规范了不同种cȝXML标识和合法的标识的布局。你能够使用DTD来确定你不能产生一个非法的XMLl构。你也能够用它来确定你正在d得XMLl构是合法的?/P>

不幸的是Qؓ(f)一个复杂的文档指定一个DTD是非常的困难的。所以构Z个DTD在某U意义上讲是一门艺术。DTD可以出现在文档的前端Q作为序的一部分。它也可以作为单独的一个实体,或者在文档的序和外部的实体中同时存在?/P>

命名I间
命名I间标准允许你用两个或更多的XML标记集合~写XML文档。例如你产生一个基于XML的列表,q个列表使用的标记是另一个厂商提供的。在整个XML文档中“price”数据可能会(x)很多Q然而,你只是想昄针对一个结构的“price”数据。命名空间规范定义了一个限定名U的机制Q这样可以避免؜淆。这h们写的程序就可以正确的处理文档中的信息?/P>

最新的命名I间信息Q?A >http://www.w3.org/TR/REC-xml-names.

XSL
扩展样式表语aQExtensible Stylesheet LanguageQ?/P>

XML标准指定怎样识别数据Q而不是怎样昄数据。从另一斚w来说QHTML是告诉数据怎样昄而不是怎样识别数据。XSL标准有两部分QXSLT和XSL-FO。XSL-FOZ提供面上的多区域定义ƈ他们连接到一赗当一个文本流被导向这个集合,它首先流向第一个区域,在第一个区域被充满后会(x)导向W二个区域。像q样的对象被使用在新ȝ、一览表和杂志出版中?/P>

最新的XSL标准Q?A >http://www.w3.org/TR/WD-xsl

XSLT(+XPATH)
针对转换的扩展样式表语言QExtensible Stylesheet Language for TransformationsQ?/P>

XSLT的{换标准本质上来讲是一个{换机Ӟ它让你指定将一个XML标记转换成什么ƈ用来昄。例如,转换成HTML标识。不同的XSL格式能够以不同的方式昄同样的数据。(XPATH标准是一个寻址机制Q当你构造{换指令示?x)用到它。)

概要标准
一个DTD佉K证相关的单XML文档是否合法成ؓ(f)可能Q但是做h很难?/P>

一个DTD不能限制元素中的内容Q不能指定复杂的关系。例如,指定一?lt;book>中的<heading>必须包含?lt;title>?lt;author>Q而一?lt;chapter>中的<heading>紧紧需要一?lt;title>。在DTD中,你只能一ơ的指定<heading>的结构。DTD不是上下文敏感的Q因为DTD规范不是层次的?/P>

例如Q一个邮件地址包含几个“解析的字符数据QPCDATAQ”元素,DTD可能?x)像下面q样Q?BR><!ELEMENT mailAddress (name, address, zipcode)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ELEMENT zipcode (#PCDATA)>
像你看到的那Pq个规范是线性的。所以,在DTD中,如果你需要另一个“name”元素,那么你需要ؓ(f)它定义一个不同的识别W。你不能单的U它为“name”,因ؓ(f)它会(x)?lt;mailAddress>元素中用的“name”冲H?/P>

另一个问题是DTD的无层次性得理解其中的注解很困难。一个在最上面的注解看h更像是针对全文结构的注解Q但也可能它只是对第一条的注解。最后,DTD不允怽形式上的指定合法域准则,例如寚w政编码域中的5位数限制?/P>

最后,一个DTD使用的语法不同于XMLQ所以它不能被一个标准的XML分析器解析。这意味着你不能将DTD读进DOMQ和~辑、修改它?/P>

Z修补q些~点Q很多的提案已经被提交。像层次性的“概?-schema”,它指定了合法性准则。后面介l了一些主要的提案?/P>

XML概要QSchemaQ?BR>一个大而复杂的标准Q它拥有两部分。一部分指定l构联系Q这是最大最复杂的部分)。另一部分指定XML元素中的内容的合法性机Ӟ可以通过为每个元素指定一个数据类型。一个好消息是,XML概要可以指定M设想的关联。坏消息是他很难实现也很隑֭?fn)?/P>

XML概要的更多的信息Q可以查看W3C specs XML Schema(Structures) and XML Schema(Datatypes).
http://www.w3c.org/XML/Schema.

RELAX NG
XML的规则语a描述Q下一代)--QRegular Language description for XMLQNext GenerationQ)

RELAX NG是一个新兴标准,它要比XMLl构概要单。再不远的将来它也可能成Z个ISO标准?/P>

RELAX NG使用规则表达式来表达l构关系上的限制Q它使用XML概要数据cd机制来表辑ֆ容上的限制。这个标准也使用XML语法Q它包含一个DTD到RELAX的{换器。(说它是“next generation”是因ؓ(f)它是l和TREX 的RELAX概要机制的新版本Q?/P>

关于RELAX NG的更多的信息Q?A >http://www.oasis-open.org/committees/relax-ng/

TREX
针对XML的树(wi)型规则表辑ּQTree Regular Expressions for XMLQ?/P>

它是一个通过为XML文档中的l构和内Ҏ(gu)qC个模版来表达合法性准则的手段。现在作为RELAX NG的一部分?/P>

SOX
面向对象的概要(Schema for Object-oriented XMLQ?/P>

SOX是一个概要提案,它包括扩展数据类型、命名空间和嵌入的文档?/P>

SOX更多的信息:(x)http://www.ascc.net/xml/resource/schematron/schematron.html.

q接和表现标?BR>可以证明QHTML中的文档之间的连接和单的文档格式是最大的优点。下面的标准定位于在XML中保留HTML的好处ƈ增加额外的功能?/P>

XML Linking
q些规范提供一个不同的q接能力Q但对XML的用上形成了一ơ很大的冲击?/P>

XLink
Xlink协议是一个在XML文档间处理连接的规范。这个规范允怸些恰当的改进q接Q包含双向连接、连接到多文档、展开q接、内部指向连接等?/P>

XML 基础
q个标准定义一个XML文档属性,q个属性定义一个“基”地址Q“基”地址在查找一个关联的地址时被使用。(例如Q一个简单的文g名可以在一个基地址目录中被扑ֈQ?/P>

XPointer
一般情况下QXlink规范是将使用它的ID的文档或文档片断作ؓ(f)目标的。XPointer规范定义的机制是针对“在一个XML文档内部l构的寻址”的。XPointer规范不需要文档的作者ؓ(f)一个文档片断定一个ID?/P>

XMLq接的更多的信息Q?A >http://www.w3.org/XML/Linking.
XHTML
XHTML规范是XML文档的一个用途,只不qXML文档更像HTML文档。既然XML文档可以包含L的标识,那么Z么不能定义一个很像HTML标识的XML标识集呢Q这是XHTML的想法。这个规范的l果是一个文档既能在览器中昄Q又能作为XML文档被处理。尽它q不是纯正的XMLQ但是它比HTML更容易被处理?/P>

例如Q在一个格式良好的XML文档中,每一个标识必L一个结束标识。所以在XHTML中,你可能看?lt;p>..</p>Q或<p/>。但你绝对看不到单独?lt;p>?/P>

XHTML规范是一个HTML4.0到XML的再形成。最新的信息在:(x)http://www.w3.org/TR/xhtml1.

知识标准
RDF
资源描述框架QResource Description FrameworkQ?/P>

RDF是一个定义元数据的标准,元数据是描述一个特D的数据条目是什么的信息q指定怎么h使用q个数据条目。例如,联合XHTML规范或HTML面来用,RDF被用来描q页面的内容。例如,如果你的览器存储你的ID信息像FIRSTNAME、LASTNAME和EMAILQ一个RDF描述传输传输个需要NAME和EMAILADDRESS的应用程序相应的信息。想象一下,到那一天,你可能不需要在每个|站里输入你的名字和邮g地址?/P>

关于RDF更多的信息:(x)http://www.w3.org/TR/REC-rdf-syntax

RDF概要
RDF概要允许相容性原则和附加信息的规范?/P>

更多的RDF概要信息Q?A >http://www.w3.org/TR/rdf-schema.

XTM
XML主题映射QXML Topic MapsQ?/P>

在许多方面,M映射标准是一个比RDF更简单的、更Ҏ(gu)使用得知识表C,它更应该值得被关注。迄今ؓ(f)止,RDF是一个W3C标准Q但是,主题映射可能只能作ؓ(f)一U开发者选择的标准?/P>

XML主题映射更多的信息:(x)http://www.topicmaps.org/xtm/index.html.

建立在XML上的标准
下面的标准和提案都是建立在XML之上的。因为XML基本上是一个定义语a的工P所以这些标准用它定义Ҏ(gu)目的标准语言?/P>

扩展文档标准QExtended Document StandardsQ?BR>q些标准定义了用XML产生极端复杂的文档的机制?/P>

SMIL
同步的多媒体l合语言QSynchronized Multimedia Integration LanguageQ?BR>SMIL是一个W3C的标准,它涵盖了音频、视频和动画?/P>

更多关于SMIL的信息:(x)http://www.w3.org/TR/REC-smil.

MathML
数学标记语言QMathematical Markup LanguageQ?/P>

MathML是一个W3C的标准,它处理数学公式的昄?/P>

更多关于MathML的信息:(x)http://www.w3.org/TR/REC-MathML.

SVG
可׾~的向量囑փQScalable Vector GraphicsQ?/P>

SVG是一个W3C工作草案Q它覆盖了向量图像的昄?/P>

更多关于SVG的信息:(x)http://www.w3.org/TR/WD-SVG.

DrawML
l制元语aQDrawing Meta LanguageQ?/P>

DrawML是一个W3C的附注,它涵盖了技术图表的2D囑փ?/P>

更多的关于DrawML的信息:(x)http://www.w3.org/TR/NOTE-drawml.

?sh)子商务标准QeCommerce StandardsQ?/P>

q些标准定位于在B2B和B2C的范围里使用XML?/P>

ICE
信息和内容交换(Information and Content ExchangeQ?/P>

ICE是一个被内容l营者用的协议。它的焦点在“在传统出版和B2B联系上自动化内容转换和重用?/P>

更多关于ICE的信息:(x)http://www.w3.org/TR/NOTE-ice.

ebXML
ZXML的电(sh)子交易(Electronic Business with XMLQ?/P>

q个标准定位在用XML建立模块化的?sh)子交易框架。它是UN/CEFACT的一个v步品?/P>

更多关于ebXML的信息:(x)http://www.ebxml.org/.

cxml
商业XMLQCommerce XMLQ?/P>

cxml是一个RosettaNetQ?A >www.rosettanet.orgQ标准,它的目的是ؓ(f)了不同的C建立一个在U的名单?/P>

更多关于cxml的信息:(x)http://www.cxml.org/

CBL
通用交易库(Common Business LibraryQ?/P>

CBL是一个元素和属性定义的库?/P>

更多关于CBL的信息:(x)http://www.commerce.net/projects/currentprojects/eco/wg/eCo_Framework_Specifications.html.
UBL
l一商业语言QUniversal Business LanguageQ?/P>

一个OASIS初步定位在编译一个XML交易文档的标准库?/P>

更多关于UBL的信息:(x)http://www.oasis-open.org/committees/ubl.

ȝ
XML是一个正在被q泛的应用的标准Q它正在被用在不同的领域?BR>



Victor 2006-01-11 10:07 发表评论
]]>
译了篇AJAX的文章Usint AJAX With JAVA Technology(?http://www.tkk7.com/Victor/articles/26055.htmlVictorVictorFri, 30 Dec 2005 06:43:00 GMThttp://www.tkk7.com/Victor/articles/26055.htmlhttp://www.tkk7.com/Victor/comments/26055.htmlhttp://www.tkk7.com/Victor/articles/26055.html#Feedback0http://www.tkk7.com/Victor/comments/commentRss/26055.htmlhttp://www.tkk7.com/Victor/services/trackbacks/26055.html闲着没事Q在SUN.COM上看CAJAX的文章,感觉不错Q所以试着译成了中文。许多地方自׃把握不也作者的意思,加上个h英文水^不咋圎ͼ可能许多不正的地方Q希望大家指正?BR>样例安装的一D|有翻译,感觉没有必要~~Q例子中没有附JSTL包,要自己到APACHE下蝲安装。)

原文地址Q?A >http://java.sun.com/developer/EJTechTips/2005/tt1122.html#1

by Greg Murray
作者:(x)格雷|默里
AJAX stands for Asynchronous JavaScript and XML. In essence, AJAX is an efficient way for a web application to handle user interactions with a web page -- a way that reduces the need to do a page refresh or full page reload for every user interaction. This enables rich behavior (similar to that of a desktop application or plugin-based web application) using a browser. AJAX interactions are handled asynchronously in the background. As this happens, a user can continue working with the page. AJAX Interactions are initiated by the JavaScript in the web page. When the AJAX interaction is complete, JavaScript updates the HTML source of the page. The changes are made immediately without requiring a page refresh. AJAX interactions can be used to do things such as validate form entries (while the user is entering them) using server-side logic, retrieve detailed data from the server, dynamically update data on a page, and submit partial forms from the page.
AJAX代表着异步的JAVASCRIPT和XML。本质上QAJAX是一U在WEB应用中通过|页与用户交互的有效方式Q它减少了用户交互中h面或整重载的频率。这样用浏览器可以q行更丰富的动作Q与桌面应用或基于PLUGIN的WEB应用怼Q。AJAX交互在后台异步执行,此时用户可以l箋在这个页面上工作。AJAX是由|页中的JAVASCRIPT驱动的。当AJAX交互完成后,JS更新|页HTML代码。这个动作在不需要刷新页面的情况下迅速执行。AJAX可以用于许多斚wQ例如在用户输入的同时用服务器端规则验证其输入,获得服务器端详细数据q主动更新页面数据,或者提交页面表单的部分数据?BR>What is particularly attractive about this is that AJAX applications do not require a separate plug-in, and are platform and browser-neutral. That said, AJAX is not supported as well in older browsers. Care needs to be taken in writing client-side script that accounts for the differences between browsers. You might consider using a JavaScript library that abstracts the browser differences and in some cases support older browsers using alternative interaction techniques. For more details, see the AJAX FAQ for the Java Developer
是什么让AJAX技术具体如此魅力呢QAJAX应用不需用单独的插gQƈ且是q_和浏览器中立的。也是_(d)AJAXq不被旧的浏览器良好支持。但是不必太q担心,你可以撰写跨不同览器的脚本。你应该考虑使用跨不同浏览器的JS库ƈ且在一些情况下有选择性的使用交互技术以支持旧的览器。了解更多,h看JAVA开发者的AJAX  FAQ?A >http://weblogs.java.net/blog/gmurray71/

So Where Does Java Technology Fit In?
那么JAVA技术适合在哪儿用呢Q?BR>Java technology and AJAX work well together. Java technology provides the server-side processing for AJAX interactions. It can provide this through servlets, JavaServer Pages (JSP) technology, JavaServer Faces (JSF) technology, and web services. The programming model for handling AJAX requests uses the same APIs that you would use for conventional web applications. JSF technology can be used to create reusable components that generate the client-side JavaScript and corresponding server-side AJAX processing code. Let's look at an example that uses AJAX and servlets.
JAVA技术与AJAX搭配使用非常不错。JAVA技术ؓ(f)AJAX交互提供服务器端处理Q通过servlets、JavaServer Pages (JSP)、JavaServer Faces (JSF) ?qing)web服务。AJAXh的编E模式用与常规WEB应用相同的API。JSF技术可以用来创建可重用的组Ӟq些lg生成客户端JSq与服务器端AJAX处理代码通信。下面让我们来看一个用AJAX和SERVLETS的例子?BR>Autocomplete Example
实例Q自动完?BR>Imagine a web page in which a user can search for information about an employee. The page includes a field where the user can enter the name of the employee. In this example the entry field has an autocomplete feature. In other words, the user can type in part of the employee name, and the web application attempts to complete the name by listing all employees whose first or last name begins with the characters entered. The autocomplete feature saves the user from having to remember the complete name of the employee or from looking for the name on another page.
假设用户在一个网中搜烦雇员信息。这个页面包含一个输入域Q用户在其中输入雇员的名字。在q个例子中输入域h自动完成的功能。换句话_(d)用户输入雇员名的一部分QW(xu)EB应用通过列出所有姓名以输入字母开头的雇员来帮助完成输入。自动完成功能让用户可以无需C员工的全名或者从另一个页面查扑֐字。(此句偶之前百思不得其解,后来l永华指点,大约是这L(fng)Q你可以有三U方式查询员工信息,1.C员工的名字?.从别的地方,比如其它面扑ֈ后复制粘贴过来,3.使用自动完成功能Q很昄Q第三种是最省事的,优于其它方式Q所以说3 SAVE FROM 1/2.Q?/P>


Implementing autocomplete in a search field is something that can be performed using AJAX. To do it, you need to provide code on the client and on the server.
可以使用AJAX实现搜烦输入域的自动完成。要实现q个Q需要撰写相应的客户端和服务器端代码?/P>

On the Client
客户?BR>First, the user specifies the URL of a page that is loaded by the browser. For this example let's assume the page is an HTML page that is generated by a JSF component, servlet, or JSP page. The page contains a form text field that has an attribute onkeyup with the name of a JavaScript function doCompletion(). This function is called each time a key is pressed in the form text field.
首先Q用h开一个网c(din)假设这个页面是一个由JSFlg、SERVLET或JSP产生的HTML面。页面中包含一个表单文本域Q它有一个ONKEYUP属性,其gؓ(f)一个JS函数doCompletion()。这个每当文本域有输入改变,q个函数׃(x)被调用?BR>    <input type="text"
          size="20"
          autocomplete="off"
          id="complete-field"
                      name="id"
          onkeyup="doCompletion();">

Let's assume that a user types in an "M" character in the form text field. In response, the doCompletion() function is called which, in turn, initializes an XMLHttpRequest object:
假设用户在表单文本域输入字母MQdoCompletion()被调用Q初始化一个XMLHttpRequest对象?BR>   function initRequest(url) {
       if (window.XMLHttpRequest) {
           return new XMLHttpRequest();
       } else if (window.ActiveXObject) {
           isIE = true;
           return new ActiveXObject("Microsoft.XMLHTTP");
       }
   }

   function doCompletion() {
       if (completeField.value == "") {
           clearTable();
       } else {
           var url = "autocomplete?action=complete&id=" +
                   escape(completeField.value);
           var req = initRequest(url);
           req.onreadystatechange = function() {
               if (req.readyState == 4) {
                   if (req.status == 200) {
                       parseMessages(req.responseXML);
                   } else if (req.status == 204){
                       clearTable();
                   }
               }
           };
           req.open("GET", url, true);
           req.send(null);
       }
   }

The XMLHttpRequest object is not currently part of standard JavaScript (efforts are underway to standardize it), but is a de facto standard and is the heart of AJAX. This object is responsible for interacting over HTTP with a server-side component (in this case, a servlet).
XMLHttpRequest对象现在q不是JS标准中的一部分Q正在努力将其标准化Q,但它却是事实上的标准q且是AJAX的核心。这个对象对于在HTTP协议上与服务器端lgQ此例中是一个SERVLETQ交互很可靠.

Three parameters are specified when you create an XMLHttpRequest object: a URL, the HTTP method (GET or POST), and whether or not the interaction is asynchronous. In the XMLHttpRequest example, the parameters are:
当创建XMLHttpRequest对象旉指定三个参数Q一个URL,HTTP方式QGET或POSTQ? 交互是否异步。在q个XMLHttpRequest 例子中,q些参数如下Q?BR>    * The URL autocomplete, and the text from the complete-field (an M character):
*自动完成的URL和从输入域键入的文字Q?BR>     var url = "autocomplete?action=complete&id=" +
             escape(completeField.value);

    * GET, signifying the HTTP interactions uses the GET method, and true, signifying that the interaction is asynchronous:
*GETQ表CHTTP交互使用GETҎ(gu)QTRUEQ表CZ互是异步的:(x)
     req.open("GET", url, true);

A callback function needs to be set when you use asynchronous calls. This callback function is called asynchronously at specific points during HTTP interaction when the readyState property on the XMLHttpRequest changes. In the example the callback function is processRequest(). It's set as the XMLHttpRequest.onreadystatechange property to a function. Notice the call to the parseMessages function when the readState is "4". The XMLHttpRequest.readyState of "4" signifies the successful completion of the HTTP interaction.
当用异步调用时Q需要徏立一个回调函数。HTTP交互中当XMLHttpRequest中的readyState属性改变时Q回调函数被异步调用。此例中回调函数是processRequest()。它Z个函数徏立了一个XMLHttpRequest.onreadystatechange属性。(前两句还不太明白什么意思——译者注Q。注意当readyState?时对parseMessages函数的调用。XMLHttpRequest.readyState?意味着HTTP交互的成功完成?BR>The HTTP interaction begins when XMLHttpRequest.send() is called. If the interaction is asynchronous, the browser continues to process events in the page.
HTTP交互以调用XMLHttpRequest.send()开始。如果交互是异步的,览器前l箋执行面事gQ而不是中断用户当前动作去执行交互动作——译者注Q?BR>On the Server
服务器端
The XMLHttpRequest makes an HTTP GET request to the URL autocomplete, which is mapped to a servlet called AutoComplete. The doGet() method of the AutoComplete servlet is called. Here is what the doGet() method looks like:
XMLHttpRequest动完成的URL产生了一个HTTP GEThQ这个URL被映到一个名为AutoComplete的Servlet上。AutoComplete servlet的doGet() Ҏ(gu)被调用。这里的doGet()Ҏ(gu)如下Q?BR>   public void doGet(HttpServletRequest request,
           HttpServletResponse response)
        throws IOException, ServletException {
       ...
       String targetId = request.getParameter("id");
       Iterator it = employees.keySet().iterator();
       while (it.hasNext()) {
           EmployeeBean e = (EmployeeBean)employees.get(
                   (String)it.next());
           if ((e.getFirstName().toLowerCase().startsWith(targetId) ||
              e.getLastName().toLowerCase().startsWith(targetId))
              && !targetId.equals("")) {
              sb.append("<employee>");
              sb.append("<id>" + e.getId() + "</id>");
              sb.append("<firstName>" + e.getFirstName() +
                      "</firstName>");
              sb.append("<lastName>" + e.getLastName() +
                      "</lastName>");
              sb.append("</employee>");
              namesAdded = true;
           }
       }
       if (namesAdded) {
           response.setContentType("text/xml");
           response.setHeader("Cache-Control", "no-cache");
           response.getWriter().write("<employees>" +
                   sb.toString() + "</employees>");
       } else {
           response.setStatus(HttpServletResponse.SC_NO_CONTENT);
       }
    }

As you can see in this servlet, there is nothing really new you need to learn to write server-side code for AJAX processing. The response content type needs to be set to text/xml for cases where you want to exchange XML documents. With AJAX, you can also exchange plain text or even snippets of JavaScript which may be evaluated or executed by the callback function on the client. Note too that some browsers might cache the results, and so it might be necessary to set the Cache-Control HTTP header to no-cache. In this example, the servlet generates an XML document that contains all employees with a first or last name beginning with the character M. Here is an example of an XML document that is returned to the XMLHttpRequest object that made the call:
如你在SERVLET中所看到Q不需要ؓ(f)写服务器端AJAX处理代码而学?fn)新知识。当你想要发送XML文档Q只需响应内容类型设|ؓ(f)text/xml。用AJAXQ你甚至可以发送普通文本或者小DJS代码Q这些代码可能在客户端被回调函数计算或执行。注意:(x)一些浏览器可能结果缓存,所以有必要讄Cache-Control HTTP header为no-cache。此例中QSERVLET产生一个XML文档Q它包含所有姓或名以M开头的雇员的姓名。下面是一个返回给XMLHttpRequest对象的XML文档例子Q?BR>   <employees>
      <employee>
        <id>3</id>
        <firstName>George</firstName>
        <lastName>Murphy</lastName>
      </employee>
      <employee>
        <id>2</id>
        <firstName>Greg</firstName>
        <lastName>Murphy</lastName>
      </employee>
      <employee>
        <id>11</id><firstName>Cindy</firstName>
        <lastName>Murphy</lastName>
        </employee>
      <employee>
        <id>4</id>
        <firstName>George</firstName>
        <lastName>Murray</lastName>
      </employee>
      <employee>
        <id>1</id>
        <firstName>Greg</firstName>
        <lastName>Murray</lastName>
     </employee>
   </employees>
Returning to the Client
再来看客L(fng)
When the XMLHttpRequest object that made the initial call receives the response, it calls the parseMessages() function (see the initialization of the XMLHttpRequest earlier in this example for more details). Here is what the parseMessages() function looks like:
当最初发送请求的XMLHttpRequest对象收到回应Q它调用parseMessages() 函数Q参见此例前面XMLHttpRequest的初始化Q。这个函数如下:(x)
   function parseMessages(responseXML) {
       clearTable();
           var employees = responseXML.getElementsByTagName(
                   "employees")[0];
       if (employees.childNodes.length > 0) {
           completeTable.setAttribute("bordercolor", "black");
           completeTable.setAttribute("border", "1");
       } else {
           clearTable();
       }
   
       for (loop = 0; loop < employees.childNodes.length; loop++) {
           var employee = employees.childNodes[loop];
           var firstName = employee.getElementsByTagName(
                   "firstName")[0];
           var lastName = employee.getElementsByTagName(
                   "lastName")[0];
           var employeeId = employee.getElementsByTagName(
                   "id")[0];
           appendEmployee(
                   firstName.childNodes[0].nodeValue,
                   lastName.childNodes[0].nodeValue,
                   employeeId.childNodes[0].nodeValue);
       }
   }

The parseMessages() function receives as a parameter an object representation of the XML document returned by the AutoComplete servlet. The function programmatically traverses the XML document, and then uses the results to update the contents of the HTML page. This is done by injecting into a <div> element whose id is "menu-popup" the HTML source for the names in the XML document:
parseMessages() 函数接收AutoComplete servletq回的XML文档对象做ؓ(f)参数。该函数自动转化XML文档q更新网内容,通过在HTML源文件中为XML文档中的姓名插入一?id ?"menu-popup"的DIV元素Q?BR>   <div style="position: absolute;
      top:170px;left:140px" id="menu-popup">

As the user enters more characters, the list shortens. The user can then click on one of the names.
当用戯入更多字W,姓名列表变短。用户可以点击要查找的姓名?BR>Hopefully by now you realize that AJAX is simply exchanging information over HTTP in the background of a page, and updating that page dynamically based on the results. For more information about AJAX and Java technology, see the technical article Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform, Enterprise Edition. Q?A >http://java.sun.com/developer/technicalArticles/J2EE/AJAX/index.htmlQAlso see the AJAX BluePrints page, Q?A >http://java.sun.com/blueprints/ajax.htmlQand the AJAX FAQ for the Java Developer in Greg Murray's blog. Q?A >http://weblogs.java.net/blog/gmurray71/Q?BR>希望现在你已l了解到AJAX如何在后台简单地交换信息以及(qing)在此基础上动态地更新面。欲了解更多关于AJAX和JAVA技术,可以看这技术文章《Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform, Enterprise Edition》(http://java.sun.com/developer/technicalArticles/J2EE/AJAX/index.htmlQ。或者看AJAX蓝图http://java.sun.com/blueprints/ajax.htmlQ或Greg Murray的博客中为JAVA开发者写的AJAX FAQ?A >http://weblogs.java.net/blog/gmurray71/
About the Author
关于作?BR>Greg Murray is the servlet specification lead. Greg is a former member of the Java BluePrints team, and was responsible for the web tier recommendations. He is leading the AJAX effort at Sun with the help of the BluePrints team. Greg has experience with internationalization, web services, J2SE standalone clients, and AJAX-based web clients.
格雷|默里是SERVLET规范领导。他曾是JAVA蓝图工作l会(x)员,非常负责地对WEB TIER提出许多(或者是对XX负责)。在蓝图工作l的协助下他在SUN领导AJAX工作。格h在国际化、WEB服务、J2SE独立客户端和ZAJAX的WEB客户端方面有着丰富的经验?/P>

About the Translater
关于译?BR>Ahdong is wide-interested boy in China.Ahdong is a member of Network Creative Lab of Huaqiao University,and is  responsible for the newbees' recommendations about learning.He is leading the software department at the lab with Younghua.Ahdong is interested in and has some experience with Linux,web development with JAVA or PHP,web standard,and AJAX-based web clients.
阿冬是一个兴广泛的中国男孩。他是华侨大学网l创新实验室的一员,负责d对许多初学者提了许多中肯的。他和永华一起领导实验室软g部。阿冬在LINUX、PHP或JAVA WEB开发、WEB标准、基于AJAX的WEB客户端方面有着深厚的兴ƈ多少有一点儿l验?BR>



Victor 2005-12-30 14:43 发表评论
]]>
Java更新XML的四U常用方法简?/title><link>http://www.tkk7.com/Victor/articles/23756.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Wed, 14 Dec 2005 01:02:00 GMT</pubDate><guid>http://www.tkk7.com/Victor/articles/23756.html</guid><wfw:comment>http://www.tkk7.com/Victor/comments/23756.html</wfw:comment><comments>http://www.tkk7.com/Victor/articles/23756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/Victor/comments/commentRss/23756.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/Victor/services/trackbacks/23756.html</trackback:ping><description><![CDATA[<div id="nhuxspr" class=comText><FONT size=3>本文要的讨论了Java语言~程中更新XML文档的四U常用方?q且分析q四U方法的优劣。其?本文q对如何控制JavaE序输出的XML文档的格式做了展开?BR><BR>  JAXP是Java API for XML Processing的英文字头羃?中文含义?用于XML文档处理的用Java语言~写的编E接口。JAXP支持DOM、SAX、XSLT{标准。ؓ(f)了增强JAXP使用上的灉|?开发者特别ؓ(f)JAXP设计了一个Pluggability Layer,在Pluggability Layer的支持之?JAXP既可以和具体实现DOM API、SAX API 的各UXML解析?XML Parser,例如Apache Xerces)联合工作,又可以和具体执行XSLT标准的XSLT处理?XSLT Processor,例如Apache Xalan)联合工作。应用Pluggability Layer的好处在?我们只需要熟(zhn)JAXP各个~程接口的定义即?而不需要对所采用的具体的XML解析器、XSLT处理器有很深入的了解。比如在某个JavaE序?通过JAXP调用XML解析器Apache Crimson对XML文档q行处理,如果我们希望使用别的XML解析?比如Apache Xerces),以便提高该程序的性能,那么原程序代码可能不需要Q何改?直接可以?你所需要做的事情只是将包含Apache Xerces代码的jar文g加入到环境变量CLASSPATH?而将包含Apache Crimson代码的jar文g在环境变量CLASSPATH中删??<BR><BR>  目前JAXP已经应用的十分普遍了,可以说是Java语言中处理XML文档的标准API。有些初学者在学习(fn)使用JAXP的过E中,l常?x)提L(fng)问题:我编写的E序对DOM Tree做了更新,但是当程序退Z?原始的XML文档q没有改?q是老样?如何实现对原始XML文档和DOM Tree的同步更新呢?咋一看来,在JAXP中似乎没有提供相应的接口/Ҏ(gu)/c?q是很多初学者都感到困惑的问题。本文的L在于解册个问?单的介绍几种常用的同步更新原始XML文档和DOM Tree的方法。ؓ(f)了羃?yu)讨论的范?本文所涉及(qing)的XML解析器仅包括Apache Crimson和Apache Xerces,而XSLT处理器仅仅用Apache Xalan?<BR><BR>  Ҏ(gu)一:直接dXML文档 <BR><BR>  q也许是最W最原始的办法了。当E序获取DOM Tree之后,应用DOM模型的Node接口的各个方法对DOM Treeq行更新,下一步应该对原始的XML文档q行更新了。我们可以运用递归的办法或者是应用TreeWalkerc?遍历整个DOM Tree,与此同时,DOM Tree的每一个节?元素依次写入到预先打开的原始XML文档?当DOM Tree被遍历完全之?DOM Tree和原始的XML文档实C同步更新。实际中,q个Ҏ(gu)极少使用,不过如果你要~程实现自己的XML解析?q种Ҏ(gu)q是有可能用得上的?BR><BR>Ҏ(gu)?使用XmlDocumentc?<BR><BR>  使用XmlDocumentc?JAXP中分明没有这个类呀!是不是作者搞错了?没有?是使用XmlDocumentc?切的说,是用XmlDocumentcȝwrite()Ҏ(gu)?<BR><BR>  在上文已l提到过,JAXP可以和各U各L(fng)XML解析器联合?q次我们选用的XML解析器是Apache Crimson。XmlDocument(org.apache.crimson.tree.XmlDocument)是Apache Crimson的一个类,q不包含于标准的JAXP?难怪在JAXP的文档中找不到XmlDocumentcȝ芌呢。现在问题出来了,如何应用XmlDocumentcL实现更新XML文档的功?在XmlDocumentcM提供了下面三个write()Ҏ(gu)(Ҏ(gu)Crimson最新的版本------Apache Crimson 1.1.3): <BR><BR></FONT><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD><FONT size=3>public void write (OutputStream out) throws IOException<BR>public void write (Writer out) throws IOException<BR>public void write (Writer out, String encoding) throws IOException</FONT></TD></TR></TBODY></TABLE><BR>  上述三个write()Ҏ(gu)的主要作用就是输出DOM Tree中的内容到特定的输出介质?比如文g输出、应用程序控制台{等。那么又如何使用上述三个write()Ҏ(gu)?L(fng)下面的JavaE序代码片断: <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>String name="fancy";<BR>DocumentBuilder parser;<BR>DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();<BR>try <BR>{<BR>parser = factory.newDocumentBuilder();<BR>Document doc = parser.parse("user.xml");<BR>Element newlink=doc.createElement(name);<BR>doc.getDocumentElement().appendChild(newlink);<BR>((XmlDocument)doc).write(new FileOutputStream(new File("xuser1.xml")));<BR>}<BR>catch (Exception e) <BR>{<BR>//to log it <BR>}</TD></TR></TBODY></TABLE><BR>  在上面的代码?首先创徏了一个Document对象doc,获取完整的DOM Tree,然后应用Node接口的appendChild()Ҏ(gu),在DOM Tree的最后追加了一个新节点(fancy),最后调用XmlDocumentcȝwrite(OutputStream out)Ҏ(gu),把DOM Tree中的内容输出到xuser.xml?其实也可以输出到user.xml,更新原始的XML文档,在这里ؓ(f)了便于做Ҏ(gu),故而输出到xuser.xml文g?。需要注意的是不能直接对Document对象doc直接调用write()Ҏ(gu),因ؓ(f)JAXP的Document接口q没有定义Q何write()Ҏ(gu),所以必ddoc由Document对象强制转换为XmlDocument对象,然后才能调用write()Ҏ(gu),在上面的代码中用的是write(OutputStream out)Ҏ(gu),q个Ҏ(gu)使用~省的UTF-8~码输出DOM Tree中的内容到特定的输出介质?如果DOM Tree中包含中文字W?那么输出的结果有可能是ؕ?亦即存在所谓的"汉字问题",解决的办法是使用write (Writer out, String encoding)Ҏ(gu),昑ּ指定输出时的~码,例如第二个参数设ؓ(f)"GB2312",q时即不存在"汉字问题",输出l果能够正常昄中文字符?<BR><BR>  完整的例子请参考下列文? AddRecord.java(见附?、user.xml(见附?。该例子的运行环境ؓ(f):Windows XP Professional、JDK 1.3.1。ؓ(f)了能够正常编译运行AddRecord.javaq个E序,你需要到|址<A target=_blank>http://xml.apache.org/dist/crimson/M载Apache</A> Crimson,q将所获取的crimson.jar文g加入到环境变量CLASSPATH中?<BR><BR>  注意: <BR><BR>  Apache Crimson的前w是Sun Project X Parser,后来不知何故,由X Parser演变为Apache Crimson,至今Apache Crimson的很多代码都是从X Parser中直接移植过来的。比如上文用到的XmlDocumentc?它在X Parser中是com.sun.xml.XmlDocument,CApache Crimson中摇w一?变成了org.apache.crimson.tree.XmlDocumentc?其实它们的绝大部分代码是一L(fng),可能package语句和import语句以及(qing)文g开头的一Dlience有所不同而已。早期的JAXP是和X Parser捆绑在一L(fng),因此一些老的E序使用了com.sun.xml?如果你现在重新编译它?有可能不能通过,肯定是因ؓ(f)q个原因。后来的JAXP和Apache Crimson捆绑在一?比如JAXP 1.1,如果你用JAXP 1.1,那么不需要额外下载Apache Crimson,也能够正常编译运行上面的例子(AddRecord.java)。最新的JAXP 1.2 EA(Early Access)改u更张,采用性能更好的Apache Xalan和Apache Xerces分别作ؓ(f)XSLT处理器和XML解析?不能直接支持Apache Crimson?所以如果你的开发环境采用了JAXP 1.2 EA或者是Java XML Pack(内含JAXP 1.2 EA),那么无法直接编译运行上面的例子(AddRecord.java),你需要额外下载ƈ安装Apache Crimson?nbsp;<BR><BR>Ҏ(gu)?使用TransformerFactory和Transformerc?<BR><BR>  在JAXP中所提供的标准的更新原始XML文档的方法就是调用XSLT引擎,亦即使用TransformerFactory和TransformercR请看下面的Java代码片断: <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>//首先创徏一个DOMSource对象,该构造函数的参数可以是一个Document对象<BR>//doc代表更改后的DOM Tree?BR>DOMSource doms = new DOMSource (doc);<BR><BR>//创徏一个File对象,代表DOM Tree所包含的数据的输出介质,q是一个XML文g?BR>File f = new File ("XMLOutput.xml");<BR><BR>//创徏一个StreamResult对象,该构造函数的参数可以取ؓ(f)File对象?BR>StreamResult sr = new StreamResult (f);<BR><BR>//下面调用JAXP中的XSLT引擎来实现输出DOM Tree中的数据到XML文g中的功能?BR>//XSLT引擎的输入ؓ(f)DOMSource对象,输出为StreamResut对象?BR>try <BR>{<BR>//首先创徏一个TransformerFactory对象,再由此创建Transformer对象。Transformer<BR>//cȝ当于一个XSLT引擎。通常我们使用它来处理XSL文g,但是在这里我们<BR>//用它来输出XML文档?BR>TransformerFactory tf=TransformerFactory.newInstance(); <BR>Transformer t=tf.newTransformer ();<BR><BR>//关键的一? 调用Transformer对象 (XSLT引擎)的transform()Ҏ(gu),该方法的W一<BR>//个参数是DOMSource对象,W二个参数是StreamResult对象?BR>t.transform(doms,sr); <BR>}<BR>catch (TransformerConfigurationException tce)<BR>{ <BR>System.out.println("Transformer Configuration Exception\n-----");<BR>tce.printStackTrace(); <BR>}<BR>catch (TransformerException te) <BR>{ <BR>System.out.println ("Transformer Exception\n---------"); <BR>te.printStackTrace (); <BR>} </TD></TR></TBODY></TABLE><BR>  在实际的应用?我们可以应用传统的DOM API从XML文档中获取DOM Tree,然后Ҏ(gu)实际的需求对DOM Tree执行各种操作,得到最l的Document对象,接下来可以由此Document对象创徏DOMSource对象,剩下的事情就是照搬上面的代码?E序q行完毕? XMLOutput.xml是你所需要的l果(当然?你可以随意更改StreamResultcL造函数的参数,指定不同的输Z?而不必是千篇一律的XML文档)?<BR><BR>  q个Ҏ(gu)最大的好处在于可以随心所Ʋ的控制DOM Tree中的内容输出到输Z质中的格?但是光靠TransformerFactorycdTransformercdƈ不能实现q个功能,q需要依赖OutputKeyscȝ帮助?完整的例子请参考下列文? AddRecord2.java(见附?、user.xml(见附?。该例子的运行环境ؓ(f):Windows XP Professional、JDK 1.3.1。ؓ(f)了能够正常编译运行AddRecord2.javaq个E序,你需要到|址<A target=_blank>http://java.sun.comM载安装JAXP</A> 1.1或者Java XML Pack(Java XML Pack已经内含JAXP??<BR><BR>  OutputKeysc?<BR><BR>  javax.xml.transform.OutputKeyscdjava.util.Propertiesc配合?可以控制JAXP的XSLT引擎(Transformerc?输出XML文档的格式。请看下面的代码片断: <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>//首先创徏一个TransformerFactory对象,再由此创建Transformer对象?BR>TransformerFactory tf=TransformerFactory.newInstance(); <BR>Transformer t=tf.newTransformer ();<BR><BR>//获取Transformser对象的输出属?亦即XSLT引擎的缺省输出属?q是一?BR>//java.util.Properties对象?BR>Properties properties = t.getOutputProperties(); <BR><BR>//讄新的输出属?输出字符~码为GB2312,q样可以支持中文字符,XSLT引擎所输出<BR>//的XML文档如果包含了中文字W?可以正常昄,不会(x)出现所谓的"汉字问题"?BR>//L(fng)意OutputKeyscȝ字符串常数OutputKeys.ENCODING?BR>properties.setProperty(OutputKeys.ENCODING,"GB2312"); <BR><BR>/更新XSLT引擎的输出属性?BR>t.setOutputProperties(properties); <BR><BR>//调用XSLT引擎,按照输出属性中的设|?输出DOM Tree中的内容到输Z质中?BR>t.transform(DOMSource_Object,StreamResult_Object); </TD></TR></TBODY></TABLE><BR>  从上面的E序代码,我们不难看出,通过讄XSLT引擎(Transformerc?的输出属?可以控制DOM Tree中的内容的输出格?q对于我们定制输出内Ҏ(gu)很有帮助的。那么JAXP的XSLT引擎(Transformerc?有那些输出属性可以设|呢? javax.xml.transform.OutputKeyscd义了很多字符串常?它们都是可以自由讄的输出属?常用的输出属性如下所C? <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String METHOD </TD></TR></TBODY></TABLE><BR>  可以设ؓ(f)"xml"?html"?text"{倹{?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String VERSION</TD></TR></TBODY></TABLE><BR>  所遵@规范的版本号,如果METHOD设ؓ(f)"xml",那么它的值应该设?1.0",如果METHOD设ؓ(f)"html",那么它的值应该设?4.0",如果METHOD设ؓ(f)"text",那么q个输出属性会(x)被忽略?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String ENCODING </TD></TR></TBODY></TABLE><BR>  讄输出时所采用的编码方?比如"GB2312"?UTF-8"{等,如果其讄?GB2312",可以解决所谓的"汉字问题"?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String OMIT_XML_DECLARATION</TD></TR></TBODY></TABLE><BR>  讄输出到XML文档中时是否忽略XML声明,亦即cM? <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>Q?xml version="1.0" standalone="yes" encoding="utf-8" ?Q?</TD></TR></TBODY></TABLE><BR>  q样的代码。它可选的值有"yes"?no"?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String INDENT</TD></TR></TBODY></TABLE><BR>  IDENT讑֮XSLT引擎在输出XML文档?是否自动d额外的空?它可选的gؓ(f)"yes"?no"?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>public static final java.lang.String MEDIA_TYPE </TD></TR></TBODY></TABLE><BR>  MEDIA_TYPE讑֮输出文档的MIMEcd?<BR><BR>  如果讑֮XSLT引擎的输出属性呢?下面我们来ȝ一? <BR><BR>  首先是获取XSLT引擎(Transformerc?的缺省输出属性的集合,q需要用TransformercȝgetOutputProperties()Ҏ(gu),q回值是一个java.util.Properties对象?<BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>Properties properties = transformer.getOutputProperties();</TD></TR></TBODY></TABLE><BR>  然后是设定新的输出属?比如: <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>properties.setProperty(OutputKeys.ENCODING,"GB2312");<BR>properties.setProperty(OutputKeys.METHOD,"html");<BR>properties.setProperty(OutputKeys.VERSION,"4.0");<BR>……………………………………………………?</TD></TR></TBODY></TABLE><BR>  最后是更新XSLT引擎(Transformerc?的缺省输出属性的集合,q需要用TransformercȝsetOutputProperties()Ҏ(gu),参数是一个java.util.Properties对象?<BR><BR>  我们~写了一个新的程?其中应用了OutputKeysc?用以控制XSLT引擎的输出属?该程序的架构和前一个程?AddRecord3.java)大致相同,不过输出l果略有不同。完整的代码请参考下列文? AddRecord3.java(见附?、user.xml(见附?。该例子的运行环境ؓ(f):Windows XP Professional、JDK 1.3.1。ؓ(f)了能够正常编译运行AddRecord3.javaq个E序,你需要到|址<A target=_blank>http://java.sun.comM载安装JAXP</A> 1.1或者Java XML Pack(Java XML Pack内含JAXP??nbsp;<BR><BR>Ҏ(gu)?使用Xalan XML Serializer <BR><BR>  Ҏ(gu)四其实是Ҏ(gu)三的一个变U?它需要Apache Xalan和Apache Xerces的支持才能够q行。例子代码如下所C? <BR><BR><BR> <TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1><BR> <TBODY><BR> <TR><BR> <TD>//首先创徏一个DOMSource对象,该构造函数的参数可以是一个Document对象<BR>//doc代表更改后的DOM Tree?BR>DOMSource domSource = new DOMSource (doc); <BR><BR>//创徏一个DOMResult对象,临时保存XSLT引擎的输出结果?BR>DOMResult domResult = new DOMResult();<BR><BR>//下面调用JAXP中的XSLT引擎来实现输出DOM Tree中的数据到XML文g中的功能?BR>//XSLT引擎的输入ؓ(f)DOMSource对象,输出为DOMResut对象?BR>try <BR>{<BR>//首先创徏一个TransformerFactory对象,再由此创建Transformer对象。Transformer<BR>//cȝ当于一个XSLT引擎。通常我们使用它来处理XSL文g,但是在这里我们<BR>//用它来输出XML文档?BR>TransformerFactory tf=TransformerFactory.newInstance(); <BR>Transformer t=tf.newTransformer (); <BR><BR>//讄XSLT引擎的属?必不可少,否则?x)?汉字问题")?BR>Properties properties = t.getOutputProperties(); <BR>properties.setProperty(OutputKeys.ENCODING,"GB2312");<BR>t.setOutputProperties(properties); <BR><BR>//关键的一? 调用Transformer对象 (XSLT引擎)的transform()Ҏ(gu),该方法的W一<BR>//个参数是DOMSource对象,W二个参数是DOMResult对象?BR>t.transform(domSource,domResult);<BR><BR>//创徏~省的Xalan XML Serializer,使用它将临时存放在DOMResult对象<BR>//(domResult)中的内容以输出流的Ş式输出到输出介质中?BR>Serializer serializer = SerializerFactory.getSerializer<BR>(OutputProperties.getDefaultMethodProperties("xml"));<BR><BR>//讄Xalan XML Serializer的输出属?q一步必不可?否则也可能?BR>//所谓的"汉字问题"?BR>Properties prop=serializer.getOutputFormat();<BR>prop.setProperty("encoding","GB2312");<BR>serializer.setOutputFormat(prop);<BR><BR>//创徏一个File对象,代表DOM Tree所包含的数据的输出介质,q是一个XML文g?BR>File f = new File ("xuser3.xml");<BR><BR>//创徏文g输出对象fos,L(fng)意构造函数的参数?BR>FileOutputStream fos=new FileOutputStream(f);<BR><BR>//讄Xalan XML Serializer的输出流?BR>serializer.setOutputStream(fos);<BR><BR>//串行化输出结果?BR>serializer.asDOMSerializer().serialize(domResult.getNode());<BR>}<BR>catch (Exception tce)<BR>{ <BR>tce.printStackTrace(); <BR>}</TD></TR></TBODY></TABLE><BR>  q个Ҏ(gu)不太常用,而且g有点画蛇添,所以我们就不展开讨论了。完整的例子请参考下列文? AddRecord4.java(见附?、user.xml(见附?。该例子的运行环境ؓ(f):Windows XP Professional、JDK 1.3.1。ؓ(f)了能够正常编译运行AddRecord4.javaq个E序,你需要到|址<A target=_blank>http://xml.apache.org/dist/M载安装Apache</A> Xalan和Apache Xerces?<BR><BR>  或者是到网址<A target=_blank>http://java.sun.com/xml/download.htmlM载安装Java</A> XML Pack。因为最新的Java XML Pack(Winter 01 ?包含了Apache Xalan和Apache Xerces技术在内?<BR><BR>  l论: <BR><BR>  本文略的讨论了Java语言~程中更新XML文档的四U方法。第一U方法是直接dXML文g,q种Ҏ(gu)十分J琐,而且比较Ҏ(gu)出错,极少使用,除非你需要开发自qXML Parser,否则不会(x)使用q种Ҏ(gu)。第二种Ҏ(gu)是用Apache Crimson的XmlDocumentc?q种Ҏ(gu)极ؓ(f)?使用方便,如果你选用Apache Crimson作ؓ(f)XML解析?那么不妨使用q种Ҏ(gu),不过q种Ҏ(gu)g效率不高(源于效率低下的Apache Crimson),另外,高版本的JAXP或者是Java XML Pack、JWSDP不直接支持Apache Crimson,亦即q种Ҏ(gu)不通用。第三种Ҏ(gu)是用JAXP的XSLT引擎(Transformerc?来输出XML文档,q种Ҏ(gu)也许是标准的Ҏ(gu)?使用h十分灉|,特别是可以自如控制输出格?我们推荐采用q种Ҏ(gu)。第四种Ҏ(gu)是第三种Ҏ(gu)的变U?采用了Xalan XML Serializer,引入了串行化操作,对于大量文档的修?输出有优?可惜的是要重复设|XSLT引擎的属性和XML Serializer的输出属?比较ȝ,而且依赖于Apache Xalan和Apache Xerces技?通用性略显不?<BR><BR>  除了上面讨论的四U方法以?实际上应用别的API(比如JDOM、Castor、XML4J、Oracle XML Parser V2)也有很多办法可以更新XML文档,限于幅,在这里就不一一讨论了?nbsp; </FONT></DIV><img src ="http://www.tkk7.com/Victor/aggbug/23756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/Victor/" target="_blank">Victor</a> 2005-12-14 09:02 <a href="http://www.tkk7.com/Victor/articles/23756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用struts+spring+hibernatel装你的web应用架构http://www.tkk7.com/Victor/articles/22589.htmlVictorVictorMon, 05 Dec 2005 07:26:00 GMThttp://www.tkk7.com/Victor/articles/22589.htmlhttp://www.tkk7.com/Victor/comments/22589.htmlhttp://www.tkk7.com/Victor/articles/22589.html#Feedback0http://www.tkk7.com/Victor/comments/commentRss/22589.htmlhttp://www.tkk7.com/Victor/services/trackbacks/22589.html
      构架一个Web应用需要弄明白好多问题?q运的是Q已l有不少开发者已l遇到过q类问题Qƈ且徏立了处理q类问题的框架?一个好框架具备以下几点Q?减轻开发者处理复杂的问题的负担("不重复发明轮?Q; 内部有良好的扩展Q?q且有一个支持它的强大的用户团体?好的构架一般有针对性的处理某一c问题,q且能将它做好(Do One Thing wellQ?然而,你的E序中有几个层可能需要用特定的框架Q已l完成的UI(用户接口) q不代表你也可以把你的业务逻辑和持久逻辑偶合C的UI部分?举个例子Q?你不该在一个Controller(控制?里面写JDBC代码作ؓ(f)你的业务逻辑Q?q不是控制器应该提供的?一个UI 控制器应该委z其它l在UI范围之外的轻量lg?好的框架应该能指g码如何分布?更重要的是,框架能把开发者从~码中解攑և来,使他们能专心于应用程序的逻辑Q这对客h说很重要Q?

      q篇文章讨论怎样l合几种著名的框架来使得你的应用E序做到村ּ耦合?
如何建立你的架构Qƈ且怎样让你的各个应用层保持一致。?如何整合框架以便让每个层在以一U松散偶合的方式彼此作用而不用管低层的技术细节?q对我们来说真是一U挑战?q里讨论一个整合框架的{略( 使用3 U受Ƣ迎的开源框? Q表C层我们用StrutsQ?业务层我们用SpringQ而持久层则用Hibernate?你也可以用其他FrameWork替换只要能得到同L(fng)效果?见图1 Q框架组合示意图Q?



应用E序的分?/SPAN>

大部分的Web应用在职责上臛_能被分成4层?q四层是QpresentationQ描qͼQpersistenceQ持久)QbusinessQ业务)和domain modelQ域模块Q。每个层在处理程序上都应该有一Ҏ(gu)的责Q, 而不应该在功能上与其它层混合Qƈ且每个层要与其它层分开的,但要l他们之间放一个通信接口?我们׃介绍各个层开始,讨论一下这些层应该提供什么,不应该提供什么?



表示?The Presentation Layer)

一般来Ԍ一个典型的Web应用的的末端应该是表C层?很多Java发者也理解Struts所提供的?象业务逻辑之类的被打包到org.apache.struts.Action.Q?因此Q我们很赞成使用Strutsq样的框架?



下面是Struts所负责的:(x)

* 理用户的请?做出相应的响应?

* 提供一个Controller ,委派调用业务逻辑和其它上层处理?

* 处理异常Q抛lStruts Action

* 为显C提供一个模?

* UI验证?



以下条款Q不该在Struts昄层的~码中经常出现?它们与显C层无关的?

* 直接的与数据库通信Q例如JDBC调用?

* 与你应用E序相关联的业务逻辑以及(qing)校验?

* 事物理?

在表C层引入q些代码Q则?x)带来高偶合和麻烦的l护?





持久?The Persistence Layer)

典型的Web应用的另一个末端是持久层。这里通常是程序最Ҏ(gu)失控的地斏V开发者L低估构徏他们自己的持久框架的挑战性。系l内部的持箋层不但需要大量调试时_(d)而且q经常缺功能之变得难以控Ӟq是持久层的通病?q好有几个ORM开源框架很好的解决了这c问题。尤其是Hibernate?Hibernate为java提供了OR持久化机制和查询服务, 它还l已l熟(zhn)SQL和JDBC API 的Java开发者一个学?fn)桥梁,他们学?fn)h很方ѝ?Hibernate的持久对象是ZPOJO和Java collections。此外,使用Hibernateq不妨碍你正在用的IDE?



L(fng)下面的条目,你在持久层编码中需要了解的?

* 查询对象的相关信息的语句?Hibernate通过一个OO查询语言QHQLQ或者正则表辄API来完成查询?HQL非常cM于SQL-- 只是把SQL里的table和columns用Object和它的fields代替?你需要学?fn)一些新的HQL语言Q?不管怎样Q他们容易理解而文档也做的很好?HQL是一U对象查询的自然语言Q花很小的代价就能学?fn)它?

* 如何存储Q更斎ͼ删除数据库记录?

* 象Hibernateq类的高UORM框架支持大部分主数据库Qƈ且他们支?Parent/child关系Q事物处理,l承和多态?



业务层(The Business LayerQ?/SPAN>

一个典型Web应用的中间部分是业务层或者服务层?从编码的视角来看Q这层是最Ҏ(gu)被忽视的一层?而我们却往往在UI层或持久层周围看到这些业务处理的代码Q这其实是不正确的,因ؓ(f)它导致了E序代码的紧密偶合,q样一来,随着旉推移q些代码很难l护。幸好,针对q一问题有好几种Frameworks存在?最受欢q的两个框架是Spring和PicoContainer?q些Z被称为microcontainersQ他们能让你很好的把对象搭配h?q两个框枉着手于‘依赖注?(dependency injection)(q有我们知道的‘控制反?Inversion of Control=IoC)q样的简单概c(din)?q篇文章关注于Spring的注(译注Q通过一个给定参数的SetterҎ(gu)来构造Bean,有所不同于FactoryQ? Springq提供了Setter Injection(type2)QConstructor Injection(type3){方式供我们选择?Spring把程序中所涉及(qing)到包含业务逻辑和Dao的Objects——例如transaction management handlerQ事物管理控Ӟ、Object Factoris(对象工厂)、service objectsQ服务组Ӟ——都通过XML来配|联pv来?



后面我们?x)D个例子来揭示一下Spring 是怎样q用q些概念?

业务层所负责的如下:(x)

* 处理应用E序?业务逻辑和业务校?

* 理事物

* 允许与其它层怺作用的接?

* 理业务层别的对象的依赖?

* 在显C层和持久层之间增加了一个灵zȝ机制Q得他们不直接的联pd一赗?

* 通过揭示 从显C层C务层之间的Context来得到business services?

* 理E序的执行(从业务层到持久层Q?





域模块层QThe Domain Model Layer Q?/SPAN>
既然我们致力于的是一个不是很复杂的Web的应用, 我们需要一个对象集合,让它在不同层之间Ud的?域模块层由实际需求中的业务对象组?比如, OrderLineItem , Product{等?开发者在q层 不用那些DTOsQ仅xdomain object卛_?例如QHibernate允许你将数据库中的信息存攑օ对象Qdomain objectsQ,q样你可以在q接断开的情况下把这些数据显C到UI层?而那些对象也可以q回l持l层Q从而在数据库里更新?而且Q你不必把对象{化成DTOsQ这可能似的它在不同层之间的在传输过E中丢失Q,q个模型使得Java开发者能很自然运用OOQ而不需要附加的~码?

一个简单例?



既然我们已经从全局上理解这些组件?现在p我们开始实践吧?我们q是?StrutsQSpring 和Hibernate。这三个框架已经被描q够多了Q这里就不重复介l了?q篇文章举例指导你如何用这三个框架整合开? q向你揭C?一个请求是如何贯穿于各个层的。(从用L(fng)加入一个Order到数据库Q显C;q而更新、删除)?



从这里可以下载到E序E序原代码(downloadQ?

既然每个层是互相作用的,我们先来创建domain objects。首先,我们要在q些Object中要定那些是需要持久化的,哪些是提供给business logicQ那些是昄接口的设计?下一步,我们配|我们的持久层ƈ且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后,我们?使用Spring把这些连接v来?最后,我们提供lSpring一个持久层Q从q个持久层里我们可以知道它是如何与业务逻辑层(business service layerQ通信的,以及(qing)它是怎样处理其他层抛出的异常的。?



域对象层QDomain Object LayerQ?/SPAN>


q层是编码的着手点Q我们的~码׃q层开始?例子中Order 与OrderItem 是一个One—To—Many的关pR?下面是Domain Object Layer的两个对象:(x)



· com.meagle.bo.Order.java: 包含了一个Order的概要信?

· com.meagle.bo.OrderLineItem.java: 包含了Order的详l信?

好好考虑怎你的package命名,q反应出了你是怎样分层的?例如 domain objects在程序中可能打包在com.meagle.bo内?更详l一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions?持久对象Qpresentation classesQ?应该分别攑֜ com.meagle.action和com.meagle.forms包?准确的给包命名得你的classes很好分割q且易于l护Qƈ且在你添加新的classesӞ能得程序结构上保持上下一致?

持久层的配置QPersistence Layer ConfigurationQ?/SPAN>

建立Hibernate的持久层 需要好几个步骤?W一步让我们把BO持久化?既然Hibernate是通过POJO工作的, 因此Order?OrderLineItem对象需要给所有的fileds 加上getter,setterҎ(gu)?Hibernate通过XML文g来映?OR)对象Q以下两个xml文g分别映射了Order 和OrderItem对象。(q里有个叫XDoclet工具可以自动生成你的XML影射文gQ?

- Order.hbm.xml
- OrderLineItem.hbm.xml

你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文g。Hibernate?[urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程?应该与哪个数据库通信Q该使用哪个q接池或使用了DataSourceQ?应该加蝲哪些持久对象。?A target=_blank rel=nofollow>Session接口是用来完成SelectingQSavingQDelete和Updatingq些操作?后面的我们将讲述SessionFactory和Session是怎样讄的?

业务层的配置QBusiness Layer ConfigurationQ?/SPAN>

既然我们已经有了domain objectsQ接下来我们pbusiness service objects了,用他们来执行E序的logic,调用持久层,得到UI层的requests,处理transactionsQƈ且控制exceptions?Z这些连接v来ƈ且易于管理,我们用面向方面的 SpringFramework?Spring 提供?控制倒置Qinversion of control 0==IoC)和注依赖设|(setter dependency injectionQ这些方式(可供选择Q,用XML文g对象连接v来?IoC是一个简单概念(它允怸个对象在上层接受其他对象的创建)Q用IoCq种方式让你的对象从创徏中释放了出来Q降低了偶合度?




q里是一个没有用IoC的对象创建的例子Q它有很高偶合度?




?2.没有使用 IoC. A 创徏?B ?C

而这里是一个用IoC的例子,q种方式允许对象在高层可以创建ƈq入另外一个对象,所以这样可以直接被执行?


?3. 对象使用?IoC?A 包含了接受B,C?setterҎ(gu) , q同栯C 由A创徏B,C的目的?/SPAN>

建立我们的业务服务对象(Building Our Business Service ObjectsQ?


Business Object中的SetterҎ(gu)接受的是接口Q这h们可以很松散的定义对象实玎ͼ然后注入?在我们的案例中,我们用一个business service object接收一个DAO,用它来控制domain objects的持久化?׃在这个例子中使用了HibernateQ我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了?

在面向接口的~程中,你会(x)明白 "注射依赖"模式是怎样松散耦合你的业务逻辑和持久机制的Q)?



下面是一个接口business service objectQDAO代码片段Q?


代码:

public interface IOrderService {

  public abstract Order saveNewOrder(Order order)

    throws OrderException,

           OrderMinimumAmountException;

 

  public abstract List findOrderByUser(

                                     String user)

                           throws OrderException;

 

  public abstract Order findOrderById(int id)

                           throws OrderException;

 

  public abstract void setOrderDAO(

                             IOrderDAO orderDAO);

}

 

注意到这D代码里有一?setOrderDaoQ)Q它?yu)是一个DAO Object讄Ҏ(gu)Q注器Q?但这里ƈ没有一个getOrderDao的方法,q不必要Q因Zq不?x)在外部讉Kq个orderDao。这个DAO Objecte被调用Q和我们的persistence layer 通信。我们将用Spring把DAO Object ?business service object搭配h的。因为我们是面向接口~程的,所以ƈ不需要将实现cȝ密的耦合在一赗?



接下L们开始我们的DAO的实现类q行~码?既然Spring已经有对Hibernate的支持,那这个例子就直接l承HibernateDaoSupportcMQ这个类很有用,我们可以参?A target=_blank rel=nofollow>HibernateTemplateQ它主要是针对HibernateDaoSupport的一个用法,译注Q具体可以查?A target=_blank rel=nofollow>Srping 的APIQ?下面是这个DAO接口代码Q?

代码:
public interface IOrderDAO {
  public abstract Order findOrderById(
                                    final int id);
 
  public abstract List findOrdersPlaceByUser(
                           final String placedBy);
  public abstract Order saveOrder(
                               final Order order);
}


我们仍然要给我们持久层组装很多关联的对象Q这里包含了HibernateSessionFactory 和TransactionManager?Spring 提供了一?HibernateTransactionManagerQ他用线E捆l了一个Hibernate SessionQ用它来支持transactions(h?A target=_blank rel=nofollow>ThreadLocal) ?

下面是HibernateSessionFactory ?HibernateTransactionManager:的配|:(x)

代码:
<bean id="mySessionFactory"
       class="org.springframework.orm.hibernate.
              LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>
        com/meagle/bo/Order.hbm.xml
      </value>
      <value>
        com/meagle/bo/OrderLineItem.hbm.xml
      </value>
    </list>
  </property>
  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">
        net.sf.hibernate.dialect.MySQLDialect
      </prop>
      <prop key="hibernate.show_sql">
        false
      </prop>
      <prop key="hibernate.proxool.xml">
        C:/MyWebApps/.../WEB-INF/proxool.xml
      </prop>
      <prop key="hibernate.proxool.pool_alias">
          spring
      </prop>
    </props>
  </property>
</bean>
 
<!-- Transaction manager for a single Hibernate
SessionFactory (alternative to JTA) -->
<bean id="myTransactionManager"
         class="org.
                springframework.
                orm.
                hibernate.
                HibernateTransactionManager">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
  </bean>



可以看出Q每个对象都可以在Spring 配置信息中用<bean>标签引用。在q里QmySessionFactory引用了HibernateSessionFactoryQ而myTransactionManager引用了HibernateTransactionManage?注意代码中myTransactionManger Bean有个sessionFactory属性?HibernateTransactionManager有个sessionFactory setter ?getterҎ(gu)Q这是用来在Spring启动的时候实?依赖注入" Qdependency injectionQ的?在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后pl装了v来了?q样的搭配让你从 单例Qsingleton objectsQ和工厂QfactoriesQ中解放了出来,降低了代码的l护代h(hun)?mySessionFactory.的两个属性,分别是用来注入mappingResources ?hibernatePropertes的。通常Q如果你在Spring之外使用Hibernate,q样的设|应该放在hibernate.cfg.xml中的?不管怎样,Spring提供了一个便L(fng)方式-----在Spring内部配置中ƈ入了Hibernate的配|?如果要得到更多的信息Q可以查阅Spring API?





既然我们已经l装配置好了Service BeansQ就需要把Business Service Object?DAO也组装v来,q把q些对象配到一个事务管理器Qtransaction managerQ里?



在Spring中的配置信息Q?
代码:

<!-- ORDER SERVICE -->
<bean id="orderService"
  class="org.
         springframework.
         transaction.
         interceptor.
         TransactionProxyFactoryBean">
  <property name="transactionManager">
    <ref local="myTransactionManager"/>
  </property>
  <property name="target">
    <ref local="orderTarget"/>
  </property>
  <property name="transactionAttributes">
    <props>
      <prop key="find*">
     PROPAGATION_REQUIRED,readOnly,-OrderException
      </prop>
      <prop key="save*">
     PROPAGATION_REQUIRED,-OrderException
      </prop>
    </props>
  </property>
</bean>
 
<!-- ORDER TARGET PRIMARY BUSINESS OBJECT:
Hibernate implementation -->
<bean id="orderTarget"
         class="com.
                meagle.
                service.
                spring.
                OrderServiceSpringImpl">
  <property name="orderDAO">
    <ref local="orderDAO"/>
  </property>
</bean>
 
<!-- ORDER DAO OBJECT -->
<bean id="orderDAO"
         class="com.
                meagle.
                service.
                dao.
                hibernate.
                OrderHibernateDAO">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
</bean>




? 是我们对象搭建的一个提UӀ?从中可以看出Q每个对象都联系着SpringQƈ且能通过Spring注入到其他对象。把它与Spring的配|文件比较,观察他们之间的关p?



?4. Spring是q样Z配置文gQ将各个Bean搭徏在一赗?/SPAN>

q个例子使用一个TransactionProxyFactoryBeanQ它定义了一个setTransactionManager()?q对象很有用Q他能很方便的处理你x的事物还有Service Object?你可以通过transactionAttributes属性来定义怎样处理?想知道更多还是参考TransactionAttributeEditor吧?

TransactionProxyFactoryBean q有个setter. q会(x)被我?Business service objectQorderTargetQ引用, orderTarget定义?业务服务层,q且它还有个属性,由setOrderDAO()引用。这个属?



Spring 和Bean 的还有一点要注意的:(x) bean可以以用两种方式创造?q些都在单例模式QSingtonQ和原型模式QpropotypeQ中定义了?默认的方式是singleton,q意味着׃n的实例将被束~?而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得C们自己Bean的CopyӞ你应该仅使用prototype模式。(更多的请参考设计模式中的单例模式和原Ş模式Q?

提供一个服务定位器QProviding a Service LocatorQ?/SPAN>
既然我们已经我们的Serices和DAO搭配h了。我们需要把我们的Service昄到其他层?q个通常是在Struts或者Swingq层里编码。一个简单方法就是用 服务定位器返回给Spring context 。当Ӟ可以通过直接调用Spring中的Bean来做?

下面是一个Struts Actin 中的服务定位器的一个例子?
代码:

public abstract class BaseAction extends Action {
 
  private IOrderService orderService;
 
  public void setServlet(ActionServlet
                                 actionServlet) {
    super.setServlet(actionServlet);
    ServletContext servletContext =
               actionServlet.getServletContext();
 
    WebApplicationContext wac =
      WebApplicationContextUtils.
         getRequiredWebApplicationContext(
                                 servletContext);
 
      this.orderService = (IOrderService)
                     wac.getBean("orderService");
  }
 
  protected IOrderService getOrderService() {
    return orderService;
  }
}
 

UI 层配|?QUI Layer ConfigurationQ?/SPAN>

q个例子里UI?使用了Struts framework. q里我们要讲qC下在l程序分层的时候, 哪些是和Struts部分的。我们就从一个Struts-config.xml文g中的Action的配|信息开始吧?
代码:

struts-config.xml file.

<action path="/SaveNewOrder"
    type="com.meagle.action.SaveOrderAction"
    name="OrderForm"
    scope="request"
    validate="true"
    input="/NewOrder.jsp">
  <display-name>Save New Order</display-name>
  <exception key="error.order.save"
    path="/NewOrder.jsp"
    scope="request"
    type="com.meagle.exception.OrderException"/>
  <exception key="error.order.not.enough.money"
    path="/NewOrder.jsp"
    scope="request"
    type="com.
          meagle.
          exception.
          OrderMinimumAmountException"/>
  <forward name="success" path="/ViewOrder.jsp"/>
  <forward name="failure" path="/NewOrder.jsp"/>
</action>

SaveNewOrder q个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的Action; 注意观察q个Action中exception配置Q这些Exceptions也在Spring 配置文g(applicationContext-hibernate.xml)中配|了Q就?business service object 的transactionAttributes属性里Q?当异常在业务层被被抛出时Q我们可以控制他们,q当的显C给UI层?

W一个异常,OrderException,在持久层保存order对象p|的时候被触发。这导致事物回滚ƈ且通过BO把异常回传到Strutsq一层?

W二个异常,OrderMinimumAmountException也同W一个一栗?





搭配整和的最后一?通过是让你显C层和业务层相结合。这个已l被服务定位器(service locatorQ实CQ前面讨了)Q?q里服务层作Z个接口提供给我们的业务逻辑和持久层?



SaveNewOrder Action 在Struts中用一个服务定位器Qservice locatorQ来调用执行业务Ҏ(gu)的?Ҏ(gu)代码如下Q?



代码:
public ActionForward execute(

  ActionMapping mapping,

  ActionForm form,

  javax.servlet.http.HttpServletRequest request,

  javax.servlet.http.HttpServletResponse response)

  throws java.lang.Exception {

 

  OrderForm oForm = (OrderForm) form;

 

  // Use the form to build an Order object that

  // can be saved in the persistence layer.

  // See the full source code in the sample app.

 

  // Obtain the wired business service object

  // from the service locator configuration

  // in BaseAction.

  // Delegate the save to the service layer and

  // further upstream to save the Order object.

  getOrderService().saveNewOrder(order);

 

  oForm.setOrder(order);

 

  ActionMessages messages = new ActionMessages();

  messages.add(

      ActionMessages.GLOBAL_MESSAGE,

            new ActionMessage(

      "message.order.saved.successfully"));

 

  saveMessages(request, messages);

 

  return mapping.findForward("success");

}


ȝ

q篇文章在技术和构架斚w掩盖了很多低层的基础信息Q?文章的主要的意图在于让你意识到如何给你应用程序分层?分层可以"解?你的代码——允许新的组件被dq来Q而且让你的代码易于维护?q里用到的技术只是专注于?解偶"做好?不管怎样Q用这L(fng)构架可以让你用其他技术代替现在的层?例如Q你可能不用Hibernate实现持久化。既然你在DAO中面向接口的~程的,所以你完全可以用iBATIS来代ѝ或者,你也可能想用Struts外的其他的技术或者框架替换现在的UI层(转换久层Q实现层q不应该直接影响C的业务逻辑和业务服务层Q?用适当的框架搭Z的Web应用Q其实也不是一件烦琐的工作Q更主要的是?解?了你E序中的各个层?





后记Q?

看完q篇文章后,只是觉得很喜Ƣ,于是q译了Q当然同时也准备着挨大家扔来的鸡蛋Q)?

q篇文章里ƈ没有太多的技术细节,和详l的步骤。如果你从未使用q这些框架而在q行实例E序遇上困难的话Q可以到CSDN论坛Java Open Source版发_(d)我一定会(x)详细解答的(啊哦Q这不算做广告吧Q)Q?

文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层, 有太多的术语我都不知道怎么表达Q而且可能有很多语句存在错误。如果媄响了你的阅读Q请你直接点原文地址Q我同时也象你说声抱歉?



作者简介:(x)Mark Eagle 高软g工程师,亚特兰大?
?译:(x)Totodo,软g工程?





参考:(x)

StrutsQhttp://jakarta.apache.org/struts/index.html

Spring: http://www.springframework.org

Hibernate: http://www.hibernate.org

http://www.hibernate.org.cn

关于控制反{IOC和依赖注:(x)http://www.martinfowler.com/articles/injection.html

原文:

http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=1
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=2
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=4


Victor 2005-12-05 15:26 发表评论
]]>
[转]J2EE架构?个最?jng)_?/title><link>http://www.tkk7.com/Victor/articles/22587.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Mon, 05 Dec 2005 07:25:00 GMT</pubDate><guid>http://www.tkk7.com/Victor/articles/22587.html</guid><wfw:comment>http://www.tkk7.com/Victor/comments/22587.html</wfw:comment><comments>http://www.tkk7.com/Victor/articles/22587.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/Victor/comments/commentRss/22587.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/Victor/services/trackbacks/22587.html</trackback:ping><description><![CDATA[虽然许多文章曄讨论qJ2EE最?jng)_c(din)那么,Z么我q要再写一文章呢Q本文究竟与以前的文章有何不同或者说比其他文章好在哪呢? <BR>  首先Q本文的目标读者是正在从事技术工作的架构师。ؓ(f)了避免浪费大家的才智Q我?x)避免讲qC些陈腐的最?jng)_践,例如"日常构徏Qbuild dailyQ??试一切(test everythingQ??l常集成Q?nbsp;integrate oftenQ?nbsp;MhU职架构师的目都有分工明确的、定义良好的团队l构。他们还行编码检查、构Z码(每日或在需要时Q、进行测试(单元、集成和pȝ的)、部|和配置/释放理而具备已记录的过E?<BR>  其次Q我蟩q通常Ҏ(gu)的最?jng)_践,例如"Z接口的设??使用著名的设计模?以及(qing)"使用面向服务的架?{。相反,我将集中讲述我曾学过q且使用了若q年?Q不是很多)个方面的in-the-trench评。最后,本文的目的是让?zhn)思考一下自q架构Q提供工作代码示例或者解x案超Z本文的范围。下面就让我介绍一下这6课:(x) <BR><BR>W?课:(x)切勿l过服务器端验证 <BR>  作ؓ(f)一位Y仉问,我曾有机?x)不但设计ƈ实现了Web应用E序Q而且q评?审核了许多Web应用E序。在复杂的、ƈ且用JavaScript客户端封装的应用E序内,我经帔R到对用户输入信息执行大量查的Web面。即使HTML元素h数据有效性的属性也如此Q例如MAXLENGTH。只有在成功验证所有输入信息后Q才能提交HTML表单。结果,一旦服务器端收到通知表单Q请求)Q便恰当地执行业务逻辑?<BR>  在此Q?zhn)发现问题了么Q开发h员已l做了许多重要的假设。例如,他们假设所有的Web应用E序用户都同栯实。开发h员还假设所有用户将L使用他们试q的览器访问Web应用E序。还有很多其他的假设。这些开发h员忘C利用可以免费得到的工P通过命o(h)行很Ҏ(gu)地模拟类似浏览器的行为。事实上Q通过在浏览器H口中键入适当的URLQ?zhn)可以发送Q?posted"表单Q尽如此,通过用q些面的GEThQ?zhn)很容易地Lq样?表单发?。但是,(zhn)不能阻止h们模拟甚臛_Z们自q览器来入R(zhn)的pȝ?<BR>Ҏ(gu)的问题在于开发h员不能确定客L(fng)验证与服务器端验证的主要差别。两者的主要差别不在于验证究竟发生在哪里Q例如在客户端或者在服务器端。主要的差别在于验证背后的目的不同?<BR>  客户端验证仅仅是方便。执行它可ؓ(f)用户提供快速反??使应用程序似乎做出响应,lh一U运行桌面应用程序的错觉?<BR>  另一斚wQ服务器端验证是构徏安全Web应用E序必需的。不在客户端一侧输入的是什么,它可以确保客L(fng)送往服务器的所有数据都是有效的?<BR>  因而,只有服务器端验证才可以提供真正应用程序的安全。许多开发h员陷入了错误感觉的圈套:(x)只有在客L(fng)q行所有数据的验证才能保安全。下面是说明此观点的一个常见的CZQ?<BR>  一个典型的d面拥有一个用来输入用户名的文本框和一个输入密码的文本框。在服务器端Q某人在接收servlet中可能遇C些代码,q些代码构成了下面Ş式的SQL查询Q?<BR>"SELECT * FROM SecurityTable WHERE username = '" + form.getParameter("username") + "' AND password = '" + form.getParameter("password") + "';"Qƈ执行q些代码。如果查询在l果集的某一行返回,则用L(fng)录成功,否则用户dp|?<BR>  W一个问题是构造SQL的方式,但现在让我们暂时忽略它。如果用户在用户名中输入"Alice'--"?x)怎样呢?假设名ؓ(f)"Alice"的用户已l在SecurityTable中,q时此用P更恰当的说法是黑客)成功地登录。我把扑ևZ么会(x)出现q种情况的原因做为留l?zhn)的一道习(fn)题?<BR>  许多创造性的客户端验证可以阻止一般的用户从浏览器中这L(fng)录。但对于已经用了JavaScript的客L(fng)Q或者那些能够用其他类似浏览器E序直接发送命令(HTTP POST和GET命o(h)Q的高用户Q或者说黑客Q来_(d)我们又有什么办法呢Q服务器端验证是防止q种漏洞cd所必须的。这ӞSSL、防火墙{都z不上用Z?<BR><BR>W?课:(x)安全q是附加物 <BR>  如第1课所qͼ我曾有幸研究q许多Web应用E序。我发现所有的JavaServer PageQJSPQ都有一个共同的主题Q那是hcM下面伪代码的布局Q?<BR><BR><% <BR>User user =  <BR>session.getAttribute("User"); <BR>if(user == null) <BR>{ <BR>// redirect to  <BR>// the logon page... <BR>}  <BR>if(!user.role.equals("manager")) <BR>{ <BR>// redirect to the <BR>// "unauthorized" page... <BR>} <BR>%> <BR><BR><!- <BR>HTML, JavaScript, and JSP <BR>code to display data and <BR>allow user interaction --> <BR><BR>  如果目使用诸如Strutsq样的MVC框架Q所有的Action Bean都会(x)hcM的代码。尽最后这些代码可能运行得很好Q但如果(zhn)发C个bugQ或者?zhn)必须d一个新的角Ԍ例如Q?guest"或?admin"Q,q就?x)代表一场维护恶梦?<BR>  此外Q所有的开发h员,不管(zhn)多q轻Q都需要熟(zhn)这U编码模式。当Ӟ(zhn)可以用一些JSP标签来整理JSP代码Q可以创Z个清除派生Action Bean的基本Action Bean。尽如此,׃与安全相关的代码?x)分布到多个地方Q所以维护时的恶梦仍旧存在。由于Web应用E序的安全是建立在应用程序代码的U别上(由多个开发h员)Q而不是徏立在架构U别上,所以Web应用E序q是很可能存在弱炏V?<BR>  很可能,Ҏ(gu)的问题是在项目接q完成时才处理安全性问题。最q作Z名架构师Q我曑֜一q多的时间里亲历了某一要实现项目的6个版本,而直到第四版时我们才提到了安全??即该项目会(x)高度敏感的个h数据暴露于Web上,我们也没有注意到安全性。ؓ(f)了更改发布计划,我们卷入了与目资助人及(qing)其管理h员的争斗中,以便在第一版中包含所有与安全相关的功能,q将一?业务"功能攑֜后箋的版本中。最l,我们赢得了胜利。而且׃应用E序的安全性相当高Q能够保护客L(fng)U有数据Q这一Ҏ(gu)们引以ؓ(f)荣,我们的客户也非常高兴?<BR>  遗憾的是Q在大多数应用程序中Q安全性看hq未增加M实际的商业h(hun)|所以直到最后才解决。发生这U情冉|Qh们才匆忙开发与安全相关的代码,而丝毫没有考虑解决Ҏ(gu)的长期可l护性或者健壮性。忽视该安全性的另一个征兆是~Z全面的服务器端验证,如我在第1课中所qͼq一Ҏ(gu)安全Web应用E序的一个重要组成部分?<BR>  CQJ2EE Web应用E序的安全性ƈ非仅仅是在Web.xml 和ejb-jar.xml文g中用合适的声明Q也不是使用J2EE技术,如Java 认证和授权服务(Java Authentication and Authorization ServiceQJAASQ。而是l过深思熟虑后的设计,且实C个支持它的架构?<BR><BR>W?课:(x)国际化(I18NQ不再是U怸谈兵  <BR>  当今世界的事实是许多p非母语的Z访问?zhn)的公共Web应用E序。随着?sh)子政务的实行,׃它允思h们(某个国家的居民)在线与政府机构交互,所以这一点特别真实。这L(fng)例子包括换发驄或者R辆登记证。许多第一语言不是p的h们很可能访问这L(fng)应用E序。国际化Q即Q?i18n"Q因为在"internationalization"q个单词中,字母i和字母n之间一共有18个字母)使得(zhn)的应用E序能够支持多种语言?<BR>  昄Q如果?zhn)的JSP 面中有编码的文本Q或者?zhn)的Java代码q回编码的错误消息Q那么?zhn)要花费很多时间开发此Web应用E序的西班牙语版本。然而,在Web应用E序中,Z支持多种语言Q文本不是惟一必须"具体?的部分。因多图像中嵌有文字Q所以图形和囑փ也应该是可配|的。在极端的情况下Q图像(或者颜Ԍ在不同的文化背景中可能有完全不同的意思。类似地QQ何格式化数字和日期的Java代码也必L地化。但问题是:(x)(zhn)的面布局可能也需要更攏V?<BR>  例如Q如果?zhn)使用HTML表格来格式化和显C单选项、应用程序题头或注脚Q则(zhn)可能必Mؓ(f)每一U支持的语言更改每一栏的最宽度和表格其他可能的方面。ؓ(f)了适应不同的字体和颜色Q?zhn)可能必须为每一U语a使用单独的样式表?<BR>  昄Q现在创Z个国际化的Web应用E序面(f)的是架构挑战而不是应用程序方面的挑战。一个架构良好的Web应用E序意味着(zhn)的JSP面和所有与业务相关的(应用E序Ҏ(gu)的)Java代码都不知不觉地选择了本地化。要C的教训是Q不要因为Java、J2EE支持国际化而不考虑国际化。?zhn)必须从第一天vp住设计具有国际化的解x案?<BR><BR>W?课:(x)在MVC表示中避免共同的错误  <BR>  J2EE开发已l够成熟,在表C层Q大多数目使用MVC架构的某些Ş式,例如Struts。在q样的项目中Q我常见到的现象是对MVC模式的误用。下面是几个CZ?<BR>  常见的误用是在模型层Q例如,在Struts的Action Bean中)实现了所有的业务逻辑。不要忘了,表示层的模型层仍然是表示层的一部分。用该模型层的正确Ҏ(gu)是调用适当的业务层服务Q或对象Qƈ结果发送到视图层(view layerQ。用设计模式术语来说QMVC表示层的模型应该作ؓ(f)业务层的外观QF(tun)a?adeQ来实现。更好的Ҏ(gu)是,使用核心J2EE模式QCore J2EE PatternsQ中到的Business Delegate模式。这D自书中摘录的内容精彩地概述了将(zhn)的模型作ؓ(f)Business Delegate来实现的要点和优点:(x) <BR>  Business Delegate起到客户端业务抽象化的作用。它抽象化,q而隐藏业务服务的实现。用Business DelegateQ可以降低表C层客户端和pȝ的业务服?之间的耦合E度。根据实现策略不同,Business Delegate可以在业务服务API的实CQ保护客L(fng)不受可能的变动性媄响。这P在业务服务API或其底层实现变化Ӟ可以潜在地减必M改表C层客户端代码的ơ数?<BR>  另一个常见的错误是在模型层中攄许多表示cd的逻辑。例如,如果JSP面需要以指定方式格式化的日期或者以指定方式排序的数据,某些人可能将该逻辑攄在模型层Q对该逻辑来说Q这是错误的地方。实际上Q它应该在JSP面使用的一lhelpercM。当业务层返回数据时QAction Bean应该数据{发给视图层。这P无需创徏模型和视图之间多余的耦合Q就能够灉|支持多个视图层(JSP、Velocity、XML{)。也使视图能够确定向用户昄数据的最x式?<BR>  最后,我见q的大多数MVC应用E序都有未充分应用的控制器。例如,l大多数的Struts应用E序创Z个基本的Actionc,q完成所有与安全相关的功能。其他所有的Action Bean都是此基cȝzcR这U功能应该是控制器的一部分Q因为如果没有满_全条Ӟ则首先调用不应该到达Action BeanQ即Q模型)。记住,一个设计良好的MVC架构的最强大功能之一是存在一个健壮的、可扩展的控制器。?zhn)应该利用该能力以加强自己的优ѝ?<BR><BR>W?课:(x)不要被JOPO束缚(x)住手?<BR>  我曾目睹许多目Z使用Enterprise JavaBean而用Enterprise JavaBean。因为EJBgl项目带来优感和妄自尊大的表现Q所以有时它是显L(fng)要素Qcoolness factorQ。而其他时候,它会(x)使J2EE和EJB引vh。记住,J2EE和EJB不是同意词。EJB只是J2EE 的一部分QJ2EE 是包含JSP、servlet、Java 消息服务QJMSQ、Java数据库连接(JDBCQ、JAAS?nbsp;Java理扩展QJMXQ和EJB在内的一pd技术,同样也是有关如何共同使用q些技术徏立解x案的一l指导原则和模式?<BR>  如果在不需要用EJB的情况下使用EJBQ它们可能会(x)影响E序的性能。与老的Web服务器相比,EJB一般对应用服务器有更多的需求。EJB提供的所有增值服务一般需要消耗更大的内存和更多的CPU旉。许多应用程序不需要这些服务,因此应用服务器要与应用程序争源?<BR>  在某些情况下Q不必要C用EJB可能使应用程序崩溃。例如,最q我遇到了一个在开源应用服务器上开发的应用E序。业务逻辑装在一pd有状态会(x)话beanQEJBQ中。开发h员ؓ(f)了在应用服务器中完全用q些bean?钝化"费了很大的劲。客L(fng)要求应用E序部v在某一商用应用服务器上Q而该服务器是客户端技术栈的一部分。该应用服务器却不允许关?钝化"功能。事实上Q客L(fng)不想改变与其合作的应用服务器的设M|。结果,开发商到了很大的ȝ。(gQ有的事情是开发商自己都不能给Zؓ(f)什么将代码用EJBQ而且q是有状态会(x)话beanQ实现的好理由。不仅仅是开发商?x)遇到性能问题Q他们的E序在客户那里也无法工作?<BR>  在Web应用E序中,无格式普通Java 对象QPOJOQ是EJB强有力的竞争者。POJO是轻量的,不像EJB那样负担额外的负担。在我看来,对许多EJB的优点,例如对象入池Q估计过高。POJO是?zhn)的朋友,不要被它束?x)住手脚?<BR><BR>W?课:(x)数据讉Kq不能托O/R映射  <BR>  我曾参与q的所有Web应用E序都向用户提供从其他地方存取的数据Qƈ且因此需要一个数据访问层。这q不是说所有的目都需要标识ƈ建立q样一个层Q这仅仅说明q样层的存在不是隐含的就是明的。如果是隐含的数据层Q数据层是业务对象(卻I(x)业务服务Q层的一部分。这适用于小型应用程序,但通常与大一些项目所接受的架构指导原则相抵触?<BR>  MQ数据访问层必须满或超Z下四个标准:(x) <BR>  h透明?nbsp; <BR>  业务对象在不知道数据源实现的具体l节情况下,可以使用数据源。由于实现细节隐藏在数据讉K层的内部Q所以访问是透明的?<BR>  易于q移 <BR>  数据讉K层应用E序很容易迁Ud其他数据库实现。业务对象不了解底层的数据实玎ͼ所以迁UM仅涉?qing)到修改数据讉K层。进一步地_(d)如果(zhn)正在部|某U工厂策略,(zhn)可以ؓ(f)每个底层的存储实现提供具体的工厂实现。如果是那样的话Q迁Ud不同的存储实现意味着为应用程序提供一个新的工厂实现?<BR>  量减少业务对象中代码复杂?nbsp; <BR>  因ؓ(f)数据讉K层管理着所有的数据讉K复杂性,所以它可以化业务对象和使用数据讉K层的其他数据客户端的代码。数据访问层Q而不是业务对象,含有许多与实现相关的代码Q例如SQL语句Q。这L(fng)开发h员带来了更高的效率、更好的可维护性、提高了代码的可L等一pd好处?<BR>  把所有的数据讉K集中在单独的层上 <BR>  ׃所有的数据讉K操作现在都委托给数据讉K层,所以?zhn)可以这个单独的数据讉K层看做能够将应用E序的其他部分与数据讉K实现怺隔离的层。这U集中化可以使应用程序易于维护和理?<BR>  注意Q这些标准都不能明确地调出对O/RQ对象到关系Q映层的需求。O/R映射层一般用O/R映射工具创徏Q它提供对象对关pL据结构的查看和感知(look-and-feelQ。在我看来,在项目中使用O/R映射与用EJBcM。在大多数情况下Qƈ不要求它。对于包含中{规模的联合以及(qing)多对多关pȝ关系型数据库来说QO/R映射?x)变得相当复杂。由于增加O/R 映射解决Ҏ(gu)本n的内在复杂性,例如延迟加蝲Qlazy loadingQ、高速缓冲等Q?zhn)?f)(zhn)的目带来更大的复杂性(和风险)?<BR>  Zq一步支持我的观点,我将指出按照Sun Microsystem所普及(qing)的实体BeanQO/R映射的一U实玎ͼ的许多失败的试Q这是自1.0版以来一直折h的难题。在SUN的防卫措施中Q一些早期的问题是有关EJB规范的开发商实现的。这依次证明了实体Bean规范自n的复杂性。结果,大多数J2EE架构师一般认Z实体Bean中脱d来是一个好L?<BR>  大多数应用程序在处理他们的数据时Q只能进行有限次数的查询。在q样的应用程序中Q访问数据的一U有效方法是实现一个数据访问层Q该层实现执行这些查询的一pd服务Q或对象、或APIQ。如上所qͼ在这U情况下Q不需要O/R映射。当(zhn)要求查询灵zL时QO/R映射正合适,但要CQ这U附加的灉|性ƈ不是没有代h(hun)的?<BR>  像我承诺的那样Q在本文中,我尽量避免陈腐的最?jng)_c(din)相反,关于J2EE目中每一位架构师必须做出的最重要的决定,我集中讲解了我的观点。最后,(zhn)应该记住:(x)J2EEq某种具体的技术,也不是强行加入到解决Ҏ(gu)中的一些首字母~写。相反,(zhn)应该在适当的时机,恰当的地方,使用合适的技术,q循J2EE的指导原则和J2EE中所包含的比技术本w重要得多的实践?<BR><img src ="http://www.tkk7.com/Victor/aggbug/22587.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/Victor/" target="_blank">Victor</a> 2005-12-05 15:25 <a href="http://www.tkk7.com/Victor/articles/22587.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://gedebai.com" target="_blank">ŮëƬѲƵm</a>| <a href="http://ksp33.com" target="_blank">gayվ</a>| <a href="http://864007.com" target="_blank">avƷɫҹĻ</a>| <a href="http://bjhuicui.com" target="_blank">޹ۺϾƷĻ</a>| <a href="http://chibifilm.com" target="_blank">Ƶۿ</a>| <a href="http://wenfaka.com" target="_blank">ݺݾþѹۿ</a>| <a href="http://yaku100.com" target="_blank">պҹƵ</a>| <a href="http://vip98888.com" target="_blank">һɫëƬ</a>| <a href="http://7x966.com" target="_blank">ۺɫ߹ۿ</a>| <a href="http://mabaolu.com" target="_blank">avĻ</a>| <a href="http://doubaye.com" target="_blank">Avۺɫרɫ</a>| <a href="http://zaidongmaixi.com" target="_blank">ɫ͵С˵</a>| <a href="http://818812.com" target="_blank">Avۺɫרɫ</a>| <a href="http://zzxngk.com" target="_blank">vavava</a>| <a href="http://5222133.com" target="_blank">һѹۿ</a>| <a href="http://guoyit.com" target="_blank">޹˳þþƷ</a>| <a href="http://bjfljg.com" target="_blank">޲122021鶹</a>| <a href="http://by1687.com" target="_blank">þþƷަvDz</a>| <a href="http://senimei9.com" target="_blank">ۺϾƷ</a>| <a href="http://wwwaa875.com" target="_blank">avר߹ۿ</a>| <a href="http://yutuzb.com" target="_blank">ۺɫ</a>| <a href="http://my637.com" target="_blank">ŷ޾ƷƵѹۿ </a>| <a href="http://91haikala.com" target="_blank">ҹAVëƬþ</a>| <a href="http://93qsgy.com" target="_blank">þþþþ޾Ʒ</a>| <a href="http://kmyake.com" target="_blank">޹ƷþSM</a>| <a href="http://www00475.com" target="_blank">ɫ</a>| <a href="http://beidemei.com" target="_blank">һþþþþþþ</a>| <a href="http://cnkaiertong.com" target="_blank">ѲŮһëƬ</a>| <a href="http://www-7479.com" target="_blank">йһػƸѵĴƬйһɫƬ</a>| <a href="http://zqsplc.com" target="_blank">㶮õ߹ۿƵ</a>| <a href="http://yxjcgs.com" target="_blank">91㽶߹ۿ</a>| <a href="http://www66913.com" target="_blank">ˬִ̼APP</a>| <a href="http://1ygogo.com" target="_blank"> С˵ۺͼ</a>| <a href="http://www-63228.com" target="_blank">ۺͼɫ40p</a>| <a href="http://www769393.com" target="_blank">޼ɫС˵</a>| <a href="http://anyliz.com" target="_blank">޹AV</a>| <a href="http://6t23.com" target="_blank">鶹һƷһAVһ</a>| <a href="http://youtobey.com" target="_blank">þùƵ</a>| <a href="http://srztw.com" target="_blank">޾Ʒھþ</a>| <a href="http://av-fantasy.com" target="_blank">ҹƷһ</a>| <a href="http://jkc178.com" target="_blank">avרߵӰ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>