﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-学习.......工作.......-随笔分类-技术文章转载</title><link>http://www.blogjava.net/hallywang/category/8293.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 13 Mar 2007 06:55:04 GMT</lastBuildDate><pubDate>Tue, 13 Mar 2007 06:55:04 GMT</pubDate><ttl>60</ttl><item><title>http协议头文件</title><link>http://www.blogjava.net/hallywang/archive/2007/03/12/103329.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 12 Mar 2007 07:08:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2007/03/12/103329.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/103329.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2007/03/12/103329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/103329.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/103329.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">HTTP</span>
				<span style="FONT-FAMILY: 宋体">协议完整规范参见</span>
				<span lang="EN-US">W3C</span>
				<span style="FONT-FAMILY: 宋体">官方网站</span>
				<span lang="EN-US">
						<a href="http://www.w3.org/Protocols/">http://www.w3.org/Protocols/</a>
				</span>
				<span style="FONT-FAMILY: 宋体">）</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">http</span>
				<span style="FONT-FAMILY: 宋体">头的组成：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">==============</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US"> </span>
				<span lang="EN-US">HTTP</span>
				<span style="FONT-FAMILY: 宋体">头字段包括</span>
				<span lang="EN-US">4</span>
				<span style="FONT-FAMILY: 宋体">类：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       general-header ;</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">     request-header ;</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       response-header ;</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">     entity-header .</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">*******************************************************************************</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US"> </span>
				<span lang="EN-US">General Header Fields</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">=============================</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">   general header</span>
				<span style="FONT-FAMILY: 宋体">是</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">、</span>
				<span lang="EN-US">response</span>
				<span style="FONT-FAMILY: 宋体">都可用的</span>
				<span lang="EN-US">, </span>
				<span style="FONT-FAMILY: 宋体">但是不能用于</span>
				<span lang="EN-US">entity. </span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Cache-Control</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Connection</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Date</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Pragma</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Trailer</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Transfer-Encoding</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Upgrade</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Via</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Warning</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">*******************************************************************************</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US"> </span>
				<span lang="EN-US">Request Header Fields</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">======================</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">   request-header fields </span>
				<span style="FONT-FAMILY: 宋体">允许客户端传递关于</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">和客户端的附加信息到服务端，</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Accept</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Accept-Charset</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Accept-Encoding</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Accept-Language</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Authorization</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Expect</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> From</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Host</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> If-Match</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> If-Modified-Since</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> If-None-Match</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> If-Range</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> If-Unmodified-Since</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Max-Forwards</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Proxy-Authorization</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Range </span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Referer</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> TE</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> User-Agent</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">*******************************************************************************</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US"> </span>
				<span lang="EN-US"> Response Header Fields</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">===============================</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">   response-header fields </span>
				<span style="FONT-FAMILY: 宋体">允许服务端传递关于</span>
				<span lang="EN-US">response</span>
				<span style="FONT-FAMILY: 宋体">的、不能放到</span>
				<span lang="EN-US">Status-Line</span>
				<span style="FONT-FAMILY: 宋体">的附加信息。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">   </span>
				<span style="FONT-FAMILY: 宋体">这些头给出关于服务端的信息。</span>
				<span lang="EN-US">   </span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Accept-Ranges</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Age</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> ETag</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Location </span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Proxy-Authenticate</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Retry-After</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Server</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Vary </span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">      </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> WWW-Authenticate</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">*******************************************************************************</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US"> </span>
				<span lang="EN-US">Entity Header Fields</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">========================</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">   Entity-header fields </span>
				<span style="FONT-FAMILY: 宋体">定义关于</span>
				<span lang="EN-US">entity-body</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">metainformation(</span>
				<span style="FONT-FAMILY: 宋体">标题字段数据</span>
				<span lang="EN-US">),</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">   </span>
				<span style="FONT-FAMILY: 宋体">如果当前没有</span>
				<span lang="EN-US">body, </span>
				<span style="FONT-FAMILY: 宋体">则定义被</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">确定的资源信息</span>
				<span lang="EN-US">.</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">   </span>
				<span style="FONT-FAMILY: 宋体">一些</span>
				<span lang="EN-US">metainformation</span>
				<span style="FONT-FAMILY: 宋体">是可选的</span>
				<span lang="EN-US">; </span>
				<span style="FONT-FAMILY: 宋体">一些是必须的。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
				</span> </p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Allow</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Encoding</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Language</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Length</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Location</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-MD5</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Range</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Content-Type</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Expires</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">       </span>
				<span style="FONT-FAMILY: 宋体">－－</span>
				<span lang="EN-US"> Last-Modified</span>
		</p>
