﻿<?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-yyg1107-文章分类-java</title><link>http://www.blogjava.net/yyg1107/category/15861.html</link><description>&lt;center&gt;这家伙很懒,什么都没有留下&lt;/center&gt;</description><language>zh-cn</language><lastBuildDate>Sun, 08 Apr 2007 00:23:45 GMT</lastBuildDate><pubDate>Sun, 08 Apr 2007 00:23:45 GMT</pubDate><ttl>60</ttl><item><title>Hibernate Gossip: 樂觀鎖定（Optimistic locking）</title><link>http://www.blogjava.net/yyg1107/articles/94336.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Tue, 16 Jan 2007 17:29:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/94336.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/94336.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/94336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/94336.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/94336.html</trackback:ping><description><![CDATA[
		<p>悲觀鎖定假定任何時刻存取資料時，都可能有另一個客戶也正在存取同一筆資料，因而對資料採取了資料庫層次的鎖定狀態，在鎖定的時間內其他的客戶不能對資料進行存取，對於單機或小系統而言，這並不成問題，然而如果是在網路上的系統，同時間會有許多連線，如果每一次讀取資料都造成鎖定，其後繼的存取就必須等待，這將造成效能上的問題，造成後繼使用者的長時間等待。 <br /><br />樂觀鎖定（Optimistic locking）則樂觀的認為資料的存取很少發生同時存取的問題，因而不作資料庫層次上的鎖定，為了維護正確的資料，樂觀鎖定使用應用程式上的邏輯實現版本控制的解決。 <br /><br />在不實行悲觀鎖定策略的情況下，資料不一致的情況一但發生，有幾個解決的方法，一種是先更新為主，一種是後更新的為主，比較複雜的就是檢查發生變動的資料來實現，或是檢查所有屬性來實現樂觀鎖定。 <br /><br />Hibernate中透過版本號檢查來實現後更新為主，這也是Hibernate所推薦的方式，在資料庫中加入一個version欄位記錄，在讀取資料時連同版本號一同讀取，並在更新資料時比對版本號與資料庫中的版本號，如果等於資料庫中的版本號則予以更新，並遞增版本號，如果小於資料庫中的版本號就丟出例外。<br /><br />實際來透過範例瞭解Hibernate的樂觀鎖定如何實現，首先在資料庫中新增一個表格：<br /></p>
		<div style="MARGIN-LEFT: 40px; FONT-FAMILY: Courier New,Courier,monospace">
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<span style="COLOR: #0000ff">CREATE</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">TABLE</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #ff00ff">user</span>
						<span style="COLOR: #000000"> (<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    id </span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">INT</span>
						<span style="COLOR: #000000">(</span>
						<span style="FONT-WEIGHT: bold; COLOR: #800000">11</span>
						<span style="COLOR: #000000">) </span>
						<span style="COLOR: #808080">NOT</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">NULL</span>
						<span style="COLOR: #000000"> auto_increment </span>
						<span style="COLOR: #0000ff">PRIMARY</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">KEY</span>
						<span style="COLOR: #000000">,<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    version </span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">INT</span>
						<span style="COLOR: #000000">,<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    name </span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">VARCHAR</span>
						<span style="COLOR: #000000">(</span>
						<span style="FONT-WEIGHT: bold; COLOR: #800000">100</span>
						<span style="COLOR: #000000">) </span>
						<span style="COLOR: #808080">NOT</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">NULL</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">default</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #ff0000">''</span>
						<span style="COLOR: #000000">,<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    age </span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">INT</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />);</span>
				</div>
				<br />
		</div>
		<p>
				<br />這個user表格中的version用來記錄版本號，以供Hibernate實現樂觀鎖定，接著設計User類別，當中必須包括version屬性：<br /></p>
		<p> </p>
		<span id="Codehighlighter1_57_702_Open_Text">
				<ul>
						<li>User.java </li>
				</ul>
				<pre>package onlyfun.caterpillar;<br /><br />public class User {<br />    private Integer id;<br /><span style="FONT-WEIGHT: bold">    private Integer version; // 增加版本屬性   </span><br />    private String name;<br />    private Integer age;<br /><br />    public User() {<br />    }<br /><br />    public Integer getId() {<br />        return id;<br />    }<br /><br />    public void setId(Integer id) {<br />        this.id = id;<br />    }<br /><br />    public Integer getVersion() {<br />        return version;<br />    }<br /><br />    public void setVersion(Integer version) {<br />        this.version = version;<br />    }<br /><br />    public String getName() {<br />        return name;<br />    }<br /><br />    public void setName(String name) {<br />        this.name = name;<br />    }<br /><br />    public Integer getAge() {<br />        return age;<br />    }<br /><br />    public void setAge(Integer age) {<br />        this.age = age;<br />    }<br />}</pre>
				<p>
				</p>
		</span>
		<br />在映射文件的定義方面，則如下所示：<br /><ul><li>User.hbm.xml </li></ul><pre>&lt;?xml version="1.0" encoding="utf-8"?&gt; <br />&lt;!DOCTYPE hibernate-mapping <br />    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" <br />    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt; <br /><br />&lt;hibernate-mapping&gt; <br /><br />    &lt;class name="onlyfun.caterpillar.User" <br />           table="user"<br /><span style="FONT-WEIGHT: bold">optimistic-lock="version"</span>&gt; <br /><br />        &lt;id name="id" column="id" type="java.lang.Integer"&gt; <br />            &lt;generator class="native"/&gt; <br />        &lt;/id&gt; <br /><br /><span style="FONT-WEIGHT: bold">        &lt;version name="version" </span><br style="FONT-WEIGHT: bold" /><span style="FONT-WEIGHT: bold">                 column="version"</span><br style="FONT-WEIGHT: bold" /><span style="FONT-WEIGHT: bold">                 type="java.lang.Integer"/&gt; </span><br /><br />        &lt;property name="name" column="name" type="java.lang.String"/&gt; <br /><br />        &lt;property name="age" column="age" type="java.lang.Integer"/&gt; <br /><br />    &lt;/class&gt; <br /><br />&lt;/hibernate-mapping&gt;</pre><p><br />注意&lt;version&gt;標籤必須出現在&lt;id&gt;標籤之後，接著您可以試著在資料庫中新增資料，例如：<br /></p><div style="MARGIN-LEFT: 40px"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">User user = new User(); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">user.setName("caterpillar"); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">user.setAge(new Integer(30)); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">Session session = sessionFactory.openSession();</span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">Transaction tx =  session.beginTransaction();</span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">session.save(user); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">tx.commit(); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace" /><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">session.close();</span><br /></div><p><br /><span class="postbody">您可以檢視資料庫中的資料，每一次對同一筆資料進行更新，version欄位的內容都會自動更新，接著來作個實驗，直接以範例說明：<br /></span></p><div style="MARGIN-LEFT: 40px; FONT-FAMILY: Courier New,Courier,monospace"><span class="postbody" style="FONT-WEIGHT: bold">// 有使用1者開啟了一個session1</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">Session session1 = sessionFactory.openSession();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 在這之後，馬上有另一個使用者2開啟了session2</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">Session session2 = sessionFactory.openSession();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">Integer id = new Integer(1);</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold"></span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 使用者1查詢資料        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">User userV1 = (User) session1.load(User.class, id);</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 使用者2查詢同一筆資料</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">User userV2 = (User) session2.load(User.class, id);</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold"></span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 此時兩個版本號是相同的</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">System.out.println(" v1 v2 " </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">                + userV1.getVersion().intValue() + " " </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">                + userV2.getVersion().intValue());</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">Transaction tx1 = session1.beginTransaction();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">Transaction tx2 = session2.beginTransaction();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold"></span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 使用者1更新資料        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">userV1.setAge(new Integer(31));</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">tx1.commit();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold"></span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 此時由於資料更新，資料庫中的版本號遞增了</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 兩筆資料版本號不一樣了</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">System.out.println(" v1 v2 " </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">                + userV1.getVersion().intValue() + " " </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">                + userV2.getVersion().intValue());</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// userV2 的 age 資料還是舊的 </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 資料更新</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">userV2.setName("justin");</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 因版本號比資料庫中的舊</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">// 送出更新資料會失敗，丟出</span><span style="FONT-WEIGHT: bold">StableObjectStateException例外</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">tx2.commit();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">        </span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">session1.close();</span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="FONT-WEIGHT: bold">session2.close();</span><br /><span class="postbody"></span></div><p><span class="postbody"><br />運行以下的程式片段，會出現以下的結果：<br /></span></p><div style="MARGIN-LEFT: 40px; FONT-FAMILY: Courier New,Courier,monospace"><span class="postbody"><span style="FONT-WEIGHT: bold">Hibernate: select user0_.id as id0_, user0_.version as version0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody"><span style="FONT-WEIGHT: bold">Hibernate: select user0_.id as id0_, user0_.version as version0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody"><span style="FONT-WEIGHT: bold"> v1 v2 0 0</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody"><span style="FONT-WEIGHT: bold">Hibernate: update user set version=?, name=?, age=? where id=? and version=?</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody"><span style="FONT-WEIGHT: bold"> v1 v2 1 0</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody"><span style="FONT-WEIGHT: bold">Hibernate: update user set version=?, name=?, age=? where id=? and version=?</span></span><br style="FONT-WEIGHT: bold" /><span class="postbody" style="COLOR: rgb(255,0,0)"><span style="FONT-WEIGHT: bold">16:11:43,187 ERROR AbstractFlushingEventListener:277 - Could not synchronize database state with session</span></span><br style="FONT-WEIGHT: bold; COLOR: rgb(255,0,0)" /><span class="postbody" style="COLOR: rgb(255,0,0)"><span style="FONT-WEIGHT: bold">org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [onlyfun.caterpillar.User#1]</span></span><br style="FONT-WEIGHT: bold; COLOR: rgb(255,0,0)" /><span class="postbody" style="COLOR: rgb(255,0,0)"><span style="FONT-WEIGHT: bold">    at org.hibernate.persister.entity.BasicEntityPersister.check(BasicEntityPersister.java:1441)</span></span><br /><span class="postbody"></span></div><p><span class="postbody"><span style="FONT-FAMILY: Courier New,Courier,monospace"></span><br />由於新的版本號是1，而userV2的版本號還是0，因此更新失敗丟出StableObjectStateException，您可以捕捉這個例外作善後處理，例如在處理中重新讀取資料庫中的資料，同時將目前的資料與資料庫中的資料秀出來，讓使用者有機會比對不一致的資料，以決定要變更的部份，或者您可以設計程式自動讀取新的資料，並比對真正要更新的資料，這一切可以在背景執行，而不用讓您的使用者知道。 <br /><br />要注意的是，由於樂觀鎖定是使用系統中的程式來控制，而不是使用資料庫中的鎖定機制，因而如果有人特意自行更新版本訊息來越過檢查，則鎖定機制就會無效，例如在上例中自行更改userV2的version屬性，使之與資料庫中的版本號相同的話就不會有錯誤，像這樣版本號被更改，或是由於資料是由外部系統而來，因而版本資訊不受控制時，鎖定機制將會有問題，設計時必須注意。<br /></span><br /><br />from : <a href="http://caterpillar.onlyfun.net/Gossip/HibernateGossip/HibernateGossip.html">http://caterpillar.onlyfun.net/Gossip/HibernateGossip/HibernateGossip.html</a></p><img src ="http://www.blogjava.net/yyg1107/aggbug/94336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2007-01-17 01:29 <a href="http://www.blogjava.net/yyg1107/articles/94336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：如何在JAVA中使用日期 </title><link>http://www.blogjava.net/yyg1107/articles/81469.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Thu, 16 Nov 2006 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/81469.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/81469.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/81469.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/81469.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/81469.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 如果想要取得系统的时间，可以使用System.currentTimeMillis()方法，例如：																												DateDemo.java 						public						 						class						 DateDemo 																														...&nbsp;&nbsp;<a href='http://www.blogjava.net/yyg1107/articles/81469.html'>阅读全文</a><img src ="http://www.blogjava.net/yyg1107/aggbug/81469.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-11-16 11:03 <a href="http://www.blogjava.net/yyg1107/articles/81469.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons:巧用类和组件1 （3）</title><link>http://www.blogjava.net/yyg1107/articles/77720.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Fri, 27 Oct 2006 11:42:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/77720.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/77720.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/77720.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/77720.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/77720.html</trackback:ping><description><![CDATA[
		<strong>3.2 HttpClient</strong>
		<p style="TEXT-INDENT: 2em">　　■ 概况：这个API扩展了java.net包，提供了模拟浏览器的功能。 </p>
		<p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/httpclient/index.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-httpclient/v2.0/commons-httpclient-2.0-beta1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-httpclient/v2.0/commons-httpclient-2.0-beta1-src.zip" target="_blank">源代码</a>。 </p>
		<p style="TEXT-INDENT: 2em">　　■ 何时适用：当你要构造Web浏览器的功能；当你的应用需要一种高效的办法进行HTTP/HTTPS通信时。 </p>
		<p style="TEXT-INDENT: 2em">　　■ 示例应用：HttpClientDemo.java。要求CLASSPATH中有commons-httpclient.jar，common-logging.jar。要求使用JDK 1.4或更高版本。 </p>
		<p style="TEXT-INDENT: 2em">　　■ 说明： </p>
		<p style="TEXT-INDENT: 2em">　　HttpClient扩展和增强了标准java.net包，是一个内容广泛的代码库，功能极其丰富，能够构造出各种使用HTTP协议的分布式应用，或者也可以嵌入到现有应用，为应用增加访问HTTP协议的能力。在Commons稳定版中，HttpClient的文档似乎要比其他包更完善一些，而且还带有几个实例。下面我们通过一个简单的例子来了解如何提取一个Web页面，HttpClient文档中也有一个类似的例子，我们将扩充那个例子使其支持SSL。注意本例需要JDK 1.4支持，因为它要用到Java Secure Socket Connection库，而这个库只有JDK 1.4及更高的版本才提供。 </p>
		<p style="TEXT-INDENT: 2em">　　① 首先确定一个可以通过HTTPS下载的页面，本例使用的是https://www.paypal.com/。同时确保%JAVA_HOME%/jre/lib/security/java.security文件包含了下面这行代码：security.provider.2=com.sun.net.ssl.internal.ssl.Provider。 </p>
		<p style="TEXT-INDENT: 2em">　　除了这些设置之外，HTTPS连接的处理方式没有其他特别的地方--至少对于本例来说如此。不过，如果远程网站使用的根证书不被你使用的Java认可，则首先必须导入它的证书。 </p>
		<p style="TEXT-INDENT: 2em">　　② 创建一个HttpClient的实例。HttpClient类可以看成是应用的主驱动程序，所有针对网络的功能都依赖于它。HttpClient类需要一个Connection Manager来管理连接。HttpConnectionManager允许我们创建自己的连接管理器，或者，我们也可以直接使用内建的SimpleHttpConnectionManager或MultiThreadedHttpConnectionManager类。如果在创建HttpClient时没有指定连接管理器，HttpClient默认使用SimpleHttpConnectionManager。 <br /></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #008000">//</span>
				<span style="COLOR: #008000"> 创建一个HttpClient的实例</span>
				<span style="COLOR: #008000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #000000">HttpClient client </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">new</span>
				<span style="COLOR: #000000"> HttpClient();</span>
		</div>
		<br />③ 创建一个HttpMethod的实例，即确定与远程服务器的通信要采用哪种传输方式，HTTP允许采用的传输方式包括：GET，POST，PUT，DELETE，HEAD，OPTIONS，以及TRACE。这些传输方式分别作为一个独立的类实现，但所有这些类都实现HttpMethod接口。在本例中，我们使用的是GetMethod，创建GetMethod实例时在参数中指定我们想要GET的URL。 <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 创建一个HttpMethod的实例</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">HttpMethod method </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GetMethod(url);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><br />④ 执行HttpMethod定义的提取操作。执行完毕后，executeMethod方法将返回远程服务器报告的状态代码。注意executeMethod属于HttpClient，而不是HttpMethod。 <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 执行HttpMethod定义的提取操作</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">statusCode </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> client.executeMethod(method);</span></div><br />⑤ 读取服务器返回的应答。如果前面的连接操作失败，程序将遇到HttpException或IOException，其中IOException一般意味着网络出错，继续尝试也不太可能获得成功。服务器返回的应答可以按照多种方式读取，例如作为一个字节数组，作为一个输入流，或者作为一个String。获得服务器返回的应答后，我们就可以按照自己的需要任意处置它了。 
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">byte</span><span style="COLOR: #000000">[] responseBody </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> method.getResponseBody();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><br />　⑥ 最后要做的就是释放连接。 <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">method.releaseConnection();</span></div><br /><p style="TEXT-INDENT: 2em">　　以上只是非常简单地介绍了一下HttpClient库，HttpClient实际的功能要比本文介绍的丰富得多，不仅健壮而且高效，请参阅API文档了解详情。 </p><p style="TEXT-INDENT: 2em">　　<b>3.3 Net</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：一个用于操作Internet基础协议的底层API。 </p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/net/" target="_blank">主页</a>，<a href="http://apache.planetmirror.com/dist/jakarta/commons/net/binaries/" target="_blank">二进制</a>，<a href="http://apache.planetmirror.com.au/dist/jakarta/commons/net/source/" target="_blank">源代码</a>。 </p><p style="TEXT-INDENT: 2em">　　■ 何时适用：当你想要访问各种Internet底层协议之时（Finger，Whois，TFTP，Telnet，POP3，FTP，NNTP，以及SMTP）。 </p><p style="TEXT-INDENT: 2em">　　■ 示例应用：NetDemo.java。要求CLASSPATH中包含commons-net-1.0.0.jar。 </p><p style="TEXT-INDENT: 2em">　　■ 说明： </p><p style="TEXT-INDENT: 2em">　　Net包是一个强大、专业的类库，类库里的类最初属于一个叫做NetComponents的商业产品。 </p><p style="TEXT-INDENT: 2em">　　Net包不仅支持对各种低层次协议的访问，而且还提供了一个高层的抽象。大多数情况下，Net包提供的抽象已能满足一般需要，它使得开发者不再需要直接面对各种协议的Socket级的低层命令。使用高层抽象并不减少任何功能，Net API在这方面做得很出色，既提供了足够的功能，又不至于在特色方面作过多的妥协。 </p><p style="TEXT-INDENT: 2em">　　SocketClient是支持所有协议的基础类，它是一个抽象类，聚合了各种协议都需要的公用功能。各种不同协议的使用过程其实很相似，首先利用connect方法建立一个指向远程服务器的连接，执行必要的操作，最后终止与服务器的连接。下面通过实例介绍具体的使用步骤。 <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ① 创建一个客户端。我们将用NNTPClient<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">　　从新闻服务器下载新闻组清单。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">client </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> NNTPClient();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ② 利用前面创建的客户端连接到新闻服务器。<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">　　这里选用的是一个新闻组较少的服务器。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">client.connect(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">aurelia.deine.net</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ③ 提取新闻组清单。下面的命令将返回一个<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">　　NewsGroupInfo对象的数组。如果指定的服<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">　　务器上不包含新闻组，返回的数组将是空的，<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">　　如果遇到了错误，则返回值是null。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">list </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> client.listNewsgroups();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/images/dot.gif" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ④ 最后终止与服务器的连接。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (client.isConnected())<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   client.disconnect();</span></div><br />必须说明的是，listNewsgroups命令可能需要较长的时间才能返回，一方面是因为网络速度的影响，另外也可能是由于新闻组清单往往是很庞大的。NewsGroupInfo对象包含有关新闻组的详细信息，并提供了一些操作新闻组的命令，比如提取文章总数、最后发布的文章、发布文章的权限，等等。 
<p style="TEXT-INDENT: 2em">　　其他客户端，例如FingerClient、POP3Client、TelnetClient等，用法也差不多。 </p><p style="TEXT-INDENT: 2em">　　结束语：有关Web相关类和其他类的介绍就到此结束。在下一篇文章中，我们将探讨XML类和包装类，最后一篇文章则介绍工具类。 </p><p style="TEXT-INDENT: 2em">　　希望读者有兴趣试试本文提供的程序实例。很多时候Jakarta Commons给人以混乱的感觉，希望本文使你加深了对Jakarta Commons了解，或者至少引起了你对Commons子项目以及它提供的各种实用API和库的兴趣。 </p><p style="TEXT-INDENT: 2em">请从这里下载本文代码：<a href="" target="_blank">JakartaCommons1_code.zip</a></p><img src ="http://www.blogjava.net/yyg1107/aggbug/77720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-10-27 19:42 <a href="http://www.blogjava.net/yyg1107/articles/77720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons:巧用类和组件1 （2）</title><link>http://www.blogjava.net/yyg1107/articles/77719.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Fri, 27 Oct 2006 11:38:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/77719.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/77719.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/77719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/77719.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/77719.html</trackback:ping><description><![CDATA[              使用这类方法有什么好处呢？显然，它使得我们有可能通过一种统一的方式处理所有数据类型。所有Builder方法的用法都和上例相似。 
<p style="TEXT-INDENT: 2em">　　Java没有C风格的枚举量，为此，lang包提供了一个类型安全的Enum类型，填补了空白。Enum类是抽象的，如果你要创建枚举量，就要扩展Enum类。下面的例子清楚地说明了Enum的用法。 <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.apache.commons.lang.</span><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000">.Enum;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Map;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.List;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Iterator;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    <br /><img id="Codehighlighter1_156_700_Open_Image" onclick="this.style.display='none'; Codehighlighter1_156_700_Open_Text.style.display='none'; Codehighlighter1_156_700_Closed_Image.style.display='inline'; Codehighlighter1_156_700_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_156_700_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_156_700_Closed_Text.style.display='none'; Codehighlighter1_156_700_Open_Image.style.display='inline'; Codehighlighter1_156_700_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> OnTV </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> Enum </span><span id="Codehighlighter1_156_700_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_156_700_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> OnTV IDOL</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> OnTV(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Idol</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> OnTV SURVIVOR </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> OnTV(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Survivor</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> OnTV SEINFELD </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> OnTV(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Seinfeld</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_378_396_Open_Image" onclick="this.style.display='none'; Codehighlighter1_378_396_Open_Text.style.display='none'; Codehighlighter1_378_396_Closed_Image.style.display='inline'; Codehighlighter1_378_396_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_378_396_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_378_396_Closed_Text.style.display='none'; Codehighlighter1_378_396_Open_Image.style.display='inline'; Codehighlighter1_378_396_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> OnTV(String show) </span><span id="Codehighlighter1_378_396_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_378_396_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">super</span><span style="COLOR: #000000">(show);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_438_484_Open_Image" onclick="this.style.display='none'; Codehighlighter1_438_484_Open_Text.style.display='none'; Codehighlighter1_438_484_Closed_Image.style.display='inline'; Codehighlighter1_438_484_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_438_484_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_438_484_Closed_Text.style.display='none'; Codehighlighter1_438_484_Open_Image.style.display='inline'; Codehighlighter1_438_484_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> OnTV getEnum(String show)</span><span id="Codehighlighter1_438_484_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_438_484_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (OnTV) getEnum(OnTV.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, show);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_518_554_Open_Image" onclick="this.style.display='none'; Codehighlighter1_518_554_Open_Text.style.display='none'; Codehighlighter1_518_554_Closed_Image.style.display='inline'; Codehighlighter1_518_554_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_518_554_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_518_554_Closed_Text.style.display='none'; Codehighlighter1_518_554_Open_Image.style.display='inline'; Codehighlighter1_518_554_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Map getEnumMap() </span><span id="Codehighlighter1_518_554_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_518_554_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> getEnumMap(OnTV.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_590_627_Open_Image" onclick="this.style.display='none'; Codehighlighter1_590_627_Open_Text.style.display='none'; Codehighlighter1_590_627_Closed_Image.style.display='inline'; Codehighlighter1_590_627_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_590_627_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_590_627_Closed_Text.style.display='none'; Codehighlighter1_590_627_Open_Image.style.display='inline'; Codehighlighter1_590_627_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> List getEnumList() </span><span id="Codehighlighter1_590_627_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_590_627_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> getEnumList(OnTV.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_664_698_Open_Image" onclick="this.style.display='none'; Codehighlighter1_664_698_Open_Text.style.display='none'; Codehighlighter1_664_698_Closed_Image.style.display='inline'; Codehighlighter1_664_698_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_664_698_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_664_698_Closed_Text.style.display='none'; Codehighlighter1_664_698_Open_Image.style.display='inline'; Codehighlighter1_664_698_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Iterator iterator() </span><span id="Codehighlighter1_664_698_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_664_698_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> iterator(OnTV.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><p>以后我们就可以按照下面的方式使用枚举变量：OnTV.getEnum("Idol")。该调用从前面创建的枚举数据类型返回Idol。这个例子比较简单，实际上Enum类还提供了许多有用的方法，请参见本文后面提供的完整实例。 </p><p style="TEXT-INDENT: 2em">　　<b>2.4 Collections</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：扩展了Java Collection框架，增添了新的数据结构、迭代机制和比较操作符。 
</p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/collections.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-collections/v2.1/commons-collections-2.1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-collections/v2.1/commons-collections-2.1-src.zip" target="_blank">源代码</a>。 
</p><p style="TEXT-INDENT: 2em">　　■ 何时适用：几乎所有需要操作数据结构的重要Java开发项目都可以使用Collections API。和Java的标准实现相比，Collections API有着诸多优势。 
</p><p style="TEXT-INDENT: 2em">　　■ 示例应用：CollectionsDemo.java。要求CLASSPATH中包含commons-collections.jar。 
</p><p style="TEXT-INDENT: 2em">　　■ 说明： 
</p><p style="TEXT-INDENT: 2em">　　要在有限的文章篇幅之内详尽地介绍 Collections API实在是太困难了，不过这里仍将涵盖大多数最重要的类，希望能够引起你的兴趣，认真了解一下其余的类。Collections本身的文档也提供了许多资料并解释了每一个类的用法。 
</p><p style="TEXT-INDENT: 2em">　　Bag接口扩展标准的Java Collection，允许生成计数器来跟踪Bag里面的所有元素。当你想要跟踪进出某个集合的元素的总数时，Bag是非常有用的。由于Bag本身是一个接口，所以实际使用的应该是实现了该接口的类，例如HashBag或TreeBag--从这些类的名字也可以看出，HashBag实现的是一个HashMap的Bag，而TreeBag实现的是TreeMap的Bag。Bag接口中两个最重要的方法是：getCount(Object o)，用来返回Bag里面特定对象的出现次数；uniqueSet()，返回所有唯一元素。 
</p><p style="TEXT-INDENT: 2em">　　Buffer接口允许按照预定义的次序删除集合中的对象，删除次序可以是LIFO（Last In First Out，后进先出），或FIFO（First In First Out，先进先出），另外还可以是自定义的次序。下面来看看如何实现一个Buffer，按照自然次序删除元素。 
</p><p style="TEXT-INDENT: 2em">　　BinaryHeap类实现了Buffer接口，能够按照自然次序删除元素。如果要颠倒次序，则必须传入一个false，告诉Heap采用自然次序的逆序。</p><p> </p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">BinaryHeap heap </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> BinaryHeap();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 将元素加入该Heap</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">heap.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">…<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 删除一个元素</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">heap.remove();</span></div><br />调用该Heap的remove，按照自然次序，元素集合中的-10将被删除。如果我们要求按照逆序排序，则被删除的将是5。 
<p style="TEXT-INDENT: 2em">　　FastArrayList、FastHashMap和FastTreeMap类能够按照两种模式操作，超越了与它们对应的标准Collection。第一种模式是"慢模式"，类的修改操作（添加、删除元素）是同步的。与此相对，另一种模式是"快模式"，对这些类的访问假定为只读操作，因此不需要同步，速度较快。在快模式中，结构性的改动通过下列方式完成：首先克隆现有的类，修改克隆得到的类，最后用克隆得到的类替换原有的类。FastArrayList、FastHashMap和FastTreeMap类特别适合于那种初始化之后大部分操作都是只读操作的多线程环境。 
</p><p style="TEXT-INDENT: 2em">　　iterators包为各种集合和对象提供标准Java Collection包没有提供的迭代器。本文的示例应用示范了ArrayIterator，通过迭代方式访问Array的内容。iterators包里面各种迭代器的用法基本上与标准Java迭代器一样。 
</p><p style="TEXT-INDENT: 2em">　　最后，comparators包提供了一些实用的比较符。所谓比较符其实也是一个类，它定义的是如何比较两个属于同一类的对象，决定它们的排序次序。例如，在前面提到的Buffer类中，我们可以定义自己的比较符，用自定义的比较符来决定元素的排序次序，而不是采用元素的自然排序次序。下面来看看具体的实现经过。 <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ① 创建一个BinaryHeap类，但这一次参数中<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    指定NullComparator。NullComparator比较<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    null与其他对象，根据nullsAreHigh标记来<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    判断null值比其他对象大还是小：如果<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    nullsAreHigh的值是false，则认为null要比<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    其他对象小。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">BinaryHeap heap2 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> BinaryHeap<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> (</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> NullComparator(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ② 将一些数据（包括几个null值）加入heap：</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">heap2.add(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap2.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap2.add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Integer(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">-6</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />heap2.add(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ③ 最后删除一个元素，Bag包含的null将减少<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    一个，因为null要比其他对象小。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">heap2.remove();</span></div><br />有关其他类Commons组件的介绍就到这里结束。如果你想了解更多细节信息，请参见API文档，最好再看看这些包的源代码。 
<p style="TEXT-INDENT: 2em">　　<b>三、Web类</b></p><p style="TEXT-INDENT: 2em">　　Web类的组件用来执行与Web相关的任务。 
</p><p style="TEXT-INDENT: 2em">　　<b>3.1 FileUpload</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：一个可以直接使用的文件上载组件。 
</p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/fileupload/index.html" target="_blank">主页</a>。由于这个组件尚未正式发布，今年二月发布的Beta版又有许多BUG，所以建议从<a href="http://cvs.apache.org/builds/jakarta-commons/nightly/commons-fileupload/" target="_blank">nightly builds</a>下载最新的版本。 
</p><p style="TEXT-INDENT: 2em">　　■ 何时适用：当你想要在Java服务器环境中加入一个易用、高性能的文件上载组件之时。 
</p><p style="TEXT-INDENT: 2em">　　■ 示例应用：fileuploaddemo.jsp，fileuploaddemo.htm，和msg.jsp。要求服务器端应用目录的WEB-INF/lib下面有commons-fileupload-1.0-dev.jar。 
</p><p style="TEXT-INDENT: 2em">　　■ 说明： 
</p><p style="TEXT-INDENT: 2em">　　FileUpload组件解决了常见的文件上载问题。它提供了一个易用的接口来管理上载到服务器的文件，可用于JSP和Servlet之中。FileUpload组件遵从RFC1867，它分析输入请求，向应用程序提供一系列上载到服务器的文件。上载的文件可以保留在内存中，也可以放入一个临时位置（允许配置一个表示文件大小的参数，如果上载的文件超过了该参数指定的大小，则把文件写入一个临时位置）。另外还有一些参数可供配置，包括可接受的最大文件、临时文件的位置等。 
</p><p style="TEXT-INDENT: 2em">　　下面介绍一下使用FileUpload组件的步骤。 
</p><p style="TEXT-INDENT: 2em">　　首先创建一个HTML页面。注意，凡是要上载文件的表单都必须设置enctype属性，且属性的值必须是multipart/form-data，同时请求方法必须是POST。下面的表单除了上载两个文件，另外还有一个普通的文本输入框： <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">form name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">myform</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> action</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">fileuploaddemo.jsp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> method</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">post</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> enctype</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">multipart/form-data</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    输入你的名字:</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">text</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> size</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  图形:</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">file</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">myimage</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">br</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  文件:</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">file</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">myfile</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;&lt;</span><span style="COLOR: #000000">br </span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">submit</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Submit</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />     value</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Submit your files</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;</span></div><br />接下来创建JSP页面。 <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ① 检查输入请求是否为multipart的表单数据。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000"> isMultipart </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> FileUpload.<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  isMultipartContent(request);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ② 为该请求创建一个句柄，通过它来解析请求。执行<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    解析后，所有的表单项目都保存在一个List中。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">DiskFileUpload upload </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> DiskFileUpload();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 通过句柄解析请求，解析得到的项目保存在一个List中</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">List items </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> upload.parseRequest(request);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ③ 通过循环依次获得List里面的文件项目。要区分表示<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    文件的项目和普通的表单输入项目，使用isFormField()<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    方法。根据处理请求的要求，我们可以保存上载的文<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    件，或者一个字节一个字节地处理文件内容，或者打<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">    开文件的输入流。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">Iterator itr </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> items.iterator();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_486_1054_Open_Image" onclick="this.style.display='none'; Codehighlighter1_486_1054_Open_Text.style.display='none'; Codehighlighter1_486_1054_Closed_Image.style.display='inline'; Codehighlighter1_486_1054_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_486_1054_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_486_1054_Closed_Text.style.display='none'; Codehighlighter1_486_1054_Open_Image.style.display='inline'; Codehighlighter1_486_1054_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(itr.hasNext()) </span><span id="Codehighlighter1_486_1054_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_486_1054_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    FileItem item </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (FileItem) itr.next();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查当前的项目是普通的表单元素，还是一个上载的文件</span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_590_765_Open_Image" onclick="this.style.display='none'; Codehighlighter1_590_765_Open_Text.style.display='none'; Codehighlighter1_590_765_Closed_Image.style.display='inline'; Codehighlighter1_590_765_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_590_765_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_590_765_Closed_Text.style.display='none'; Codehighlighter1_590_765_Open_Image.style.display='inline'; Codehighlighter1_590_765_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(item.isFormField()) </span><span id="Codehighlighter1_590_765_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_590_765_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 获得表单域的名字</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    String fieldName </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> item.getFieldName();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果表单域的名字是name…</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(fieldName.equals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">))<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        request.setAttribute(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">msg</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Thank You: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> item.getString());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img id="Codehighlighter1_772_1052_Open_Image" onclick="this.style.display='none'; Codehighlighter1_772_1052_Open_Text.style.display='none'; Codehighlighter1_772_1052_Closed_Image.style.display='inline'; Codehighlighter1_772_1052_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_772_1052_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_772_1052_Closed_Text.style.display='none'; Codehighlighter1_772_1052_Open_Image.style.display='inline'; Codehighlighter1_772_1052_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_772_1052_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_772_1052_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 该项目是一个上载的文件，把它保存到磁盘。<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 注意item.getName()<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 会返回上载文件在客户端的完整路径名称，这似乎是一个BUG。<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 为解决这个问题，这里使用了fullFile.getName()。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">        File fullFile  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File(item.getName());  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        File savedFile </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        (getServletContext().getRealPath(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">),<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        fullFile.getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        item.write(savedFile);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br />我们可以通过上载句柄的upload.setSizeMax来限制上载文件的大小。当上载文件的大小超过允许的值时，程序将遇到异常。在上面的例子中，文件大小的限制值是-1，表示允许上载任意大小的文件。 
<p style="TEXT-INDENT: 2em">　　还有其他一些略有变化的使用形式，正如前面所指出的，我们可以在上载的文件上打开一个输入流，或者让它们驻留在内存中直至空间占用达到一定的限制值，或者在判断文件类型的基础上，以String或Byte数组的形式获取其内容，或者直接删除文件。这一切都只要使用FileItem类提供的方法就可以方便地做到（DefaultFileItem是FileItem的一个实现）。 </p><img src ="http://www.blogjava.net/yyg1107/aggbug/77719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-10-27 19:38 <a href="http://www.blogjava.net/yyg1107/articles/77719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons:巧用类和组件1 （1）</title><link>http://www.blogjava.net/yyg1107/articles/77718.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Fri, 27 Oct 2006 11:36:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/77718.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/77718.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/77718.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/77718.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/77718.html</trackback:ping><description><![CDATA[Jakarta Commons是Jakarta的子项目，它创建和维护着许多独立软件包，这些包一般与其他框架或产品无关，其中收集了大量小型、实用的组件，大部分面向服务器端编程。 
<p style="TEXT-INDENT: 2em">　　Commons的包分成两部分：Sandbox，Commons代码库。Sandbox是一个测试平台，用来检验各种设想、计划。本文介绍的组件属于Commons代码库，文章将展示各个组件的功能、适用场合，并通过简单的例子介绍其用法。 
</p><p style="TEXT-INDENT: 2em">　　<b>一、概述</b></p><p style="TEXT-INDENT: 2em">　　可重用性是Jakarta Commons项目的灵魂所在。这些包在设计阶段就已经考虑了可重用性问题。其中一些包，例如Commons里面用来记录日志的Logging包，最初是为其他项目设计的，例如Jakarta Struts项目，当人们发现这些包对于其他项目也非常有用，能够极大地帮助其他项目的开发，他们决定为这些包构造一个"公共"的存放位置，这就是Jakarta Commons项目。 
</p><p style="TEXT-INDENT: 2em">　　为了真正提高可重用性，每一个包都必须不依赖于其他大型的框架或项目。因此，Commons项目的包基本上都是独立的，不仅是相对于其他项目的独立，而且相对于Commons内部的大部分其他包独立。虽然存在一些例外的情况，例如Betwixt包要用到XML API，但绝大部分只使用最基本的API，其主要目的就是要能够通过简单的接口方便地调用。 
</p><p style="TEXT-INDENT: 2em">　　不过由于崇尚简洁，许多包的文档变得过于简陋，缺乏维护和支持，甚至有一部分还有错误的链接，文档也少得可怜。大部分的包需要我们自己去找出其用法，甚至有时还需要我们自己去分析其适用场合。本文将逐一介绍这些包，希望能够帮助你迅速掌握这一积累了许多人心血的免费代码库。 
</p><p style="TEXT-INDENT: 2em">　　说明：Jakarta Commons和<a href="http://commons.apache.org/" target="_blank">Apache Commons</a>是不同的，后者是Apache Software Foundation的一个顶层项目，前者则是Jakarta项目的一个子项目，同是也是本文要讨论的主角。本文后面凡是提到Commons的地方都是指Jakarta的Commons。 
</p><p style="TEXT-INDENT: 2em">　　为了便于说明，本文把Commons项目十八个成品级的组件（排除了EL、Latka和Jexl）分成5类，如下表所示。 
</p><p style="TEXT-INDENT: 2em"></p><center><img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://linux.ccidnet.com/col/attachment/2003/8/247208.gif" /></center><p style="TEXT-INDENT: 2em">　　必须指出的是，这种分类只是为了方便文章说明，Commons项目里面实际上并不存在这种分类，同时这些分类的边界有时也存在一定的重叠。 
</p><p style="TEXT-INDENT: 2em">　　本文首先介绍Web相关类和其他类里面的组件，下一篇文章将涉及XML相关、包装这两类，最后一篇文章专门介绍属于工具类的包。 
</p><p style="TEXT-INDENT: 2em">　　<b>二、其他类</b></p><p style="TEXT-INDENT: 2em">　　CLI、Discovery、Lang和Collections包归入其他类，这是因为它们都各自针对某个明确、实用的小目标，可谓专而精。 
</p><p style="TEXT-INDENT: 2em">　　<b>2.1 CLI</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：CLI即Command Line Interface，也就是"命令行接口"，它为Java程序访问和解析命令行参数提供了一种统一的接口。 
</p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/cli/index.html" target="_blank">主页</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/binaries/commons-discovery-0.2.zip" target="_blank">二进制</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/source/commons-discovery-0.2-src.zip" target="_blank">源代码</a></p><p style="TEXT-INDENT: 2em">　　■ 何时适用：当你需要以一种一致的、统一的方式访问命令行参数之时。 
</p><p style="TEXT-INDENT: 2em">　　■ 示例应用：CLIDemo.java。CLASSPATH中必须包含commons-cli-1.0.jar。 
</p><p style="TEXT-INDENT: 2em">　　■ 说明： 
</p><p style="TEXT-INDENT: 2em">　　有多少次你不得不为一个新的应用程序重新设计新的命令行参数处理方式？如果能够只用某个单一的接口，统一完成诸如定义输入参数（是否为强制参数，数值还是字符串，等等）、根据一系列规则分析参数、确定应用要采用的路径等任务，那该多好！答案就在CLI。 
</p><p style="TEXT-INDENT: 2em">　　在CLI中，每一个想要在命令中指定的参数都是一个Option对象。首先创建一个Options对象，将各个Option对象加入Options对象，然后利用CLI提供的方法来解析用户的输入参数。Option对象可以要求用户必须输入某个参数，例如必须在命令行提供文件名字。如果某个参数是必须的，创建Option对象的时候就要显式地指定。 
</p><p style="TEXT-INDENT: 2em">　　下面是使用CLI的步骤。 <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ①  创建一个Options：</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">Options options </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Options();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />options.addOption(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">current time</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ② 创建一个解析器，分析输入：</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">CommandLineParser parser </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> BasicParser();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />CommandLine cmd;<br /><img id="Codehighlighter1_195_234_Open_Image" onclick="this.style.display='none'; Codehighlighter1_195_234_Open_Text.style.display='none'; Codehighlighter1_195_234_Closed_Image.style.display='inline'; Codehighlighter1_195_234_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_195_234_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_195_234_Closed_Text.style.display='none'; Codehighlighter1_195_234_Open_Image.style.display='inline'; Codehighlighter1_195_234_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_195_234_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_195_234_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    cmd </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> parser.parse(options, args); <br /><img id="Codehighlighter1_262_290_Open_Image" onclick="this.style.display='none'; Codehighlighter1_262_290_Open_Text.style.display='none'; Codehighlighter1_262_290_Closed_Image.style.display='inline'; Codehighlighter1_262_290_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_262_290_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_262_290_Closed_Text.style.display='none'; Codehighlighter1_262_290_Open_Image.style.display='inline'; Codehighlighter1_262_290_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />}</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (ParseException pe) </span><span id="Codehighlighter1_262_290_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_262_290_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    usage(options);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ③ 最后就可以根据用户的输入，采取相应的操作：</span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_348_420_Open_Image" onclick="this.style.display='none'; Codehighlighter1_348_420_Open_Text.style.display='none'; Codehighlighter1_348_420_Closed_Image.style.display='inline'; Codehighlighter1_348_420_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_348_420_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_348_420_Closed_Text.style.display='none'; Codehighlighter1_348_420_Open_Image.style.display='inline'; Codehighlighter1_348_420_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (cmd.hasOption(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)) </span><span id="Codehighlighter1_348_420_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_348_420_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Nice to meet you: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    cmd.getOptionValue(</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">n</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br />这就是使用CLI的完整过程了。当然，CLI还提供了其他高级选项，例如控制格式和解析过程等，但基本的使用思路仍是一致的。请参见本文最后提供的示例程序。 
<p style="TEXT-INDENT: 2em">　　<b>2.2 Discovery</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：Discovery组件是发现模式（Discovery Pattern）的一个实现，它的目标是按照一种统一的方式定位和实例化类以及其他资源。 
</p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/discovery/" target="_blank">主页</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/binaries/commons-discovery-0.2.zip" target="_blank">二进制</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/source/commons-discovery-0.2-src.zip" target="_blank">源代码</a>。 
</p><p style="TEXT-INDENT: 2em">　　■ 何时适用：当你想用最佳的算法在Java程序中查找Java接口的各种实现之时。 
</p><p style="TEXT-INDENT: 2em">　　■ 应用实例：DiscoveryDemo.java，MyInterface.java，MyImpl1.java，MyImpl2.java，MyInterface。要求CLASSPATH中必须包含commons-discovery.jar和commons-logging.jar。 
</p><p style="TEXT-INDENT: 2em">　　■ 说明： 
</p><p style="TEXT-INDENT: 2em">　　Discovery的意思就是"发现"，它试图用最佳的算法查找某个接口的所有已知的实现。在使用服务的场合，当我们想要查找某个服务的所有已知的提供者时，Discovery组件尤其有用。 
</p><p style="TEXT-INDENT: 2em">　　考虑一下这种情形：我们为某个特别复杂的任务编写了一个接口，所有该接口的实现都用各不相同的方式来完成这个复杂任务，最终用户可以根据需要来选择完成任务的具体方式。那么，在这种情形下，最终用户应该用什么办法来找出接口的所有可用实现（即可能的完成任务的方式）呢？ 
</p><p style="TEXT-INDENT: 2em">　　上面描述的情形就是所谓的服务-服务提供者体系。服务的功能由接口描述，服务提供者则提供具体的实现。现在的问题是最终用户要用某种办法来寻找系统中已经安装了哪些服务提供者。在这种情形下，Discovery组件就很有用了，它不仅可以用来查找那些实现了特定接口的类，而且还可以用来查找资源，例如图片或其他文件等。在执行这些操作时，Discovery遵从Sun的服务提供者体系所定义的规则。 
</p><p style="TEXT-INDENT: 2em">　　由于这个原因，使用Discovery组件确实带来许多方便。请读者参阅本文后面示例程序中的接口MyInterface.java和两个实现类MyImpl1.java、MyImple2.java，了解下面例子的细节。在使用Discovery的时候要提供MyInterface文件，把它放入META-INF/services目录，注意该文件的名字对应接口的完整限定名称（Fully Qualified Name），如果接口属于某个包，该文件的名字也必须相应地改变。<br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ① 创建一个类装入器的实例。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">ClassLoaders loaders </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    ClassLoaders.getAppLoaders(MyInterface.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, getClass(), </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ② 用DiscoverClass的实例来查找实现类。</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">DiscoverClass discover </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> DiscoverClass(loaders);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> …<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ③ 查找实现了指定接口的类：</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">Class implClass </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> discover.find(MyInterface.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Implementing Provider: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> implClass.getName());</span></div><br />运行上面的代码，就可以得到在MyInterface文件中注册的类。再次提醒，如果你的实现是封装在包里面的，在这里注册的名字也应该作相应地修改，如果该文件没有放在正确的位置，或者指定名字的实现类不能找到或实例化，程序将抛出DiscoverException，表示找不到符合条件的实现。下面是MyInterface文件内容的一个例子：MyImpl2 # Implementation 2。 
<p style="TEXT-INDENT: 2em">　　当然，实现类的注册办法并非只有这么一种，否则的话Discovery的实用性就要大打折扣了！实际上，按照Discovery内部的类查找机制，按照这种方法注册的类将是Discovery最后找到的类。另一种常用的注册方法是通过系统属性或用户定义的属性来传递实现类的名字，例如，放弃META-INF/services目录下的文件，改为执行java -DMyInterface=MyImpl1 DiscoveryDemo命令来运行示例程序，这里的系统属性是接口的名字，值是该接口的提供者，运行的结果是完全一样的。 
</p><p style="TEXT-INDENT: 2em">　　Discovery还可以用来创建服务提供者的(singleton)实例并调用其方法，语法如下：((MyInterface)discover.newInstance(MyInterface.class)).myMethod();。注意在这个例子中，我们并不知道到底哪一个服务提供者实现了myMethod，甚至我们根本不必关心这一点。具体的情形与运行这段代码的方式以及运行环境中已经注册了什么服务提供者有关，在不同的环境下运行，实际得到的服务提供者可能不同。 
</p><p style="TEXT-INDENT: 2em">　　<b>2.3 Lang</b></p><p style="TEXT-INDENT: 2em">　　■ 概况：Lang是java.lang的一个扩展包，增加了许多操作String的功能，另外还支持C风格的枚举量。 
</p><p style="TEXT-INDENT: 2em">　　■ 官方资源：<a href="http://jakarta.apache.org/commons/lang.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-lang/v1.0.1/commons-lang-1.0.1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-lang/v1.0.1/commons-lang-1.0.1-src.zip" target="_blank">源代码</a>。 
</p><p style="TEXT-INDENT: 2em">　　■ 何时适用：当java.lang包提供的方法未能满足需要，想要更多的功能来处理String、数值和System属性时；还有，当你想要使用C风格的枚举量时。 
</p><p style="TEXT-INDENT: 2em">　　■ 示例应用：LangDemo.java，Mortgage.java，OnTV.java。CLASSPATH中必须包含commons-lang.jar。 
</p><p style="TEXT-INDENT: 2em">　　■ 说明： 
</p><p style="TEXT-INDENT: 2em">　　这个包提供了许多出于方便目的而提供的方法，它们中的大多数是静态的，简化了日常编码工作。StringUtils类是其中的一个代表，它使得开发者能够超越标准的java.lang.String包来处理字符串。使用这些方法很简单，通常只要在调用静态方法时提供适当的参数就可以了。例如，如果要将某个单词的首字符改为大写，只需调用：StringUtils.capitalise("name")，调用的输出结果是Name。请浏览StringUtils API文档了解其他静态方法，也许你会找到一些可以直接拿来使用的代码。本文提供的示例程序示范了其中一些方法的使用。 
</p><p style="TEXT-INDENT: 2em">　　另一个值得注意的类是RandomStringUtils，它提供了生成随机字符串的方法，用来创建随机密码实在太方便了。 
</p><p style="TEXT-INDENT: 2em">　　NumberUtils类提供了处理数值数据的方法，许多方法值得一用，例如寻找最大、最小数的方法，将String转换成数值的方法，等等。NumberRange和CharRange类分别提供了创建和操作数值范围、字符范围的方法。 
</p><p style="TEXT-INDENT: 2em">　　Builder包里的类提供了一些特殊的方法，可用来构造类的toString、hashCode、compareTo和equals方法，其基本思路就是构造出类的高质量的toString、hashCode、compareTo和equals方法，从而免去了用户自己定义这些方法之劳，只要调用一下Builder包里面的方法就可以了。例如，我们可以用ToStringBuilder来构造出类的toString描述，如下例所示： <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_22_216_Open_Image" onclick="this.style.display='none'; Codehighlighter1_22_216_Open_Text.style.display='none'; Codehighlighter1_22_216_Closed_Image.style.display='inline'; Codehighlighter1_22_216_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_22_216_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_216_Closed_Text.style.display='none'; Codehighlighter1_22_216_Open_Image.style.display='inline'; Codehighlighter1_22_216_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Mortgage </span><span id="Codehighlighter1_22_216_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_22_216_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000"> rate;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> years;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <img src="http://www.blogjava.net/images/dot.gif" />.<br /><img id="Codehighlighter1_97_214_Open_Image" onclick="this.style.display='none'; Codehighlighter1_97_214_Open_Text.style.display='none'; Codehighlighter1_97_214_Closed_Image.style.display='inline'; Codehighlighter1_97_214_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_97_214_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_97_214_Closed_Text.style.display='none'; Codehighlighter1_97_214_Open_Image.style.display='inline'; Codehighlighter1_97_214_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> String toString() </span><span id="Codehighlighter1_97_214_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_97_214_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ToStringBuilder(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">).<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">rate</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,  </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.rate).<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">years</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.years).<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            toString();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><img src ="http://www.blogjava.net/yyg1107/aggbug/77718.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-10-27 19:36 <a href="http://www.blogjava.net/yyg1107/articles/77718.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts  VS Turbine [转]</title><link>http://www.blogjava.net/yyg1107/articles/76728.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Mon, 23 Oct 2006 04:13:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/76728.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/76728.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/76728.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/76728.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/76728.html</trackback:ping><description><![CDATA[Struts 比 Turbine 的结构简单多了,换而言之,Struts 是一个非常纯的 Web Framework,它也仅仅只是一个 Framework.Struts 的官方定义中说了其符合 MVC,我并不是非常认同.Struts 很好的完成了 VC(Visual &amp; Control),但它并没有提供相应的M(Module),或者说不明显.Struts 最好的搭档可能就是 EJB 了,因为 EJB 补充了它的 M.<br />而 Turbine 则不然,它的设计思路决定了它是一个 Web 应用的完全解决方案.Turbine 并不是十分符合 J2EE 标准.它有自己一整套解决方案,它是一个真正意义上的 MVC 模式框架.它具有大量的子项目来支持它的应用(子项目树仅次于Jarkarta Commons 位居第二)<br />Turbine 要比 Struts 难理解,难学,但是掌握它是有意义的.如果你只是要写一个 Web App 的话,Turbine 开发要比 Struts 快.<br />Turbine 支持 Velocity,WebMacro,Cocoon(XSLT) 等等,虽然它也支持JSP,不过它的最最亲密的战友任是 Velocity.<br />Struts 对于写过 JSP 和 Servlet 的人来说可能会很轻切.Jakarta 项目组的相关项目 Taglibs 提供了大量的 Tag 以支持 Struts,使 Struts 的结构性和统一性变得很好,Struts 的另一个 Turbine 不如的地方是它的 mapping-forward 机制,在 Struts 中是用 struts-config.xml 文件来管理的,虽然随着你的项目的扩大,这个xml文件会变得很大以至于难以维护(一般大的项目中会有专人管理这个文件),但是它的统一性和导航逻辑性比 Turbine 好的多,Turbine 把相应的逻辑以 Velcoity Template 类来控制.在相应的Velocity 页面中也会用相关的导航.<br /><form name="aform" action="$link.setPage(" test.vm?).setaction(?hello?)="">和 Struts 的 struts-config.xml 相比有些乱(不知道 Turbine 3.0 中会不会有些提高).<br />Turbine 的一个极棒的子项目是 Torque,它提供了一个很好的 JDO 环境,而且 Torque 的机制会将 XML 格式的数据定义编辑成相关数据库的表(支持现在流行的几乎所有的数据库),并编译出和表结构一一对应的Java Class. <br />Torque 中的 Criteria 和 BasePeer 类具有极高的代码水准,我会在以后的文章中仔细剖析这两个类.<br />写到这里吧,最近的文章我会针对于 Turbine 做详细的分析和说明.<br />还有一点很重要,现在 Turbine 支持分布式计算方式(以前批评 Turbine 应用局限性的很重要的理由),这个子项目叫 JCS.<br />http://jakarta.apache.org/turbine<br />http://jakarta.apache.org/struts<br />注:大家都用过 Tomcat 吧,在Tomcat 4.1.10 以上版本提供了 Administrator Tools 图形配置界面,这个系统是基于Struts的,看看源代码吧,几乎用到了 Struts 所有的类和方法,极好的示例代码哦 </form><img src ="http://www.blogjava.net/yyg1107/aggbug/76728.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-10-23 12:13 <a href="http://www.blogjava.net/yyg1107/articles/76728.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDBC数据库连接池</title><link>http://www.blogjava.net/yyg1107/articles/73015.html</link><dc:creator>young</dc:creator><author>young</author><pubDate>Sat, 30 Sep 2006 05:42:00 GMT</pubDate><guid>http://www.blogjava.net/yyg1107/articles/73015.html</guid><wfw:comment>http://www.blogjava.net/yyg1107/comments/73015.html</wfw:comment><comments>http://www.blogjava.net/yyg1107/articles/73015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yyg1107/comments/commentRss/73015.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yyg1107/services/trackbacks/73015.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ConnectionHandler.javapackage com.ofis.DBConnection;import java.lang.reflect.*;import java.sql.*;import org.apache.xalan.lib.sql.ConnectionPool;/** *//** *  * 数据库连接的代理类 * */class ConnectionHandler imp...&nbsp;&nbsp;<a href='http://www.blogjava.net/yyg1107/articles/73015.html'>阅读全文</a><img src ="http://www.blogjava.net/yyg1107/aggbug/73015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yyg1107/" target="_blank">young</a> 2006-09-30 13:42 <a href="http://www.blogjava.net/yyg1107/articles/73015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>