<img src ="http://www.blogjava.net/hallywang/aggbug/103329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2007-03-12 15:08 <a href="http://www.blogjava.net/hallywang/archive/2007/03/12/103329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP协议三次握手</title><link>http://www.blogjava.net/hallywang/archive/2007/03/12/103327.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 12 Mar 2007 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2007/03/12/103327.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/103327.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2007/03/12/103327.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/103327.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/103327.html</trackback:ping><description><![CDATA[在TCP/IP协议中，TCP协议提供可靠的连接服务，采用三次握手建立一个连接。 
<p>　　第一次握手：建立连接时，客户端发送syn包(syn=j)到服务器，并进入SYN_SEND状态，等待服务器确认；</p><p>　　第二次握手：服务器收到syn包，必须确认客户的SYN（ack=j+1），同时自己也发送一个SYN包（syn=k），即SYN+ACK包，此时服务器进入SYN_RECV状态；</p><p>　　第三次握手：客户端收到服务器的SYN＋ACK包，向服务器发送确认包ACK(ack=k+1)，此包发送完毕，客户端和服务器进入ESTABLISHED状态，完成三次握手。</p><p>　　完成三次握手，客户端与服务器开始传送数据，在上述过程中，还有一些重要的概念：</p><p>　　未连接队列：在三次握手协议中，服务器维护一个未连接队列，该队列为每个客户端的SYN包（syn=j）开设一个条目，该条目表明服务器已收到SYN包，并向客户发出确认，正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态，当服务器收到客户的确认包时，删除该条目，服务器进入ESTABLISHED状态。<br />Backlog参数：表示未连接队列的最大容纳数目。</p><p>　　SYN-ACK 重传次数　服务器发送完SYN－ACK包，如果未收到客户确认包，服务器进行首次重传，等待一段时间仍未收到客户确认包，进行第二次重传，如果重传次数超过系统规定的最大重传次数，系统将该连接信息从半连接队列中删除。注意，每次重传等待的时间不一定相同。</p><p>　　半连接存活时间：是指半连接队列的条目存活的最长时间，也即服务从收到SYN包到确认这个报文无效的最长时间，该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。</p><img src ="http://www.blogjava.net/hallywang/aggbug/103327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2007-03-12 15:03 <a href="http://www.blogjava.net/hallywang/archive/2007/03/12/103327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>POI处理Excel[z]</title><link>http://www.blogjava.net/hallywang/archive/2006/10/25/77218.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Wed, 25 Oct 2006 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/10/25/77218.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/77218.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/10/25/77218.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/77218.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/77218.html</trackback:ping><description><![CDATA[
		<font color="#333333">本文将阐述如何用POI来读取/写入完整的Excel文件。<br />　　<br />　　约定：POI项目2.0版现在已经接近正式发行阶段，开发进度迅速，不断有新的功能集成到原有的系统，同时也有对原有系统的修改。<br />　　<br />　　为了保证本文的及时性，本文将按照最近的1.9开发版说明。虽然编译最近的发行版源代码也能正常运行，但现在的代码和2.0的发行版会有一些出入。<br />　　<br />　　<b>一、Excel基础</b><br />　　<br />　　Microsoft Excel 97文件格式也被称为BIFF8，最近版本的Excel只对该格式作了少量的改动。增加对新格式的支持除了增加项目的复杂性之外，唯一的效果也许只是不得不使每个用户升级代码，没有什么实际的好处。<br />　　<br />　　因此，在下文说明中，凡是提到Excel 97格式的地方其实都是指Excel从97到XP的格式。<br />　　<br />　　<b>二、HSSF概况</b><br />　　<br />　　POI项目实现的Excel 97文件格式称为HSSF??也许你已经猜到，HSSF是Horrible SpreadSheet Format的缩写，也即“讨厌的电子表格格式”（微软使某些原本简单的事情过分复杂，同时又过分简单地处理了某些原本需要灵活性的事情，让人不胜佩服！）<br />　　<br />　　也许HSSF的名字有点滑稽，就本质而言它是一个非常严肃、正规的API。通过HSSF，你可以用纯Java代码来读取、写入、修改Excel文件。<br />　　<br />　　前面一篇文章提到了POIFS，那么HSSF和POIFS又有什么关系呢？就象其他POI的API一样，HSSF建立在POIFS的基础上，因此在HSSF内的有些代码和前文的某些代码很相似。不过，当我们编写基于HSSF API的代码时，一般不需要了解POIFS API的细节。<br />　　<br />　　HSSF为读取操作提供了两类API：usermodel和eventusermodel，即“用户模型”和“事件-用户模型”。前者很好理解，后者比较抽象，但操作效率要高得多。usermodel主要有org.apache.poi.hssf.usermodel和org.apache.poi.hssf.eventusermodel包实现（在HSSF的早期版本中，org.apache.poi.hssf.eventusermodel属于eventmodel包）。<br />　　<br />　　usermodel包把Excel文件映射成我们熟悉的结构，诸如Workbook、Sheet、Row、Cell等，它把整个结构以一组对象的形式保存在内存之中。eventusermodel要求用户熟悉文件格式的底层结构，它的操作风格类似于XML的SAX API和AWT的事件模型（这就是eventusermodel名称的起源），要掌握窍门才能用好。<br />　　<br />　　另外，eventusermodel的API只提供读取文件的功能，也就是说不能用这个API来修改文件。<br />　　<br />　　<b>三、通过usermodel读取文件</b><br />　　<br />　　用HSSF的usermodel读取文件很简单。首先创建一个InputStream，然后创建一个HSSFWorkbook：<br />　　<br />　　InputStream myxls = new FileInputStream("workbook.xls"));<br />　　HSSFWorkbook wb　　 = new HSSFWorkbook(myxls);<br />　　<br />　　有了HSSFWorkbook实例，接下来就可以提取工作表、工作表的行和列，例如：<br />　　<br />　　HSSFSheet sheet = wb.getSheetAt(0);　　　 // 第一个工作表<br />　　HSSFRow row　　 = sheet.getRow(2);　　　　// 第三行<br />　　HSSFCell cell　 = row.getCell((short)3);　// 第四个单元格<br />　　<br />　　上面这段代码提取出第一个工作表第三行第四单元格。利用单元格对象可以获得它的值，提取单元格的值时请注意它的类型：<br />　　<br />　　if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {<br />　　("单元格是字符串，值是： " + cell.getStringCellValue());<br />　　} else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {<br />　　("单元格是数字，值是： " + cell.getCellValue());<br />　　} else () {<br />　　("单元格的值不是字符串或数值。");<br />　　}<br />　　<br />　　如果搞错了数据类型，程序将遇到异常。特别地，用HSSF处理日期数据要小心。Excel内部以数值的形式保存日期数据，区别日期数据的唯一办法是通过单元格的格式（如果你曾经在Excel中设置过日期格式，应该明白这是什么意思）。<br />　　<br />　　因此，对于包含日期数据的单元格，cell.getCellType()将返回HSSFCell.CELL_TYPE_NUMERIC，不过利用工具函数HSSFDateUtil.isCellDateFormatted(cell)可以判断出单元格的值是否为日期。isCellDateFormatted函数通过比较单元格的日期和Excel的内置日期格式得出结论??可以想象，按照这种判断方法，很多时候isCellDateFormatted函数会返回否定的结论，存在一定的误判可能。<br />　　<br />　　本文附录包含了一个在Servlet环境中利用HSSF创建和返回Excel工作簿的实例。<br />　　<br />　　<b>四、通过usermodel写入文件</b><br />　　<br />　　写入XLS文件比读取XLS文件还要简单。创建一个HSSFWorkbook实例，然后在适当的时候创建一个把文件写入磁盘的OutputStream，但延迟到处理结束时创建OutputStream也可以：<br />　　<br />　　HSSFWorkbook wb = new HSSFWorkbook();<br />　　FileOutputStream fileOut<br />　　= new FileOutputStream("workbook.xls");<br />　　wb.write(fileOut);<br />　　fileOut.close();<br />　　<br />　　创建工作表及其内容必须从相应的父对象出发，例如：<br />　　<br />　　HSSFSheet sheet = wb.createSheet();<br />　　HSSFRow row　　 = sheet.createRow((short)0);<br />　　HSSFCell cell　 = row.createCell((short)0);<br />　　cell.setCellValue(1);<br />　　row.createCell((short)1).setCellValue(1.2);<br />　　row.createCell((short)2).setCellValue("一个字符串");<br />　　row.createCell((short)3).setCellValue(true);<br />　　<br />　　如果要设置单元格的样式，首先要创建一个样式对象，然后把它指定给一个单元格??或者把它指定给多个具有相同样式的单元格，例如，如果Excel表格中有一个摘要行，摘要行的数据必须是粗体、斜体，你可以创建一个summaryRowStyle样式对象，然后把这个样式指定给所有摘要行上的单元格。<br />　　<br />　　注意，CellFormat和CellStyle对象是工作簿对象的成员，单元格对象只是引用它们。<br />　　...<br />　　HSSFCellStyle style = workbook.createCellStyle();<br />　　style.setDataFormat<br />　　(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));<br />　　style.setFillBackgroundColor(HSSFColor.AQUA.index);<br />　　style.setFillPattern(HSSFCellStyle.BIG_SPOTS);<br />　　...<br />　　someCell.setCellStyle(style);<br />　　someOtherCell.setCellStyle(style);<br />　　<br />　　版本较新的HSSF允许使用数量有限的Excel公式。这一功能目前还是“Beta级质量”，正式使用之前务必仔细测试。指定公式的方式类如：someCell.setCellFormula(SUM(A1:A2:);。<br />　　<br />　　当前，公式中已经可以调用所有内建的函数或操作符，但逻辑操作符和函数（例如IF函数）除外，这部分功能目前还在开发之中。 <br /><br /><strong>五、通过eventusermodel读取文件<br /></strong>　　<br />　　通过eventusermodel读取文件要比使用usermodel复杂得多，但效率也要高不少，因为它要求应用程序一边读取数据，一边处理数据。<br />　　<br />　　eventusermodel实际上模拟了DOM环境下SAX处理XML文档的办法，应用程序首先要注册期望处理的数据，eventusermodel将在遇到匹配的数据结构时回调应用程序注册的方法。使用eventusermodel最大的困难在于你必须熟悉Excel工作簿的内部结构。<br />　　<br />　　在HSSF中，低层次的二进制结构称为记录（Record）。记录有不同的类型，每一种类型由org.apache.poi.hssf.record包中的一个Java类描述。例如，BOFRecord记录表示Workbook或Sheet区域的开始，RowRecord表示有一个行存在并保存其样式信息。<br />　　<br />　　所有具有CellValueRecordInterface接口的记录表示Excel的单元格，包括NumericRecord、LabelSSTRecord和FormulaRecord（还有其他一些，其中部分已被弃置不用，部分用于优化处理，但一般而言，HSSF可以转换它们）。<br />　　<br />　　下面是一个注册事件处理句柄的例子：<br />　　<br />　　private EventRecordFactory factory = new EventRecordFactory();<br />　　factory.registerListener(new ERFListener() {<br />　　public boolean processRecord(Record rec) {<br />　　(got BOF Record);<br />　　return true;<br />　　}<br />　　}, new short[] {BOFRecord.sid});<br />　　factory.processRecords(someInputStream);<br />　　<br />　　<b>六、HSSF电子表格结构</b><br />　　<br />　　如前所述，HSSF建立在POIFS的基础上。具体地说，Excel 97+文件是OLE 2复合文档（ OLE 2 Compound Document），底层的OLE 2复合文档保存了一个总是命名为Workbook（Excel 95除外，HSSF不支持Excel 95）的流。<br />　　<br />　　然而，宏和图片并不保存在Workbook流，它们有自己独立的流，有时甚至会放到OLE 2 CDF文件之内的另一个目录。理想情况下，宏也应该被保留，不过目前POI项目中还没有合适的API来处理宏。<br />　　<br />　　每一个流之内是一组记录，一个记录其实就是一个字节数组，可分为记录头、记录体两部分。记录头指明了记录的类型（也即ID）以及后继数据的长度，记录体被分割成多个字段（Field），字段包含数值数据（包括对其他记录的引用）、字符数据或标记。<br />　　<br />　　Excel工作簿的顶级结构：<br />　　<br />　　Bla.xls {<br />　　OLE2CDF headers<br />　　"Workbook" stream {<br />　　Workbook {<br />　　Static String Table Record..<br />　　Sheet names… and pointers<br />　　}<br />　　Sheet {<br />　　ROW<br />　　ROW<br />　　…<br />　　NUMBER RECORD (cell)<br />　　LABELSST Record (cell)<br />　　…<br />　　}<br />　　Sheet<br />　　}<br />　　}<br />　　… images, macros, etc.<br />　　Document Summary<br />　　Summary<br />　　<br />　　<b>七、通过HPSF读取文档属性</b><br />　　<br />　　在Microsoft Word、Excel、PowerPoint等软件中，用户可以通过“文件”→“属性”菜单给文档添加附加信息，包括文档的标题、主题、摘要、类别、关键词等，同时应用软件本身还会加入最后访问的用户、最后访问和修改/打印的日期时间等信息。<br />　　<br />　　文档的属性和正文是分开保存的。如前所述，OLE 2 CDF文件内部就象是一个容器，里面包含许多类似目录和文件的结构，而POIFS就是用来访问其中的文件的工具。这些文件也称为流，文档的属性就保存在POIFS文件系统中专用的流里面。<br />　　<br />　　以一个Word文档为例：虽然在资源管理器中你只看到一个叫做MyFile.doc的文档，其实在这个文档的内部，又包含了一个WordDocument、一个SummaryInformation和一个DocumentSummaryInformation文档；通常还会有其他的文档，这里暂且不管。<br />　　<br />　　你能够猜出这些文档（流）分别包含什么内容吗？不错，WordDocument包含了你在Word里面编辑的文本，文档的属性保存在SummaryInformation和DocumentSummaryInformation流里面。也许将所有属性保存在单个文档里面看起来太简单了，所以Microsoft决心要使用两个流，为了使事情更复杂一点，这两个流的名字前面还加上了八进制的\005字符??这是一个不可打印的字符，因此前面就把它省略了。<br />　　<br />　　Microsoft定义的标准属性有一个好处，它们并不在乎主文档到底是什么类型??不管是Word文档、Excel工作簿还是PowerPoint幻灯。只要你知道如何读取Excel文档的属性，就知道了如何读取其他文档的属性。<br />　　<br />　　读取文档属性其实并不复杂，因为Java程序可以利用POI项目的HPSF包。HPSF是 Horrible Property Set Format的缩写，译成中文就是“讨厌的属性集格式”。HPSF包是POI项目实现的读取属性工具，目前还不支持属性写入。<br />　　<br />　　对于读取Microsoft定义的标准属性，通过HPSF提供的API可以很方便地办到；但如果要读取任意属性集就要用到更一般化的API，可以想象它要比读取标准属性的API复杂不少。本文只介绍读取标准属性的简单API，因为对大多数应用程序来说这已经完全足够了。<br />　　<br />　　下面就是一个读取OLE 2 CDF文档的标题（title）属性的Java程序：<br />　　<br />　　import java.io.*;<br />　　import org.apache.poi.hpsf.*;<br />　　import org.apache.poi.poifs.eventfilesystem.*;<br />　　<br />　　/**<br />　　* 读取OLE 2文档标题的示例程序，<br />　　* 在命令行参数中指定文档的文件名字。<br />　　*/<br />　　<br />　　public class ReadTitle<br />　　{<br />　　public static void main(String[] args) throws IOException<br />　　{<br />　　final String filename = args[0];<br />　　POIFSReader r　　　　 = new POIFSReader();<br />　　r.registerListener(new MyPOIFSReaderListener(),<br />　　"\005SummaryInformation");<br />　　r.read(new FileInputStream(filename));<br />　　}<br />　　<br />　　static class MyPOIFSReaderListener<br />　　implements POIFSReaderListener<br />　　{<br />　　public void processPOIFSReaderEvent(POIFSReaderEvent event)<br />　　{<br />　　SummaryInformation si = null;<br />　　try<br />　　{<br />　　si = (SummaryInformation)<br />　　PropertySetFactory.create(event.getStream());<br />　　}<br />　　catch (Exception ex)<br />　　{<br />　　throw new RuntimeException<br />　　("属性集流\"" + event.getPath() +<br />　　event.getName() + "\": " + ex);<br />　　}<br />　　<br />　　final String title = si.getTitle();<br />　　<br />　　if (title != null)<br />　　System.out.println("标题: \"" + title + "\"");<br />　　else<br />　　System.out.println("该文档没有标题.");<br />　　}<br />　　}<br />　　} <br /><br />main()方法利用POIFS的事件系统从命令行指定的OLE 2文档读取名为\005SummaryInformation的流，当POIFSReader 遇到这个流时，它把控制传递给MyPOIFSReaderListener的processPOIFSReaderEvent()方法。<br />　　<br />　　processPOIFSReaderEvent()到底有什么用呢？它通过参数获得一个输入流，该输入流包含了文档标题等属性。为了访问文档的属性，我们从输入流创建一个PropertySet实例，如下所示：<br />　　<br />　　si = (SummaryInformation) PropertySetFactory.create(event.getStream());<br />　　<br />　　这个语句其实包含三个步骤的操作：<br />　　<br />　　◆ event.getStream()从POIFSReader传入的POIFSReaderEvent获得输入流。<br />　　<br />　　◆ 以刚才获得的输入流为参数，调用PropertySetFactory的静态方法create()。正如其名字所暗示的，PropertySetFactory是一个工厂类，它有一台“机器”能够把一个输入流转换成一个PropertySet实例，这台机器就是create()方法。<br />　　<br />　　◆ 把create()方法返回的PropertySet定型（cast）成为SummaryInformation。PropertySet提供了按照一般办法读取属性集的各种机制，SummaryInformation是PropertySet的子类，即SummaryInformation类在PropertySet类的基础上增加了操作Microsoft标准属性的便捷方法。<br />　　<br />　　在这个处理过程中，可能引起错误的因素很多，因此我们把这部分内容放入了一个try块，不过这个示例程序只按照最简单的方式处理了异常，在实际应用中，最好能够对可能出现的不同异常类型分别处理。<br />　　<br />　　除了一般的I/O异常之外，还有可能遇到HPSF特有的异常，例如，如果输入流不包含属性集或属性集非法，就会抛出NoPropertySetStreamException异常。<br />　　<br />　　有一种错误不太常见，但也不是绝无可能\005SummaryInformation包含一个合法的属性集，但不是摘要信息属性集。如果出现这种情况，则定型成SummaryInformation操作会失败，引发ClassCastException异常。<br />　　<br />　　获得SummaryInformation实例之后，剩下的事情就很简单了，只要调用getTitle()方法，然后输出结果。<br />　　<br />　　除了getTitle()之外，SummaryInformation还包含其他一些便捷方法，例如getApplicationName()、getAuthor()、getCharCount()、和getCreateDateTime()等。HPSF的JavaDoc文档详细说明了所有这些方法。<br />　　<br />　　<b>八、文档摘要信息</b><br />　　<br />　　遗憾的是，并非所有的属性都保存在摘要信息属性集之中。许多（但不是全部）OLE 2文件还有另一个属性集，称为“文档摘要信息”，对应的流是\005DocumentSummaryInformation。这个属性集保存的属性包括文档的类别、PowerPoint幻灯的多媒体剪辑数量，等等。<br />　　<br />　　要访问文档摘要信息属性集，程序的处理过程也和上例相似，只是注册的目标应该改成\005DocumentSummaryInformation有时，你可能想要同时注册到摘要信息和文档摘要信息这两个流。其余的处理方式和前面的例子差不多，你应该把包含文档摘要信息的流传递给PropertySetFactory.create()，但这次工厂方法将返回一个DocumentSummaryInformation对象（而不是前面例子中的SummaryInformation对象）。<br />　　<br />　　如果同时注册到了两个流，注意检查返回值的具体类型，或者使用Java的instanceof操作符，或者使用专用的isSummaryInformation()和isDocumentSummaryInformation()方法。记住，create()方法返回的总是一个PropertySet对象，因此你总是可以对create()返回对象调用isSummaryInformation()和isDocumentSummaryInformation()方法，PropertySet类之所以要提供这两个方法，是因为属性集可能是自定义的。<br />　　<br />　　如果你想要处理自定义的属性集，或者要从标准的属性集读取用户定义的属性，必须使用一个更一般化的API，前面已经提到，这个API要复杂得多，本文不再讨论，请参见HPSF的HOW-TO文档和POI的文档。<br />　　<br />　　结束语：本文探讨了HSSF的应用以及如何输出到Excel文件，另外还涉及了HPSF以及如何读取属性集文档摘要信息。POI是一个功能非常强大的项目，许多主题本文尚未涉及，例如如何用HSSF Serializer将XML文档转换成Excel格式等，这一切仍有待您去研究了。<br />　　<br />　　<b>九、附录</b><br />　　<br />　　实例：利用Servlet创建和返回一个工作簿。<br />　　<br />　　package org.apache.poi.hssf.usermodel.examples;<br />　　<br />　　import java.io.*;<br />　　import java.net.*;<br />　　import javax.servlet.*;<br />　　import javax.servlet.http.*;<br />　　import org.apache.poi.hssf.usermodel.*;<br />　　<br />　　public class HSSFCreate extends HttpServlet {<br />　　public void init(ServletConfig config)<br />　　throws ServletException {<br />　　super.init(config);<br />　　}<br />　　<br />　　public void destroy() {<br />　　}<br />　　<br />　　/** 处理HTTP GET 和POST请求<br />　　* @param request：请求<br />　　* @param response：应答<br />　　*/<br />　　protected void processRequest(HttpServletRequest request,<br />　　HttpServletResponse response)<br />　　throws ServletException, IOException {<br />　　<br />　　response.setContentType("application/vnd.ms-excel");<br />　　HSSFWorkbook wb = new HSSFWorkbook();<br />　　HSSFSheet sheet = wb.createSheet("new sheet");<br />　　<br />　　// 创建一个新的行，添加几个单元格。<br />　　// 行号从0开始计算<br />　　HSSFRow row　　 = sheet.createRow((short)0);<br />　　// 创建一个单元格，设置单元格的值<br />　　HSSFCell cell　 = row.createCell((short)0);<br />　　cell.setCellValue(1);<br />　　<br />　　row.createCell((short)1).setCellValue(1.2);<br />　　row.createCell((short)2).setCellValue("一个字符串值");<br />　　row.createCell((short)3).setCellValue(true);<br />　　// 写入输出结果<br />　　OutputStream out = response.getOutputStream();<br />　　wb.write(out);<br />　　out.close();<br />　　}<br />　　<br />　　/** 处理HTTP GET请求<br />　　* @param request：请求<br />　　* @param response：应答<br />　　*/<br />　　protected void doGet(HttpServletRequest request,<br />　　HttpServletResponse response)<br />　　throws ServletException, IOException {<br />　　processRequest(request, response);<br />　　}<br />　　<br />　　/** 处理HTTP POST请求<br />　　* @param request：请求<br />　　* @param response：应答<br />　　*/<br />　　protected void doPost(HttpServletRequest request,<br />　　HttpServletResponse response)<br />　　throws ServletException, IOException {<br />　　processRequest(request, response);<br />　　}<br />　　<br />　　/** 返回关于Servlet的简单说明<br />　　*/<br />　　public String getServletInfo() {<br />　　return "示例：在Servlet中用HSSF创建Excel工作簿";<br />　　}<br />　　} <br /></font>
<img src ="http://www.blogjava.net/hallywang/aggbug/77218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-10-25 16:03 <a href="http://www.blogjava.net/hallywang/archive/2006/10/25/77218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JOB 用法小结 (转)</title><link>http://www.blogjava.net/hallywang/archive/2006/10/10/74312.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Tue, 10 Oct 2006 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/10/10/74312.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/74312.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/10/10/74312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/74312.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/74312.html</trackback:ping><description><![CDATA[
		<span class="bold">JOB 用法小结</span>
		<br />
		<br />
		<div style="FONT-SIZE: 12px">
				<br />一、设置初始化参数 job_queue_processes<br /><br />sql&gt; alter system set job_queue_processes=n;<font color="red"><b>（n&gt;0）</b></font><br />job_queue_processes最大值为1000<br /><br />查看job queue 后台进程<br />sql&gt;select name,description from v$bgprocess;<br /><br />二，dbms_job package 用法介绍<br />包含以下子过程： <br /><br />Broken()过程。<br />change()过程。<br />Interval()过程。<br />Isubmit()过程。<br />Next_Date()过程。<br />Remove()过程。<br />Run()过程。<br />Submit()过程。<br />User_Export()过程。<br />What()过程。<br /><br />1、<br />Broken()过程更新一个已提交的工作的状态，典型地是用来把一个已破工作标记为未破工作。<br />这个过程有三个参数：job 、broken与next_date。<br /><br />PROCEDURE Broken (job       IN binary_integer,<br />                  Broken    IN boolean,<br />                  next_date IN date :=SYSDATE)<br /><br />job参数是工作号，它在问题中唯一标识工作。<br />broken参数指示此工作是否将标记为破——TRUE说明此工作将标记为破，而FLASE说明此工作将标记为未破。<br />next_date参数指示在什么时候此工作将再次运行。此参数缺省值为当前日期和时间。<br />job如果由于某种原因未能成功之行，oracle将重试16次后，还未能成功执行，将被标记为broken<br />重新启动状态为broken的job，有如下两种方式;<br />a、利用dbms_job.run()立即执行该job<br />   sql&gt;begin<br />   sql&gt;dbms_job.run(:jobno) 该jobno为submit过程提交时返回的job number<br />   sql&gt;end;<br />   sql&gt;/<br />b、利用dbms_job.broken()重新将broken标记为false<br />   sql&gt;begin<br />   sql&gt;dbms_job.broken (:job,false,next_date)<br />   sql&gt;end;<br />   sql&gt;/<br />2、<br />Change()过程用来改变指定工作的设置。<br />这个过程有四个参数：job、what 、next_date与interval。<br /><br />PROCEDURE Change (job        IN binary_integer,<br />                  What       IN varchar2,<br />                  next_date  IN date,<br />                  interval   IN varchar2)<br /><br />此job参数是一个整数值，它唯一标识此工作。<br />What参数是由此工作运行的一块PL/SQL代码块。<br />next_date参数指示何时此工作将被执行。<br />interval参数指示一个工作重执行的频度。<br /><br />3、<br />Interval()过程用来显式地设置重执行一个工作之间的时间间隔数。<br />这个过程有两个参数：job与interval。<br /><br />PROCEDURE Interval (job      IN binary_integer,<br />                    Interval IN varchar2)<br /><br />job参数标识一个特定的工作。interval参数指示一个工作重执行的频度。<br /><br /><br /><br />4、<br />ISubmit()过程用来用特定的工作号提交一个工作。<br />这个过程有五个参数：job、what、next_date、interval与no_parse。<br /><br />PROCEDURE ISubmit (job       IN binary_ineger,<br />                   What      IN varchar2,<br />                   next_date IN date,<br />                   interval  IN varchar2,<br />                   no_parse  IN booean:=FALSE)<br /><br />这个过程与Submit()过程的唯一区别在于此job参数作为IN型参数传递且包括一个<br />由开发者提供的工作号。如果提供的工作号已被使用，将产生一个错误。<br /><br /><br />5、<br />Next_Date()过程用来显式地设定一个工作的执行时间。这个过程接收两个参数：job与next_date。<br /><br />PROCEDURE Next_Date(job         IN binary_ineger,<br />                    next_date   IN date)<br /><br />job标识一个已存在的工作。next_date参数指示了此工作应被执行的日期与时间。<br /><br /><br /><br />6、<br />Remove()过程来删除一个已计划运行的工作。这个过程接收一个参数：<br /><br />PROCEDURE Remove(job IN  binary_ineger);<br /><br />job参数唯一地标识一个工作。这个参数的值是由为此工作调用Submit()过程返回的job参数的值。<br />已正在运行的工作不能由调用过程序删除。<br /><br /><br /><br />7、<br />Run()过程用来立即执行一个指定的工作。这个过程只接收一个参数：<br /><br />PROCEDURE Run(job IN binary_ineger) <br /><br />job参数标识将被立即执行的工作。<br /><br /><br /><br />8、<br />使用Submit()过程，工作被正常地计划好。<br />这个过程有五个参数：job、what、next_date、interval与no_parse。<br /><br />PROCEDURE Submit ( job       OUT binary_ineger,<br />                   What      IN  varchar2,<br />                   next_date IN  date,<br />                   interval  IN  varchar2,<br />                   no_parse  IN  booean:=FALSE)<br /><br />job参数是由Submit()过程返回的binary_ineger。这个值用来唯一标识一个工作。<br />what参数是将被执行的PL/SQL代码块。<br />next_date参数指识何时将运行这个工作。<br />interval参数何时这个工作将被重执行。<br />no_parse参数指示此工作在提交时或执行时是否应进行语法分析——TRUE<br />指示此PL/SQL代码在它第一次执行时应进行语法分析，<br />而FALSE指示本PL/SQL代码应立即进行语法分析。<br /><br /><br /><br />9、<br />User_Export()过程返回一个命令，此命令用来安排一个存在的工作以便此工作能重新提交。<br />此程序有两个参数：job与my_call。<br /><br />PROCEDURE User_Export(job        IN binary_ineger,<br />                      my_call    IN OUT varchar2)<br /><br />job参数标识一个安排了的工作。my_call参数包含在它的当前状态重新提交此工作所需要<br />的正文。<br /><br /><br /><br />10、<br />What()过程应许在工作执行时重新设置此正在运行的命令。这个过程接收两个参数：job与what。<br /><br />PROCEDURE What (job  IN binary_ineger,<br />                What IN OUT varchar2)<br /><br />job参数标识一个存在的工作。what参数指示将被执行的新的PL/SQL代码。<br /><br /><br />三、查看相关job信息<br />1、相关视图<br />dba_jobs<br />all_jobs<br />user_jobs<br />dba_jobs_running 包含正在运行job相关信息<br /><br />2、查看相关信息<br /><br />SQL&gt;SELECT JOB, NEXT_DATE, NEXT_SEC, FAILURES, BROKEN<br />SQL&gt;FROM DBA_JOBS;<br /><br />JOB NEXT_DATE NEXT_SEC FAILURES B<br />------- --------- -------- -------- -<br />9125 01-JUN-01 00:00:00 4 N<br />14144 24-OCT-01 16:35:35 0 N<br />9127 01-JUN-01 00:00:00 16 Y<br />3 rows selected.<br /><br />正在运行的JOB相关信息<br /><br />SELECT SID, r.JOB, LOG_USER, r.THIS_DATE, r.THIS_SEC<br />FROM DBA_JOBS_RUNNING r, DBA_JOBS j<br />WHERE r.JOB = j.JOB;<br /><br />SID JOB LOG_USER THIS_DATE THIS_SEC<br />----- ---------- ------------- --------- --------<br />12 14144 HR 24-OCT-94 17:21:24<br />25 8536 QS 24-OCT-94 16:45:12<br />2 rows selected.<br />  <br />JOB QUEUE LOCK相关信息<br /><br />SELECT SID, TYPE, ID1, ID2<br />FROM V$LOCK<br />WHERE TYPE = 'JQ';<br /><br />SID TY ID1 ID2<br />--------- -- --------- ---------<br />12 JQ 0 14144<br />1 row selected.<br /><br />四、简单例子<br /><br />一个简单例子： <br /><br />创建测试表<br />SQL&gt; create table TEST(a date);<br /><br />表已创建。<br /><br />创建一个自定义过程<br />SQL&gt; create or replace procedure MYPROC as<br />  2  begin<br />  3  insert into TEST values(sysdate);<br />  4  end;<br />  5  /<br /><br />过程已创建。<br /><br />创建JOB<br />SQL&gt; variable job1 number;<br />SQL&gt; <br />SQL&gt; begin<br />  2  dbms_job.submit(:job1,'MYPROC;',sysdate,'sysdate+1/1440');　　--每天1440分钟，即一分钟运行test过程一次<br />  3  end;<br />  4  /<br /><br />PL/SQL 过程已成功完成。<br /><br />运行JOB<br />SQL&gt; begin<br />  2  dbms_job.run(:job1);<br />  3  end;<br />  4  /<br /><br />PL/SQL 过程已成功完成。<br /><br />SQL&gt; select to_char(a,'yyyy/mm/dd hh24:mi:ss') 时间 from TEST;<br /><br />时间<br />-------------------<br />2001/01/07 23:51:21<br />2001/01/07 23:52:22<br />2001/01/07 23:53:24<br /><br />删除JOB<br />SQL&gt; begin<br />  2  dbms_job.remove(:job1);<br />  3  end;<br />  4  /<br /><br />PL/SQL 过程已成功完成。<br />五、相关注意事项<br /><br />1、执行dbms_job包相关过程如remove、Change、broken时，登陆的用户要同建立该JOB的用户一致<br /><br />2、当执行dbms_job.change过程时，如果参数what,next_date,interval值为null，则表示原参数值不变<br />如<br />BEGIN<br />DBMS_JOB.CHANGE(14144, NULL, NULL, 'SYSDATE + 3');<br />END;<br />/<br /><br />3、如果利用database link来提交job，则该link必须包含合适的用户名和密码。<br /><br />4、执行job的用户必须具有作业过程中所涉及对象的相应权限。<br /><br />5、数据库在restricted mode下，不能执行job<br /><br /></div>
<img src ="http://www.blogjava.net/hallywang/aggbug/74312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-10-10 16:03 <a href="http://www.blogjava.net/hallywang/archive/2006/10/10/74312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle dba 职责 【转】</title><link>http://www.blogjava.net/hallywang/archive/2006/10/09/74027.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 09 Oct 2006 03:52:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/10/09/74027.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/74027.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/10/09/74027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/74027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/74027.html</trackback:ping><description><![CDATA[
		<font color="#333333">转自：<a href="http://www.linuxmine.com/49842.html">http://www.linuxmine.com/49842.html</a>　<br /><br />ORACLE数据库管理员应按如下方式对ORACLE数据库系统做定期监控： <br />　　(1). 每天对ORACLE数据库的运行状态,日志文件,备份情况,数据 库的空间使用情况,系统资源的使用情况进行检查,发现并解决 问题。 <br />　　(2). 每周对数据库对象的空间扩展情况,数据的增长情况进行监控,对数据库做健康检查,对数据库对象的状态做检查。 <br />　　(3). 每月对表和索引等进行Analyze,检查表空间碎片,寻找数据库 性能调整的机会,进行数据库性能调整,提出下一步空间管理计划。对ORACLE数据库状态进行一次全面检查。 每天的工作 <br />　　(1).确认所有的INSTANCE状态正常登陆到所有数据库或例程,检测ORACLE后台进程: <br />　　$ps ?ef|grep ora <br />　　(2). 检查文件系统的使用（剩余空间）。如果文件系统的剩余空间小于20%，需删除不用的文件以释放空间。 <br />　　$df ?k <br />　　(3). 检查日志文件和trace文件记录alert和trace文件中的错误。连接到每个需管理的系统 <br />　　使用’telnet’ <br />　　对每个数据库,cd 到bdump目录,通常是$ORACLE_BASE/&lt;SID&gt;/bdump <br />　　使用 Unix ‘tail’命令来查看alert_&lt;SID&gt;.log文件 <br />　　如果发现任何新的ORA- 错误,记录并解决 <br />　　(4). 检查数据库当日备份的有效性。 <br />　　对RMAN备份方式: <br />　　检查第三方备份工具的备份日志以确定备份是否成功 <br />　　对EXPORT备份方式: <br />　　检查exp日志文件以确定备份是否成功 <br />　　对其他备份方式: <br />　　检查相应的日志文件 <br />　　(5). 检查数据文件的状态记录状态不是“online”的数据文件，并做恢复。 <br />　　Select file_name from dba_data_files where status=’OFFLINE’ <br />　　(6). 检查表空间的使用情况 <br />　　SELECT tablespace_name, max_m, count_blocks free_blk_cnt, sum_free_m,to_char(100*sum_free_m/sum_m, '99.99') || '%' AS pct_free <br />　　FROM ( SELECT tablespace_name,sum(bytes)/1024/1024 AS sum_m FROM dba_data_files GROUP BY tablespace_name), <br />　　( SELECT tablespace_name AS fs_ts_name, max(bytes)/1024/1024 AS max_m, count(blocks) AS count_blocks, sum(bytes/1024/1024) AS sum_free_m FROM dba_free_space GROUP BY tablespace_name ) <br />　　WHERE tablespace_name = fs_ts_name <br />　　(7). 检查剩余表空间 <br />　　SELECT tablespace_name, sum ( blocks ) as free_blk , <br />　　trunc ( sum ( bytes ) /(1024*1024) ) as free_m, <br />　　max ( bytes ) / (1024) as big_chunk_k, count (*) as num_chunks <br />　　FROM dba_free_space GROUP BY tablespace_name; <br />　　(8). 监控数据库性能 <br />　　运行bstat/estat生成系统报告 <br />　　或者使用statspack收集统计数据 <br />　　(9). 检查数据库性能，记录数据库的cpu使用、IO、buffer命中率等等 <br />　　使用vmstat,iostat,glance,top等命令 <br />　　(10). 日常出现问题的处理。 <br />　　每周的工作 <br />　　(1). 控数据库对象的空间扩展情况 <br />　　根据本周每天的检查情况找到空间扩展很快的数据库对象,并采取相 <br />　　应的措施 <br />　　-- 删除历史数据 <br />　　--- 扩表空间 <br />　　alter tablespace &lt;name&gt; add datafile ‘&lt;file&gt;’ size &lt;size&gt; <br />　　--- 调整数据对象的存储参数 <br />　　next extent <br />　　pct_increase <br />　　(2). 监控数据量的增长情况 <br />　　根据本周每天的检查情况找到记录数量增长很快的数据库对象,并采 <br />　　取相应的措施 <br />　　-- 删除历史数据 <br />　　--- 扩表空间 <br />　　alter tablespace &lt;name&gt; add datafile ‘&lt;file&gt;’ size &lt;size&gt; <br />　　(3). 系统健康检查 <br />　　检查以下内容: <br />　　init&lt;sid&gt;.ora <br />　　controlfile <br />　　redo log file <br />　　archiving <br />　　sort area size <br />　　tablespace(system,temporary,tablespace fragment) <br />　　datafiles(autoextend,location) <br />　　object(number of extent,next extent,index) <br />　　rollback segment <br />　　logging &amp;tracing(alert.log,max_dump_file_size,sqlnet) <br />　　(4). 检查无效的数据库对象 <br />　　SELECT owner, object_name, object_type FROM dba_objects <br />　　WHERE status=’INVALID’。 <br />　　(5). 检查不起作用的约束 <br />　　SELECT owner, constraint_name, table_name, <br />　　constraint_type, status <br />　　FROM dba_constraints <br />　　WHERE status = 'DISABLED’ AND constraint_type = 'P' <br />　　(6). 检查无效的trigger <br />　　SELECT owner, trigger_name, table_name, status <br />　　FROM dba_triggers <br />　　WHERE status = 'DISABLED’ <br />　　每月的工作 <br />　　(1). Analyze Tables/Indexes/Cluster <br />　　analyze table &lt;name&gt; estimate statistics sample 50 percent; <br />　　(2). 检查表空间碎片 <br />　　根据本月每周的检查分析数据库碎片情况,找到相应的解决方法 <br />　　(3). 寻找数据库性能调整的机会 <br />　　比较每天对数据库性能的监控报告,确定是否有必要对数据库性能进 行调整 <br />　　(4). 数据库性能调整 <br />　　如有必要,进行性能调整 <br />　　(5). 提出下一步空间管理计划 <br />　　根据每周的监控,提出空间管理的改进方法<br />　　<br />　　<b>Oracle DBA 日常管理</b><br />　　目的：这篇文档有很详细的资料记录着对一个甚至更多的ORACLE 数据库每天的，每月的， 每年的运行的状态的结果及检查的结果，在文档的附录中你将会看到所有检查，修改的SQL 和PL/SQL 代码。 <br />　　目录 <br />　　1.日常维护程序 <br />　　A． 检查已起的所有实例 <br />　　B． 查找一些新的警告日志 <br />　　C． 检查DBSNMP 是否在运行 <br />　　D． 检查数据库备份是否正确 <br />　　E． 检查备份到磁带中的文件是否正确 <br />　　F． 检查数据库的性能是否正常合理，是否有足够的空间和资源 <br />　　G． 将文档日志复制到备份的数据库中 <br />　　H． 要常看DBA 用户手册 <br />　　2.晚间维护程序 <br />　　A．收集VOLUMETRIC 的数据 <br />　　3.每周维护工作 <br />　　A． 查找那些破坏规则的OBJECT <br />　　B． 查找是否有违反安全策略的问题 <br />　　C． 查看错误地方的SQL*NET 日志 <br />　　D． 将所有的警告日志存档 <br />　　E． 经常访问供应商的主页 <br />　　4.月维护程序 <br />　　A． 查看对数据库会产生危害的增长速度 <br />　　B． 回顾以前数据库优化性能的调整 <br />　　C． 查看I/O 的屏颈问题 <br />　　D． 回顾FRAGMENTATION <br />　　E． 将来的执行计划 <br />　　F． 查看调整点和维护 <br />　　5.附录 <br />　　A． 月维护过程 <br />　　B． 晚间维护过程 <br />　　C． 周维护过程 <br />　　<br />　　<b>一．日维护过程 </b><br />　　A．查看所有的实例是否已起确定数据库是可用的，把每个实例写入日志并且运行日报告或是运行测试 文件。当然有一些操作我们是希望它能自动运行的。 可选择执行：用ORACLE 管理器中的‘PROBE’事件来查看 <br />　　B．查找新的警告日志文件 <br />　　1. 联接每一个操作管理系统 <br />　　2. 使用‘TELNET’或是可比较程序 <br />　　3. 对每一个管理实例，经常的执行$ORACLE_BASE/&lt;SID&gt;/bdump 操 作，并使其能回退到控制数据库的SID。 <br />　　4. 在提示下，使用UNIX 中的‘TAIL’命令查看alert_&lt;SID&gt;.log，或是 用其他方式检查文件中最近时期的警告日志 <br />　　5. 如果以前出现过的一些ORA_ERRORS 又出现，将它记录到数据库 恢复日志中并且仔细的研究它们，这个数据库恢复日志在〈FILE〉中 <br />　　C．查看DBSNMP 的运行情况 检查每个被管理机器的‘DBSNMP’进程并将它们记录到日志中。 在UNIX 中，在命令行中，键入ps ?ef | grep dbsnmp,将回看到2 个 DBSNMP 进程在运行。如果没有，重启DBSNMP。 <br />　　D．查数据库备份是否成功 <br />　　E．检查备份的磁带文档是否成功 <br />　　F．检查对合理的性能来说是否有足够的资源 <br />　　1. 检查在表空间中有没有剩余空间。对每一个实例来说，检查在表空间中是否存在有剩余空间来满足当天 的预期的需要。当数据库中已有的数据是稳定的，数据日增长的平均 数也是可以计算出来，最小的剩余空间至少要能满足每天数据的增 长。 <br />　　A） 运行‘FREE.SQL’来检查表空间的剩余空间。 <br />　　B） 运行‘SPACE.SQL’来检查表空间中的剩余空间百分率 <br />　　2. 检查回滚段回滚段的状态一般是在线的，除了一些为复杂工作准备的专用 段，它一般状态是离线的。 <br />　　a) 每个数据库都有一个回滚段名字的列表。 <br />　　b) 你可以用V$ROLLSTAT 来查询在线或是离线的回滚段的现在状 态. <br />　　c) 对于所有回滚段的存储参数及名字， 可用DBA_ROLLBACK_SEGS 来查询。但是它不如V$ROLLSTAT 准确。 <br />　　3. 识别出一些过分的增长查看数据库中超出资源或是增长速度过大的段，这些段的存储参 数需要调整。 <br />　　a） 收集日数据大小的信息， 可以用‘ANALYZE5PCT.SQL’。如果你收集的是每晚的信息， 则可跳过这一步。 <br />　　b） 检查当前的范围，可用‘NR.EXTENTS.SQL’。 <br />　　c） 查询当前表的大小信息。 <br />　　d） 查询当前索引大小的信息。 <br />　　e） 查询增长趋势。 <br />　　4. 确定空间的范围。如果范围空间对象的NEXT_EXTENT 比表空间所能提供的最大范围还要大，那么这将影响数据库的运行。如果我们找到了这个目标，可以用‘ALTER TABLESPACE COALESCE’调查它的位置，或加另外 的数据文件。 <br />　　A）运行‘SPACEBOUND.SQL’。如果都是正常的，将不返回任何行。 <br />　　5. 回顾CPU，内存，网络，硬件资源论点的过程 <br />　　A）检查CPU的利用情况，进到x:\web\phase2\default.htm =&gt;system metrics=&gt;CPU 利用页，CPU 的最大限度为400，当CPU 的占用保持在350 以上</font>
<img src ="http://www.blogjava.net/hallywang/aggbug/74027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-10-09 11:52 <a href="http://www.blogjava.net/hallywang/archive/2006/10/09/74027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tar命令详解</title><link>http://www.blogjava.net/hallywang/archive/2006/05/09/45240.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Tue, 09 May 2006 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/05/09/45240.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/45240.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/05/09/45240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/45240.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/45240.html</trackback:ping><description><![CDATA[
		<table style="TABLE-LAYOUT: fixed" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td valign="top">
										<p>tar <br />格式： tar 选项 文件目录列表 <br />功能： 对文件目录进行打包备份 <br />选项：<br />-c 建立新的归档文件<br />-r 向归档文件末尾追加文件<br />-x 从归档文件中解出文件<br />-O 将文件解开到标准输出<br />-v 处理过程中输出相关信息<br />-f 对普通文件操作<br />-z 调用gzip来压缩归档文件，与-x联用时调用gzip完成解压缩<br />-Z 调用compress来压缩归档文件，与-x联用时调用compress完成解压缩 <br />实例1： 目的：用tar打包一个目录下的文件<br />命令：＃tar -cvf /mnt/lgx/a1.doc<br />结果：产生一个以.tar为扩展名的打包文件 <br />实例2： 目的：用tar解开打包文件<br />命令：＃tar -xvf /mnt/lgx/a1.doc.tar<br />附加说明：在通常情况下，tar打包与gzip（压缩）经常联合使用，效果更好。方法是：<br />首先用tar打包，如：＃tar -cvf /mnt/lgx/a1.doc （产生a1.doc.tar文件）<br />然后用gzip压缩a1.doc.tar文件，如：＃gzip /mnt/lgx/a1.doc.tar （产生a1.doc.tar.gz文件） <br />实例3： 目的：解压a1.doc.tar.gz文件<br />方法1：<br />＃gzip -dc /mnt/lgx/a1.doc.tar.gz （产生a1.doc.tar文件）<br />＃tar -xvf /mnt/lgx/a1.doc.tar （产生a1.doc文件）<br />这两次命令也可使用管道功能，把两个命令合二为一：<br />＃gzip -dc /mnt/lgx/a1.doc.tar.gz | tar -xvf<br />方法2：使用tar提供的自动调用gzip解压缩功能<br />＃tar -xzvf /mnt/lgx/a1.doc.tar.gz<br />经过tar打包后，也可用compress命令压缩（注：gzip比compress压缩更加有效），产生一个以.tar.Z的文件，在解包时，可先用“uncompress 文件名”格式解压，然后用“tar -xvf 文件名”解包。也可直接调用“tar -Zxvf 文件名”解包。<br /><br /></p> </td>
						</tr>
				</tbody>
		</table>
		<div class="posted">Posted by <span id="n_109">bd4rfk</span> <span id="t_109">2006-3-27 11:21:00</span></div>
		<div class="entry">
				<table style="TABLE-LAYOUT: fixed" cellspacing="0" cellpadding="0" width="100%" border="0">
						<tbody>
								<tr>
										<td valign="top">
												<span id="c_109">
														<p>举几个例子：</p>
														<p>例一：将整个/etc目录下的文件全部打包成为/tmp/etc.tar<br />tar -cvf /tmp/etc.tar /etc  #仅打包，不压缩<br />tar -zcvf /tmp/etc.tar.gz /etc  #打包后，以gzip压缩<br />tar -jcvf /tmp/etc.tar.bz2 /etc  #打包后，以bzip2压缩</p>
														<p>例二：查阅上述/tmp/etc.tar.gz文件内有哪些文件<br />tar -ztvf /tmp/etc.tar.gz</p>
														<p>例三：将/tmp/etc.tar.gz文件解压缩到/usr/local/src下<br />cd /usr/local/src   #先将工作目录变换到/usr/local/src下<br />tar -zxvf /tmp/etc.tar.gz<br />  <br />例四：只将/tmp/etc.tar.gz内的etc/passwd解压到/tmp下<br />cd /tmp<br />tar -zxvf /tmp/etc.tar.gz etc/passwd</p>
														<p>例五：将/etc内的所有文件备份下来，并且保存其权限！<br />tar -zxvpf /tmp/etc.tar.gz /etc</p>
														<p>例六：在/home当中，比2005/06/01新的文件才备份<br />tar -N '2005/06/01' -zcvf home.tar.gz /home</p>
														<p>例七：备份/home、/etc，但不要/home/dmtsai<br />tar --exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc</p>
														<p>例八：将/etc打包后直接解开在/tmp底下，而不产生文件！<br />cd /tmp<br />tar -cvf - /etc | tar -xvf -</p>
												</span>
										</td>
								</tr>
						</tbody>
				</table>
		</div>
<img src ="http://www.blogjava.net/hallywang/aggbug/45240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-05-09 16:49 <a href="http://www.blogjava.net/hallywang/archive/2006/05/09/45240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在J2ME开发中解析XML [转]</title><link>http://www.blogjava.net/hallywang/archive/2006/04/24/42798.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 24 Apr 2006 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/04/24/42798.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/42798.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/04/24/42798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/42798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/42798.html</trackback:ping><description><![CDATA[
		<table cellspacing="10" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="fonttitle_content" align="middle" height="40">在J2ME开发中解析XML</td>
						</tr>
						<tr>
								<td align="middle" bgcolor="#f6f6f6" height="24">
										<a href="http://www.52rd.com/">www.52RD.com</a>　2005年12月22日　我爱研发网　mingjava</td>
						</tr>
						<tr>
								<td align="middle">
										<script type="text/javascript">
												<!--
google_ad_client = "pub-3720468914994936";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel ="";
google_color_border = "F7F7F7";
google_color_bg = "F7F7F7";
google_color_link = "333366";
google_color_url = "666666";
google_color_text = "666666";
//-->
										</script>
										<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
										</script>
								</td>
						</tr>
						<tr>
								<td class="fontbig">目前,XML已经广泛应用于数据交换领域，xml是基于纯文本的，具有优秀的跨平台特性。本文将讲述如何在J2ME中解析XML进行数据传输。 
<p>    XML写法比较简单，而且非常便于人来阅读。但是必须在客户端和服务器端有XML的解析器才可以正常通信，由于初期的移动信息设备内存和处理器上的不足，所以在MIDP1.0中并没有提供对XML的支持。随着内存和处理器的提高，对XML的支持成为了可能。在JSR182中提供了XML的解析器，但是这并不是标准MIDP中的API需要特定的实现才可以支持。幸运的是有第三方的API对解析xml提供了支持，比较有名的是kxml和nanoxml。</p><p>    使用XML之前，你必须考虑好是不是必须用它来传输数据，因为解析xml是比较耗费资源的，尤其是在CPU和内存的资源都很宝贵的条件下。如果我们能使用DataInputStream和DataOutputStream传输的话就尽量不要使用XML。XML的解析器有两种，一种是确认性的，他在解析之前会对xml的文档进行有效性的验证，确保这是应用程序需要的。另一种则是非确认性的，他不做验证工作直接进行解析，无疑这样的速度会快。kxml和nanoxml都是这样的解析器。它们也存在差别，kxml是增量解析器他会一点一点的解析，这样在解析大的文档的时候会效率比较高。nanoxml是一步解析器，一次就把文档解析完，如果文档很大的话，这无疑会耗费很大的内存。要使用kxml你可以从<a href="http://www.kxml.org/">http://www.kxml.org </a>下载得到,在<a href="http://nanoxml.sourceforge.net/">http://nanoxml.sourceforge.net</a> 你可以下载nanoxml。</p><p>    要使用kxml，你必须首先得到一个XmlParser实例，它用Reader作为构造器的参数：<br />try {<br />    Reader    r = .....;<br />    XmlParser parser = new XmlParser( r );<br />}<br />catch( java.io.IOException e ){<br />    // handle exception....<br />}</p><p>如果你的xml文档存储在String内的话你可以使用ByteArrayInputStream和InputStreamReader：<br />String    xml = "&lt;a&gt;some xml&lt;/a&gt;";<br />ByteArrayInputStream bin = <br />            new ByteArrayInputStream( xml.getBytes() );<br />XmlParser parser = new XmlParser( new InputStreamReader( bin ) );<br />当从网上接收数据的时候可以这样：<br />HttpConnection    conn = .....;<br />InputStreamReader doc = <br />         new InputStreamReader( conn.openInputStream() );<br />XmlParser parser = new XmlParser( doc );<br />得到parser实例后我们就可以调用read方法进行解析了，read方法会返回一个ParseEvent,通过判断他的类型我们就可以解析xml了。<br />try {<br />    boolean keepParsing = true;<br />        <br />    while( keepParsing ){<br />        ParseEvent event = parser.read();<br /> <br />        switch( event.getType() ){<br />            case Xml.START_TAG:<br />                ..... // handle start of an XML tag<br />                break;<br />            case Xml.END_TAG:<br />                ..... // handle end of an XML tag<br />                break;<br />            case Xml.TEXT:<br />                ..... // handle text within a tag<br />                break;<br />            case Xml.WHITESPACE:<br />                ..... // handle whitespace<br />                break;<br />            case Xml.COMMENT:<br />                ..... // handle comment<br />                break;<br />            case Xml.PROCESSING_INSTRUCTION:<br />                ..... // handle XML PI<br />                break;<br />            case Xml.DOCTYPE:<br />                ..... // handle XML doctype<br />                break;<br />            case Xml.END_DOCUMENT:<br />                ..... // end of document;<br />                keepParsing = false;<br />                break;<br />        }<br />    }<br />}<br />catch( java.io.IOException e ){<br />}</p><p>如果想使用nanoxml，那么你首先要创建一个kXMLElement实例，然后调用parseFromReader、parseString或者parseCharArray。由于他是一步解析器，那么它会把整个文档解析完后生成一个Object tree。每个节点都是一个kXMLElement的实例，通过调用getChildren等方法可以在这棵树上导航。<br />HttpConnection    conn = .....;<br />InputStreamReader doc = <br />         new InputStreamReader( conn.openInputStream() );<br />kXMLElement       root = new kXMLElement();</p><p>try {<br />    root.parseFromReader( doc );<br />}<br />catch( kXMLParseException pe ){<br />}<br />catch( IOException ie ){<br />}</p><p>下面是一个J2ME的应用程序简单演示了如何解析xml。如果有时间可以写写复杂的测试程序。你可以从如下地址下载源代码：<a href="http://www.j2medev.com/Article/UploadFiles/2004828105441118.zip"><font color="#1a6be6">XMLTest</font></a>. 里面包括了kxml和nanoxml的源代码，如果想得到最新的源代码请参考他们的官方网站，在本站提供了kxml的<a href="http://www.j2medev.com/Article/api/kxml2/index.html"><font color="#113dee">在线API</font><br /></a>package com.ericgiguere.techtips;</p><p>import java.io.*;<br />import java.util.*;<br />import javax.microedition.lcdui.*;<br />import javax.microedition.midlet.*;<br />import nanoxml.*;<br />import org.kxml.*;<br />import org.kxml.parser.*;</p><p>/**<br /> * Simple MIDlet that demonstrates how an XML document can be<br /> * parsed using kXML or NanoXML.<br /> */</p><p>public class XMLTest extends MIDlet {</p><p>    // Our XML document -- normally this would be something you<br />    // download.<br />    <br />    private static String xmlDocument =<br />        "&lt;list&gt;&lt;item&gt;apple&lt;/item&gt;" +<br />              "&lt;item&gt;orange&lt;/item&gt;" +<br />              "&lt;item&gt;pear&lt;/item&gt;&lt;/list&gt;";<br />              <br />    private Display display;<br />    private Command exitCommand = new Command( "Exit",<br />                                               Command.EXIT, 1 );<br />                                               <br />    public XMLTest(){<br />    }<br />    <br />    protected void destroyApp( boolean unconditional )<br />                       throws MIDletStateChangeException {<br />        exitMIDlet();<br />    }<br />    <br />    protected void pauseApp(){<br />    }<br />    <br />    protected void startApp() throws MIDletStateChangeException {<br />        if( display == null ){ // first time called...<br />            initMIDlet();<br />        }<br />    }<br />    <br />    private void initMIDlet(){<br />        display = Display.getDisplay( this );<br />        <br />        String [] items;<br />        <br />        //items = parseUsingNanoXML( xmlDocument );<br />        items = parseUsingkXML( xmlDocument );<br />        <br />        display.setCurrent( new ItemList( items ) );<br />    }<br />    <br />    public void exitMIDlet(){<br />        notifyDestroyed();<br />    }<br />    <br />    // Parses a document using NanoXML, looking for<br />    // "item" nodes and returning their content as an<br />    // array of strings.<br />    <br />    private String[] parseUsingNanoXML( String xml ){<br />        kXMLElement root = new kXMLElement();<br />        try {<br />            root.parseString( xml );<br />            <br />            Vector list = root.getChildren();<br />            Vector items = new Vector();<br />            <br />            for( int i = 0; i &lt; list.size(); ++i ){<br />                kXMLElement node = <br />                     (kXMLElement) list.elementAt( i );<br />                String      tag = node.getTagName();<br />                <br />                if( tag == null ) continue;<br />                if( !tag.equals( "item" ) ) continue;<br />                <br />                items.addElement( node.getContents() );<br />            }<br />            <br />            String[] tmp = new String[ items.size() ];<br />            items.copyInto( tmp );<br />            return tmp;<br />        }<br />        catch( kXMLParseException ke ){<br />            return new String[]{ ke.toString() };<br />        }<br />    }<br />    <br />    // Parses a document using kXML, looking for "item"<br />    // nodes and returning their content as an<br />    // array of strings.<br />    <br />    private String[] parseUsingkXML( String xml ){<br />        try {<br />            ByteArrayInputStream bin =<br />                            new ByteArrayInputStream( <br />                                     xml.getBytes() );<br />            InputStreamReader in = new InputStreamReader( bin );<br />            XmlParser parser = new XmlParser( in );<br />            Vector    items = new Vector();<br />            <br />            parsekXMLItems( parser, items );<br />            <br />            String[] tmp = new String[ items.size() ];<br />            items.copyInto( tmp );<br />            return tmp;<br />        }<br />        catch( IOException e ){<br />            return new String[]{ e.toString() };<br />        }<br />    }<br />    <br />    private void parsekXMLItems( XmlParser parser, Vector items )<br />                                     throws IOException {<br />        boolean inItem = false;<br />        <br />        while( true ){<br />            ParseEvent event = parser.read();<br />            switch( event.getType() ){<br />                case Xml.START_TAG:<br />                    if( event.getName().equals( "item" ) ){<br />                        inItem = true;<br />                    }<br />                    break;<br />                case Xml.END_TAG:<br />                    if( event.getName().equals( "item" ) ){<br />                        inItem = false;<br />                    }<br />                    break;<br />                case Xml.TEXT:<br />                    if( inItem ){<br />                        items.addElement( event.getText() );<br />                    }<br />                    break;<br />                case Xml.END_DOCUMENT:<br />                    return;<br />            }<br />        }<br />    }<br />    <br />    // Simple List UI component for displaying the list of<br />    // items parsed from the XML document.<br />    <br />    class ItemList extends List implements CommandListener {<br />    <br />        ItemList( String[] list ){<br />            super( "Items", IMPLICIT, list, null );<br />            addCommand( exitCommand );<br />            setCommandListener( this );<br />        }<br />        <br />        public void commandAction( Command c, Displayable d ){<br />            if( c == exitCommand ){<br />                exitMIDlet();<br />            } <br />        }<br />    }<br />}</p></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/hallywang/aggbug/42798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-04-24 11:16 <a href="http://www.blogjava.net/hallywang/archive/2006/04/24/42798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐一个spring的教程,转了简介过来.</title><link>http://www.blogjava.net/hallywang/archive/2006/04/03/38834.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 03 Apr 2006 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/04/03/38834.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/38834.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/04/03/38834.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/38834.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/38834.html</trackback:ping><description><![CDATA[
		<div class="chapter" lang="zh_cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title">
												<a name="introduction">
												</a>第 1 章 简介</h2>
								</div>
						</div>
						<div>
						</div>
				</div>
				<div class="sect1" lang="zh_cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="introduction-overview">
														</a>1.1. 概览</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>Spring包含许多功能和特性，并被很好地组织在下图所示的七个模块中。本节将依次介绍每个模块. </p>
						<p>
						</p>
						<div class="mediaobject" align="center">
								<img src="http://www.jactiongroup.net/reference/html/images/spring-overview.gif" align="middle" />
								<div class="caption">
										<p>Spring框架概览 </p>
								</div>
						</div>
						<p>
						</p>
						<p>
								<span class="emphasis">
										<em>Core</em>
								</span>包是框架的最基础部分， 并提供依赖注入（Dependency Injection）特性来使你可管理Bean容器功能。 这里的基础概念是BeanFactory，它提供Factory模式来消除对程序性单例的需要， 并允许你从程序逻辑中分离出依赖关系的配置和描述。 </p>
						<p>构建于Beans包上<span class="emphasis"><em>Context包</em></span>，提供了一种框架式的Bean访问方式， 有些象JNDI注册。Context包的特性得自Beans包，并添加了文本消息的发送，通过比如资源串， 事件传播，资源装载的方式和Context的透明创建，如通过Servlet容器。 </p>
						<p>
								<span class="emphasis">
										<em>DAO包</em>
								</span>提供了JDBC的抽象层，它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 该包也提供了一种方法实现编程性和声明性事务管理，不仅仅是针对实现特定接口的类， 而且对<span class="emphasis"><em>所有的POJO</em></span>。 </p>
						<p>
								<span class="emphasis">
										<em>ORM包</em>
								</span>为流行的关系－对象映射APIs提供了集成层，包括JDO，Hibernate和iBatis。 通过ORM包，你可与所有Spring提供的其他特性相结合来使用这些对象/关系映射， 如前边提到的简单声明性事务管理。 </p>
						<p>Spring的<span class="emphasis"><em>AOP包</em></span>提供与<span class="emphasis"><em>AOP联盟</em></span>兼容的面向方面编程实现，允许你定义， 如方法拦截器和切点，来干净地给从逻辑上说应该被分离的功能实现代码解耦。 使用源码级的元数据功能，你可将各种行为信息合并到你的代码中，有点象.Net的attribute。 </p>
						<p>Spring的<span class="emphasis"><em>Web包</em></span>提供了基本的面向Web的综合特性，如Multipart功能， 使用Servlet监听器的Context的初始化和面向Web的Applicatin Context。 当与WebWork或Struts一起使用Spring时，这个包使Spring可与其他框架结合。 </p>
						<p>Spring的<span class="emphasis"><em>Web MVC</em></span>包提供了面向Web应用的Model-View-Controller实现。 Spring的MVC实现不仅仅是一种实现，它提供了一种domain model代码和web form的清晰分离， 这使你可使用Spring框架的所有其他特性，如校验. </p>
				</div>
				<div class="sect1" lang="zh_cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="overview-usagescenarios">
														</a>1.2. 使用场景</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>利用积木方式来描述你在各种场合使用Spring的情况， 从Applet一直到完整的使用Spring的事务管理功能和Web框架的企业应用。 </p>
						<p>
						</p>
						<div class="mediaobject" align="center">
								<img src="http://www.jactiongroup.net/reference/html/images/full.gif" align="middle" />
								<div class="caption">
										<p>典型的完整Spring Web应用 </p>
								</div>
						</div>
						<p>
						</p>
						<p>一个典型的使用大部分Spring特性的Web应用。使用<tt class="literal">TransactionProxyFactoryBeans</tt>， Web应用是完全事务性的，就像使用EJB提供的那种容器管理的事务一样． 所有的你的自定义业务逻辑可以通过简单的POJO来实现，并通过Spring的Dependency Injection容器进行管理。其他的服务，如发送email和校验，独立于Web层， 使你能够决定在哪里执行校验规则。 Spring的ORM支持包含了Hibernate，JDO和iBatis。如使用<tt class="literal">HibernateDaoSupport</tt>， 你可复用已经存在的Hibernate映射。从Controller无缝整合web层和领域模型， 消除对<tt class="literal">ActionForms</tt>的需要和其他转换HTTP参数为领域模型的类。 </p>
						<p>
						</p>
						<div class="mediaobject" align="center">
								<img src="http://www.jactiongroup.net/reference/html/images/thirdparty-web.gif" align="middle" />
								<div class="caption">
										<p>使用了第三方框架的Spring中间层 </p>
								</div>
						</div>
						<p>
						</p>
						<p>有时，现有情况不允许你彻底地转换到一种不同的框架。Spring没有 <span class="emphasis"><em>强迫</em></span>你使用它的全部,它不是一种<span class="emphasis"><em>全有全无</em></span> 的解决方案。现有的使用WebWork,Struts,Tapestry或其他的UI框架的前端程序可极佳的 与基于Spring的中间层进行集成，使你可使用Spring提供的事务处理特性。 你唯一要做的事是使用<tt class="literal">ApplicationContext</tt>来挂接你的业务逻辑和 通过<tt class="literal">WebApplicationContext</tt>来集成你的Struts前端程序。 </p>
						<p>
						</p>
						<div class="mediaobject" align="center">
								<img src="http://www.jactiongroup.net/reference/html/images/remoting.gif" align="middle" />
								<div class="caption">
										<p>远程使用场景 </p>
								</div>
						</div>
						<p>
						</p>
						<p>当你需要通过WebService来访问你的现有代码时， 你可使用Spring的<tt class="literal">Hessian-</tt>,<tt class="literal">Burlap-</tt>, <tt class="literal">Rmi-</tt> 或者 <tt class="literal">JaxRpcProxyFactory</tt>类。 使得突然给现有应用增加远程访问时不再那么困难。 </p>
						<p>
						</p>
						<div class="mediaobject" align="center">
								<img src="http://www.jactiongroup.net/reference/html/images/ejb.gif" align="middle" />
								<div class="caption">
										<p>EJBs - 封装现有的POJO </p>
								</div>
						</div>
						<p>
						</p>
						<p>Spring也为EJB提供了访问层和抽象层， 使你可复用已存在的POJO并将他们包装在Stateless SessionBean中， 以便在可能需要声明式安全(EJB中的安全管理,译者注)的可升级的可容错的Web应用中使用。 </p>
				</div>
		</div>
		<div class="navfooter">
				<hr />
				<a href="http://www.jactiongroup.net/reference/html/index.html">
						<br />全文地址:<br /><br />http://www.jactiongroup.net/reference/html/index.html</a>
		</div>
<img src ="http://www.blogjava.net/hallywang/aggbug/38834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-04-03 10:11 <a href="http://www.blogjava.net/hallywang/archive/2006/04/03/38834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]使用spring更好的处理struts动作</title><link>http://www.blogjava.net/hallywang/archive/2006/03/10/34656.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Fri, 10 Mar 2006 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/hallywang/archive/2006/03/10/34656.html</guid><wfw:comment>http://www.blogjava.net/hallywang/comments/34656.html</wfw:comment><comments>http://www.blogjava.net/hallywang/archive/2006/03/10/34656.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hallywang/comments/commentRss/34656.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hallywang/services/trackbacks/34656.html</trackback:ping><description><![CDATA[<P>George Franciscus , 负责人, Nexcel</P>
<P>您肯定已经听说过控制反转 (IOC) 设计模式，因为很长一段时间以来一直在流传关于它的信息。如果您在任何功能中使用过 Spring 框架，那么您就知道其原理的作用。在本文中，我利用这一原理把一个 <A class=glossary-term href="http://www.mywelt.net/?q=glossary#term191"><ACRONYM title="Struts: Apache Struts (formerly under the Apache Jakarta project, Struts is now a top level project) is an open-source framework for developing J2EE web applications. It uses and extends the Java Servlet API to encourage developers to adopt an MVC architecture. It was originally created by Craig McClanahan and donated to the Apache Foundation in May, 2000.">Struts</ACRONYM></A> 应用程序注入 Spring 框架，您将亲身体会到 IOC 模式的强大。</P>
<P>将一个 Struts 应用程序整合进 Spring 框架具有多方面的优点。首先，Spring 是为解决一些关于 JEE 的真实世界问题而设计的，比如复杂性、低性能和可测试性，等等。第二，Spring 框架包含一个 AOP 实现，允许您将面向方面技术应用于面向对象的代码。第三，一些人可能会说 Spring 框架只有<I>处理</I> Struts 比 Struts 处理自己好。但是这是观点问题，我演示三种将 Struts 应用程序整合到 Spring 框架的方法后，具体由您自己决定使用哪一种。</P>
<P>我所演示的方法都是执行起来相对简单的，但是它们却具有明显不同的优点。我为每一种方法创建了一个独立而可用的例子，这样您就可以完全理解每种方法。</P>
<P><A name=IDAFEWW><SPAN class=atitle><FONT size=4>为什么 Spring 这么了不起？</FONT></SPAN></A></P>
<P>Spring 的创立者 Rod Johnson 以一种批判的眼光看待 <A class=glossary-term href="http://www.mywelt.net/?q=glossary#term166"><ACRONYM title="Java: Java is a reflective, object-oriented programming language developed initially by James Gosling and colleagues at Sun Microsystems. Initially called Oak (named after the oak trees outside Gosling's office), it was intended to replace C++, although the feature set better resembles that of Objective-C. Java should not be confused with JavaScript, which shares only the name and a similar C-like syntax. Sun Microsystems currently maintains and updates Java regularly.">Java</ACRONYM></A>? 企业软件开发，并且提议很多企业难题都能够通过战略地使用 IOC 模式（也称作依赖注入）来解决。当 Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时，结果就产生了 Spring 框架。简言之，Spring 是一个轻型的容器，利用它可以使用一个外部 <A class=glossary-term href="http://www.mywelt.net/?q=glossary#term196"><ACRONYM title="XML: The Extensible Markup Language (XML) is a W3C-recommended general-purpose markup language for creating special-purpose markup languages. It is a simplified subset of SGML, capable of describing many different kinds of data. Its primary purpose is to facilitate the sharing of data across different systems, particularly systems connected via the Internet. Languages based on XML (for example, RDF, RSS, MathML, XHTML, SVG, and cXML) are defined in a formal way, allowing programs to modify and validate documents in these languages without prior knowledge of their form.">XML</ACRONYM></A> 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用，留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。</P>
<TABLE cellSpacing=0 cellPadding=0 width="40%" align=right border=0>
<TBODY>
<TR>
<TD width=10><IMG height=1 src="http://www.ibm.com/i/c.gif" width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><A name=IDAMEWW><B>IOC 和 Spring</B></A><BR>
<P>IOC 是一种使应用程序逻辑外在化的设计模式，所以它是被注入而不是被写入客户机代码中。将 IOC 与接口编程应用结合，就像 Spring 框架那样，产生了一种架构，这种架构能够减少客户机对特定实现逻辑的依赖。</P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>依赖注入是一个强大的特性，但是 Spring 框架能够提供更多特性。Spring 支持可插拔的事务管理器，可以给您的事务处理提供更广泛的选择范围。它集成了领先的持久性框架，并且提供一个一致的异常层次结构。Spring 还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制。</P>
<P>Spring AOP 允许您使用<I>拦截器</I> 在一个或多个执行点上拦截应用程序逻辑。加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的、实用的代码基础，所以拦截器广泛用于日志记录。您很快就会看到，为了处理横切关注点，Spring AOP 发布了它自己的拦截器，您也可以编写您自己的拦截器。</P>
<P><A name=IDA2EWW><SPAN class=atitle><FONT size=4>整合 Struts 和 Spring</FONT></SPAN></A></P>
<P>与 Struts 相似，Spring 可以作为一个 <A class=glossary-term href="http://www.mywelt.net/?q=glossary#term192"><ACRONYM title="MVC: Model-View-Controller (MVC) is a software architecture that separates an application's data model, user interface, and control logic into three distinct components so that modifications to one component can be made with minimal impact to the others.">MVC</ACRONYM></A> 实现。这两种框架都具有自己的优点和缺点，尽管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础。Struts 具有如此大的推动力，以至于开发团队宁愿整合 Spring 框架的特性，而不愿意转换成 Spring MVC。没必要进行转换对您来说是一个好消息。Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层。最后的结果就是现在一切条件都具备了。</P>
<P>在接下来的小窍门中，您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法。我将揭示每种方法的缺陷并且对比它们的优点。 一旦您了解到所有三种方法的作用，我将会向您展示一个令人兴奋的应用程序，这个程序使用的是这三种方法中我最喜欢的一种。</P>
<P><A name=IDADFWW><SPAN class=atitle><FONT size=4>三个小窍门</FONT></SPAN></A></P>
<P>接下来的每种整合技术（或者窍门）都有自己的优点和特点。我偏爱其中的一种，但是我知道这三种都能够加深您对 Struts 和 Spring 的理解。在处理各种不同情况的时候，这将给您提供一个广阔的选择范围。方法如下：</P>
<UL>
<LI>使用 Spring 的 <CODE>ActionSupport</CODE> 类整合 Structs 
<LI>使用 Spring 的 <CODE>DelegatingRequestProcessor</CODE> 覆盖 Struts 的 <CODE>RequestProcessor </CODE>
<LI>将 Struts <CODE>Action</CODE> 管理委托给 Spring 框架</LI></UL>
<P><A name=IDAAGWW><SPAN class=smalltitle><STRONG>装载应用程序环境</STRONG></SPAN></A></P>
<P>无论您使用哪种技术，都需要使用 Spring 的 <CODE>ContextLoaderPlugin</CODE> 为 Struts 的 <CODE>ActionServlet</CODE> 装载 Spring 应用程序环境。就像添加任何其他插件一样，简单地向您的 struts-config.xml 文件添加该插件，如下所示：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;plug-in className=
  "org.springframework.web.struts.ContextLoaderPlugIn"&gt;
    &lt;set-property property=
      "contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
 &lt;/plug-in&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P><A name=IDAZGWW><SPAN class=atitle><FONT size=4>窍门 1. 使用 Spring 的 ActionSupport</FONT></SPAN></A></P>
<P>手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单，Spring 提供了一些帮助。为了方便地获得 Spring 环境，<CODE>org.springframework.web.struts.ActionSupport</CODE> 类提供了一个 <CODE>getWebApplicationContext()</CODE> 方法。您所做的只是从 Spring 的 <CODE>ActionSupport</CODE> 而不是 Struts <CODE>Action</CODE> 类扩展您的动作，如清单 1 所示：</P><BR><A name=IDAUHWW><B>清单 1. 使用 ActionSupport 整合 Struts</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console" size=1>package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends ActionSupport {   <SPAN class=boldcode><STRONG>|(1)</STRONG></SPAN>


  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
    //the old fashion way
    //BookService bookService = new BookServiceImpl();
		
    ApplicationContext ctx = 
      getWebApplicationContext();    <SPAN class=boldcode><STRONG>|(2)</STRONG></SPAN>
    BookService bookService = 
      (BookService) ctx.getBean("bookService");   <SPAN class=boldcode><STRONG>|(3)</STRONG></SPAN>
        
  Book book = bookService.read(isbn.trim());

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
        ("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

    request.setAttribute("book", book);
    return mapping.findForward("success");
  }
}
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>让我们快速思考一下这里到底发生了什么。在 (1) 处，我通过从 Spring 的 <CODE>ActionSupport</CODE> 类而不是 Struts 的 <CODE>Action</CODE> 类进行扩展，创建了一个新的 <CODE>Action</CODE>。在 (2) 处，我使用 <CODE>getWebApplicationContext()</CODE> 方法获得一个 <CODE>ApplicationContext</CODE>。为了获得业务服务，我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。</P>
<P>这种技术很简单并且易于理解。不幸的是，它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring，那么您必须重写代码。并且，由于 Struts 动作不在 Spring 的控制之下，所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时，这种技术可能有用，但是在大多数情况下，这种方法不如另外两种方法合适。</P>
<P><A name=IDA0A4W><SPAN class=atitle><FONT size=4>窍门 2. 覆盖 RequestProcessor</FONT></SPAN></A></P>
<P>将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用 <CODE>org.springframework.web.struts.DelegatingRequestProcessor</CODE> 类来覆盖 Struts 的 <CODE>RequestProcessor</CODE> 处理程序，如清单 2 所示：</P><BR><A name=IDANB4W><B>清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;

&lt;!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//<A class=glossary-term href="http://www.mywelt.net/?q=glossary#term308"><ACRONYM title='DTD: A Document Type Definition (DTD for short) is a set of declarations that conform to a particular markup syntax and that describe a class, or "type", of SGML or XML documents, in terms of constraints on the structure of those documents.'>DTD</ACRONYM></A> Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;

&lt;struts-config&gt;
 &lt;form-beans&gt;
    &lt;form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm"&gt;
               &lt;form-property name="isbn"    type="java.lang.String"/&gt;
    &lt;/form-bean&gt;
  
  &lt;/form-beans&gt;

 &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
     &lt;forward   name="welcome"                path="/welcome.do"/&gt;
     &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
     &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
 &lt;/global-forwards&gt;

 &lt;action-mappings&gt;
    &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
    &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
    &lt;action    path="/searchSubmit" 
               type="ca.nexcel.books.actions.SearchSubmit"
               input="/searchEntry.do"
               validate="true"
               name="searchForm"&gt;
              &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
              &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
    &lt;/action&gt;  

 &lt;/action-mappings&gt;

 &lt;message-resources parameter="ApplicationResources"/&gt;

 &lt;controller processorClass="org.springframework.web.struts.
   DelegatingRequestProcessor"/&gt; <SPAN class=boldcode><STRONG>|(1)</STRONG></SPAN>

 &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
    &lt;set-property property="pathnames" 
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
 &lt;/plug-in&gt;


 &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
    &lt;set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
 &lt;/plug-in&gt;
 
&lt;/struts-config&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>我利用了 <CODE>&lt;controller&gt;</CODE> 标记来用 <CODE>DelegatingRequestProcessor</CODE> 覆盖默认的 Struts <CODE>RequestProcessor</CODE>。下一步是在我的 Spring 配置文件中注册该动作，如清单 3 所示：</P><BR><A name=IDAGC4W><B>清单 3. 在 Spring 配置文件中注册一个动作</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;
  &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;

  &lt;bean name="/searchSubmit" 
    class="ca.nexcel.books.actions.SearchSubmit"&gt; <SPAN class=boldcode><STRONG>|(1)</STRONG></SPAN>
     &lt;property name="bookService"&gt;
        &lt;ref bean="bookService"/&gt;
     &lt;/property&gt;
  &lt;/bean&gt;
&lt;/beans&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>注意：在 (1) 处，我使用名称属性注册了一个 bean，以匹配 struts-config 动作映射名称。<CODE>SearchSubmit</CODE> 动作揭示了一个 JavaBean 属性，允许 Spring 在运行时填充属性，如清单 4 所示：</P><BR><A name=IDAXC4W><B>清单 4. 具有 JavaBean 属性的 Struts 动作</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends Action {
	
  private BookService bookService;
  public BookService getBookService() {
    return bookService;
  }

  public void setBookService(BookService bookService) { <SPAN class=boldcode><STRONG>| (1)</STRONG></SPAN>
    this.bookService = bookService; 
  } 

  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
  Book book = getBookService().read(isbn.trim());  <SPAN class=boldcode><STRONG>|(2)</STRONG></SPAN>

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

      request.setAttribute("book", book);
      return mapping.findForward("success");
  }

}</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>在清单 4 中，您可以了解到如何创建 Struts 动作。在 (1) 处，我创建了一个 JavaBean 属性。<CODE>DelegatingRequestProcessor</CODE>自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring 管理，并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在，所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring。</P>
<P><CODE>DelegatingRequestProcessor</CODE> 方法的确比第一种方法好，但是仍然存在一些问题。如果您使用一个不同的 <CODE>RequestProcessor</CODE>，则需要手动整合 Spring 的 <CODE>DelegatingRequestProcessor</CODE>。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外，还有过一些使用一系列命令来代替 Struts <CODE>RequestProcessor</CODE> 的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。</P><BR>
<P><A name=IDAYD4W><SPAN class=atitle><FONT size=4>窍门 3. 将动作管理委托给 Spring</FONT></SPAN></A></P>
<P>一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 <CODE>struts-config</CODE> 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring 的控制之下，所以它可以填充动作的 JavaBean 属性，并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。 </P>
<P>清单 5 中的 <CODE>Action</CODE> 类与清单 4 中的相同。但是 struts-config 有一些不同：</P><BR><A name=IDANE4W><B>清单 5. Spring 整合的委托方法</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;

&lt;!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;

&lt;struts-config&gt;
 &lt;form-beans&gt;
    &lt;form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm"&gt;
               &lt;form-property name="isbn"    type="java.lang.String"/&gt;
    &lt;/form-bean&gt;
  
  &lt;/form-beans&gt;

 &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
     &lt;forward   name="welcome"                path="/welcome.do"/&gt;
     &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
     &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
 &lt;/global-forwards&gt;

 &lt;action-mappings&gt;
    &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
    &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
    &lt;action    path="/searchSubmit" 
             type="org.springframework.web.struts.DelegatingActionProxy" <SPAN class=boldcode><STRONG>|(1)</STRONG></SPAN>
             input="/searchEntry.do"
             validate="true"
             name="searchForm"&gt;
             &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
             &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
    &lt;/action&gt;  

 &lt;/action-mappings&gt;

 &lt;message-resources parameter="ApplicationResources"/&gt;


 &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
    &lt;set-property 
    property="pathnames" 
    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
 &lt;/plug-in&gt;


 &lt;plug-in 
    className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
    &lt;set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
 &lt;/plug-in&gt;

 
&lt;/struts-config&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>清单 5 是一个典型的 struts-config.xml 文件，只有一个小小的差别。它注册 Spring 代理类的名称，而不是声明动作的类名，如（1）处所示。DelegatingActionProxy 类使用动作映射名称查找 Spring 环境中的动作。这就是我们使用 <CODE>ContextLoaderPlugIn</CODE> 声明的环境。</P>
<P>将一个 Struts 动作注册为一个 Spring bean 是非常直观的，如清单 6 所示。我利用动作映射使用 <CODE>&lt;bean&gt;</CODE> 标记的名称属性（在这个例子中是 "<CODE>/searchSubmit</CODE>"）简单地创建了一个 bean。这个动作的 JavaBean 属性像任何 Spring bean 一样被填充： </P><BR><A name=IDAIF4W><B>清单 6. 在 Spring 环境中注册一个 Struts 动作</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;
  &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;

  &lt;bean name="/searchSubmit"   
        class="ca.nexcel.books.actions.SearchSubmit"&gt;
     &lt;property name="bookService"&gt;
        &lt;ref bean="bookService"/&gt;
     &lt;/property&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=IDAOF4W><SPAN class=atitle><FONT size=4>动作委托的优点</FONT></SPAN></A></P>
<P>动作委托解决方法是这三种方法中最好的。Struts 动作不了解 Spring，不对代码作任何改变就可用于非 Spring 应用程序中。<CODE>RequestProcessor</CODE> 的改变不会影响它，并且它可以利用 Spring AOP 特性的优点。 </P>
<P>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作，您就可以使用 Spring 给动作补充更强的活力。例如，没有 Spring 的话，所有的 Struts 动作都必须是线程安全的。如果您设置 <CODE>&lt;bean&gt;</CODE> 标记的 singleton 属性为“false”，那么不管用何种方法，您的应用程序都将在每一个请求上有一个新生成的动作对象。您可能不需要这种特性，但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如，当实例化 Struts 动作时，<CODE>&lt;bean&gt;</CODE> 标记的 init-method 属性被用于运行一个方法。类似地，在从容器中删除 bean 之前，destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法，它们以一种与 Servlet 生命周期相同的方式进行管理。</P><BR>
<P><A name=IDAEG4W><SPAN class=atitle><FONT size=4>拦截 Struts</FONT></SPAN></A></P>
<P>前面提到过，通过将 Struts 动作委托给 Spring 框架而整合 Struts 和 Spring 的一个主要的优点是：您可以将 Spring 的 AOP 拦截器应用于您的 Struts 动作。通过将 Spring 拦截器应用于 Struts 动作，您可以用最小的代价处理横切关注点。</P>
<P>虽然 Spring 提供很多内置拦截器，但是我将向您展示如何创建自己的拦截器并把它应用于一个 Struts 动作。为了使用拦截器，您需要做三件事：</P>
<OL>
<LI>创建拦截器。 
<LI>注册拦截器。 
<LI>声明在何处拦截代码。</LI></OL>
<P>这看起来非常简单的几句话却非常强大。例如，在清单 7 中，我为 Struts 动作创建了一个日志记录拦截器。 这个拦截器在每个方法调用之前打印一句话：</P><BR><A name=IDAUG4W><B>清单 7. 一个简单的日志记录拦截器</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>package ca.nexcel.books.interceptors;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class LoggingInterceptor implements MethodBeforeAdvice {

   public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("logging before!");
    }
}</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>这个拦截器非常简单。<CODE>before()</CODE> 方法在拦截点中每个方法之前运行。在本例中，它打印出一句话，其实它可以做您想做的任何事。下一步就是在 Spring 配置文件中注册这个拦截器，如清单 8 所示：</P><BR><A name=IDADH4W><B>清单 8. 在 Spring 配置文件中注册拦截器</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console"><FONT size=1>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;
  &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;

  &lt;bean name="/searchSubmit" 
        class="ca.nexcel.books.actions.SearchSubmit"&gt;
     &lt;property name="bookService"&gt;
        &lt;ref bean="bookService"/&gt;
     &lt;/property&gt;
  &lt;/bean&gt;

  &lt;!--  Interceptors --&gt; 
  &lt;bean name="logger"    
    class="ca.nexcel.books.interceptors.LoggingInterceptor"/&gt; <SPAN class=boldcode><STRONG>|(1)</STRONG></SPAN>

  &lt;!-- AutoProxies --&gt;
  &lt;bean name="loggingAutoProxy" 
        class="org.springframework.aop.framework.autoproxy.
          BeanNameAutoProxyCreator"&gt; <SPAN class=boldcode><STRONG>|(2)</STRONG></SPAN>
    &lt;property name="beanNames"&gt;
          &lt;value&gt;/searchSubmit&lt;/valuesgt; <SPAN class=boldcode><STRONG>|(3)</STRONG></SPAN>
    &lt;/property&gt;
    &lt;property name="interceptorNames"&gt;
        &lt;list&gt;
          &lt;value&gt;logger&lt;/value&gt; <SPAN class=boldcode><STRONG>|(4)</STRONG></SPAN>
        &lt;/list&gt;
    &lt;/property&gt;
   &lt;/bean&gt;

&lt;/beans&gt;</FONT>
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>您可能已经注意到了，清单 8 扩展了 清单 6 中所示的应用程序以包含一个拦截器。具体细节如下：</P>
<UL>
<LI>在 (1) 处，我注册了这个拦截器。 
<LI>在 (2) 处，我创建了一个 bean 名称自动代理，它描述如何应用拦截器。还有其他的方法定义拦截点，但是这种方法常见而简便。 
<LI>在 (3) 处，我将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作，则只需要在 "beanNames" 下面创建附加的 <CODE>&lt;value&gt;</CODE> 标记。 
<LI>在 (4) 处，当拦截发生时，我执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于“beanNames”。</LI></UL>
<P>就是这样。就像这个例子所展示的，将您的 Struts 动作置于 Spring 框架的控制之下，为处理您的 Struts 应用程序提供了一系列全新的选择。在本例中，使用动作委托可以轻松地利用 Spring 拦截器提高 Struts 应用程序中的日志记录能力。</P>
<P><A name=IDAFI4W><SPAN class=atitle><FONT size=4>结束语</FONT></SPAN></A></P>
<P>在本文中，您已经学习了将 Struts 动作整合到 Spring 框架中的三种窍门。使用 Spring 的 <CODE>ActionSupport</CODE> 来整合 Struts（第一种窍门中就是这样做的）简单而快捷，但是会将 Struts 动作与 Spring 框架耦合在一起。如果您需要将应用程序移植到一个不同的框架，则需要重写代码。第二种解决方法通过委托 <CODE>RequestProcessor</CODE> 巧妙地解开代码的耦合，但是它的可扩展性不强，并且当 Struts 的 <CODE>RequestProcessor</CODE> 变成一系列命令时，这种方法就持续不了很长时间。第三种方法是这三种方法中最好的：将 Struts 动作委托给 Spring 框架可以使代码解耦，从而使您可以在您的 Struts 应用程序中利用 Spring 的特性（比如日志记录拦截器）。</P>
<P>
<P><A name=resources><SPAN class=atitle><FONT size=4>参考资料 </FONT></SPAN></A></P><B>学习</B><BR>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www-128.ibm.com/developerworks/java/library/j-sr2.html" target=_blank>英文原文</FONT /></A>。 
<LI><A href="http://www.ibm.com/developerworks/web/library/wa-struts/index.html">Best practices in Struts development</FONT /></A>（Palaniyappan Thiagarajan 和 Pagadala Suresh，developerWorks，2004 年 6 月）：概述了 Struts <CODE>Action</CODE> 组件。 
<LI><A href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</FONT /></A>（Martin Fowler，2004 年 1 月）：介绍 IOC 容器。 
<LI><A href="http://www.theserverside.com/articles/article.tss?l=SpringFramework">Introduction to the Spring Framework</FONT /></A>（Rod Johnson，The ServerSide，2005 年 5 月）：Spring 的创立者解释了为什么 Spring 框架很重要。 
<LI><A href="http://www.manning.com/franciscus">Struts Recipes</FONT /></A>（George Franciscus 和 Danilo Gurovich；Manning，2004 年）：关于 Struts 窍门和最佳实践的一个流行的纲要。 
<LI><A href="http://www.manning.com/husted">Struts In Action</FONT /></A>（Ted Husted、Cedric Dumoulin、George Franciscus、David Winterfeldt；Manning，2002 年）：针对专业 Struts 开发人员的综合资源。 
<LI><A href="http://www.manning.com/walls2">Spring In Action</FONT /></A>（Craig Walls 和 Ryan Breidenbach；Manning，2005 年）：一本用于开发人员的 Spring 资源书籍。</LI></UL>
<P><A name=author><SPAN class=atitle><FONT size=4>关于作者</FONT></SPAN></A></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD colSpan=2><FONT size=4></FONT></TD></TR>
<TR vAlign=top align=left>
<TD>
<P></P></TD>
<TD>
<P>George Franciscus 是 Java 公司的一名顾问和 Struts 方面的权威。他是 Manning 出版的 <A href="http://www.manning.com/franciscus">Struts Recipes</FONT /></A> 和 <A href="http://www.manning.com/husted">Struts in Action</FONT /></A> 的合著者。 George 通过 <A href="http://www.nexcel.ca/">nexcel.ca</FONT /></A> 提供有关技术和管理方面的咨询服务。</P></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/hallywang/aggbug/34656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hallywang/" target="_blank">Hally</a> 2006-03-10 14:09 <a href="http://www.blogjava.net/hallywang/archive/2006/03/10/34656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>