<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    seaairland

     

    Java利器Jakarta Commons(一)

    Jakarta Commons是Jakarta的一個子項目,目的是創建和維護獨立于其他框架和產品的程序包(packages)。這些程序包是一些服務于小范圍的有效組件的集合,通常適用于服務器端編程。

    Commons項目分為兩部分:Sandbox和Commons庫。Sandbox用于測試。本文關注庫組件,包括它們什么時候使用,在那里,以及用例子說明如何使用。

    簡要介紹

    Jakarta Commons項目源于重用,其中的程序包必須確保能夠重用。有一些包來自于其他項目,例如通用日志包是Jakarta Struts的一部分。當開發者發現某個包對于其他項目很有用,可以縮短開發周期,他們決定將這些包做成通用組件。這就是Jakarta Commons項目。

    要真正做到可重用,每個程序包必須獨立于其他較大的框架和項目。因此,Commons項目中的每個包在很大程度上是獨立的,不僅相對于其他項目,甚至對于其他包也是如此。違反這一原則的情況是存在的,但決大多數情況是使用成熟的APIs。例如,Betwixt包建立在XML APIs基礎之上。盡管這個項目的本意是建立不依賴其他組件的程序包。

    大多數程序包十分簡潔,以至于缺少必要的文檔、維護和幫助。有些包甚至只有錯誤的連接和極少的文檔。大多數情況下,你只能自己摸索如何使用它們,為什么使用它們。希望這篇文章對你有幫助。

    注意:Jakarta Commons與Apache Commons是不同的。后者是Apache Software Foundation(ASF)的頂級項目。而前者是ASF的另一個頂級項目Jakarta的子項目,是本文介紹的對象。而且,Jakarta Commons只使用Java。在本文中Commons指的是Jakarta Commons。


    組件

    為了組織方便,我將18個(包括EL,Latka和Jexl)Commons組件分為五類。如下表:

    組件類別
    組件

    Web相關
    FileUpload,HTTPClient和Net

    XML相關
    Betwixt,Digester,Jelly和JXPath

    工具
    BeanUtils,Logging,DBCP,Pool和 Validator

    打包
    Codec 和 Modeler

    小程序
    CLI,Discovery,Lang和 Collections


    要注意的是這個分類只是對本文而言,在Commons項目中是不存在的。在某種程度上分類是重疊的。本文將介紹Web相關和小程序類,下篇文章包括XML相關和打包類,工具類在最后一篇文章中。

    小程序類
    將CLI,Discovery,Lang和 Collections歸入小程序類是因為它們都是為了一個小而實用的目的編寫的。

    1.CLI

    概要:CLI(Command Line Interface)為你的Java程序提供讀取和解析命令行參數的通用接口。
    在那得到:主頁,程序,源代碼。
    何時使用:需要統一操作命令行參數時。
    例子程序:CLIDemo.java,需要將commons-cli-1.0.jarcommons加入CLASSPATH中。
    描述:通常在完成一個Java程序時不得不重寫應用程序輸入參數的處理部分。如果有一個唯一的接口用來定義﹑解析和讀取輸入參數,以決定程序的運行方式不是很好嗎?CLI就是答案。
    對于CLI,命令行中每個要處理的參數都是一個Option。創建一個Options對象,將Option對象添加進去,然后用CLI提供的函數解析用戶的輸入參數。一個Option也許也需要用戶輸入一個值,例如文件名。這時Option必須在指定處創建。
    CLI使用步驟如下:
    1.創建Options:
    Options options = new Options();
    Options.addOption(“t”,false,”current time”);

    2.創建解析器解析用戶輸入:
    CommandLineParser parser = new BasicParser();
    CommandLine cmd;
    try{
    cmd = parser.parse(options, args);
    } catch(ParseException pe) {
    usage(options);
    return;
    }

    3.根據用戶輸入執行相應操作:

    if(cmd.hasOption(“n”)) {
    System.err.println(“Nice to meet you: ”+ cmd.getOptionValue(‘n’));
    }

    以上基本就是使用CLI的全過程。當然,CLI提供其他高級選項用于控制各種格式和解析器,但基本操作是相同的。完整的例子可以看demo。

    2.Discovery

    概要:discovery模式的實現,提供定位與實例化類或其他資源的通用方法。
    在那得到:主頁,程序,源代碼。該包處于pre-release狀態。
    何時使用:需要快速找到你的代碼中Java接口的實現時。
    例子程序:DiscoveryDemo.java,MyInterface.java,MyImpl1.java,MyImpl2.java, MyInterface。需要將commons-discovery.jar和commons-logging.jar添到CLASSPATH中。

    描述:Discovery的目的是使用最好的算法得到接口的所有實現。當用戶想找到所有的提供某一服務的提供商時,這將特別有用。

    假設你寫了一個針對某一難題的接口。這個接口的所有實現將以唯一的編碼方式解決這一難題。真正的用戶在實際解決這一難題時將會有多種選擇。他怎么才能知道接口的那種實現在他的系統中是可行的?

    這就是Service與Service Provider結構。Service就是你定義的接口。Service Providers提供Service的實現。用戶需要選擇Service Providers。Discovery組件用多種方法提供幫助。注意Discovery不僅用于發現實現類,而且可以尋找資源,例如圖像或其他文件。它遵照Sun的Service Provider Architecture規范。

    同樣,Discovery的使用也很簡單。例子程序中,MyImpl1和MyImpl2是MyInterface接口的實現。MyInterface文件必須在META-INF/services目錄下。注意這個文件必須對應接口的全路徑。如果接口在包內,那么文件名也要相應改動。

    1.取得ClassLoader:

    ClassLoaders loaders =

    ClassLoaders.getAppLoaders(MyInterface.class, getClass(), false);

    2.創建DiscoverClass用于查找實現類:

    DiscoverClass discover = new DiscoverClass(loaders);

    3.查找實現類:

    Class implClass = discover.find(MyInterface.class);

    System.err.println("Implementing Provider: " + implClass.getName());

    運行以上代碼(DiscoveryDemo.java)將得到MyInterface文件中注冊的類,如下所示。再次提醒,如果實現包含在一個包結構內,文件名必須做相應的修改。如果這個文件不在規定目錄下,或實現類不能實例化或定位,將拋出DiscoveryException異常,表明找不到MyInterface的實現。

    MyImpl2 # Implementation 2

    當然,這不是注冊實現的唯一方法,否則Discovery還有什么用!事實上,這是Discovery發現類的內部機制的最后一步。其他方法包括在系統屬性或用戶屬性中定義實現類的名字。例如,刪除META-INF/services目錄下的文件,按以下輸入運行demo,結果相同。這里系統屬性是接口名,而值是接口實現提供者。

    java -DMyInterface=MyImpl1 DiscoveryDemo

    Discovery也可用于創建(單例)服務提供者的實例并調用它們的函數。如下:

    ((MyInterface)discover.newInstance(MyInterface.class)).myMethod();

    注意此時我們并不知道那個服務提供者實現myMethod函數,我們也不關心。這個函數的實現取決于以何種方式運行以上代碼以及注冊的服務提供者。

    3.Lang

    概要:java.lang包的擴展,增加許多對String的操作。提供類C語言的枚舉。

    在那得到:主頁,程序,源代碼。這里介紹的是Lang1.0,翻譯本文時Lang2.0已經發布。

    何時使用:當對java.lang提供的默認實現感到厭煩,想更好的控制String的操作,數值函數以及系統屬性時,還有,想使用C語言風格的枚舉時。

    例子程序:LangDemo.java, Mortgage.java, OnTV.java。需要將commons-lang.jar加入CLASSPATH中。

    描述:這個包中提供的很多工具函數可以簡化Java程序員的工作。這些函數可以減少實現日常功能的編程量。特別是StringUtils類,它提供比標準的java.lang.String包更強的操作字符串的功能。它們的使用十分簡單,只要用正確的參數調用一個靜態函數。例如,要將一句話變為以大寫開頭只要:

    StringUtils.capitalise("name");

    這個函數的輸出就象我們需要的“Name”。瀏覽StringUtils API的其他靜態函數,你可能會發現對你有用的。例子程序中使用了一些。

    另一個有趣的類是RandomStringUtils。這個類中的函數產生隨機字符串,這在生成隨機密碼時很有用。

    類NumberUtils提供數據操作的函數,包括最大最小值函數,以及將字符串轉換為數字的函數。NumberRange和CharRange分別處理數字與字符的范圍。

    Builder包中的類提供為類添加toString,hashCode,compareTo和equals函數的功能。也就是說,自己不需編碼就可以在類中添加高質量的toString,hashCode,compareTo和equals函數,只要使用Builder包中的函數就可以了。例如,用ToStringBuilder函數給類添加toString方法:

    public class Mortgage {
    private float rate;
    private int years;
    ....
    public String toString() {
    return new ToStringBuilder(this).append("rate", this.rate)
    .append("years", this.years). toString();
    }
    }
    為什么使用這個函數那?因為它使用通用的方法處理所有的數據類型,恰當的返回null,同時可以控制對象和聚集的細節層次。這對于所有builder中的函數有效,而且語法同上所示相近。

    作為一個Java程序員,如果你懷念C語言風格的枚舉,那么這個包中的類型安全的Enum數據類型將填補這一空白。Enum類是抽象類,所以要創建自己的枚舉,必須擴展這個類。如下例所示:

    1.定義并擴展枚舉類:

    import org.apache.commons.lang.enum.Enum;

    import java.util.Map;

    import java.util.List;

    import java.util.Iterator;



    public final class OnTV extends Enum {



    public static final OnTV IDOL = new OnTV("Idol");

    public static final OnTV SURVIVOR = new OnTV("Survivor");

    public static final OnTV SEINFELD = new OnTV("Seinfeld");



    private OnTV(String show) {

    super(show);

    }



    public static OnTV getEnum(String show){

    return (OnTV) getEnum(OnTV.class, show);

    }



    public static Map getEnumMap() {

    return getEnumMap(OnTV.class);

    }



    public static List getEnumList() {

    return getEnumList(OnTV.class);

    }



    public static Iterator iterator() {

    return iterator(OnTV.class);

    }

    }

    2.現在就可以在你的方法中使用枚舉了:

    OnTV.getEnum("Idol");

    該行代碼從我們創建的枚舉數據類型中返回Idol項。Enum類還有其他有用的函數。

    4.Collections

    概要:對Java Collection框架的擴展,加入了新的數據結構,iterators和比較器。

    在那得到:主頁,程序,源代碼。

    何時使用:強烈建議在需要處理數據結構的Java項目盡可能使用Collections API,從中你會獲得比Java默認實現大的多的好處。

    例子程序:CollectionsDemo.java。需要將commons-collections.jar加入CLASSPATH中。

    描述:Collections API中有很多類,很難在一節中全介紹出來。所以這里我著重介紹最重要的類,希望你能感興趣去仔細研究其他類。API附帶的文檔對每個類都有詳細的描述。

    Bag接口擴展了Java Collections,加入了對所有成員的計數,它在要統計進入進出元素數時很有用。因為Bag是一個接口,所以實際使用的是它的實現類,如HashBag或TreeBag。顧名思義,HashBag是基于HashMap的Bag的實現,而Treebag是基于TreeMap的。Bag接口中的兩個重要方法是getCount(Object o)和uniqueSet()。前者返回Bag中某特殊元素的個數,后者返回Bag中的唯一元素(譯者理解為:元素類型,原文:the unique elements)的集合。

    Buffer接口允許按照預定順序從聚集中刪除對象,可以是后進先出,先進先出,或自定義的順序。下面的例子演示了如何以自然排序的順序刪除元素的:

    1.BinaryHeap類實現Buffer接口,并按自然排序刪除元素。若想以反自然排序刪除,以false為參數即可:

    BinaryHeap heap = new BinaryHeap();

    2.添加元素:

    heap.add(new Integer(-1));

    heap.add(new Integer(-10));

    heap.add(new Integer(0));

    heap.add(new Integer(-3));

    heap.add(new Integer(5));

    3.調用remove方法。按自然排序,-10將被刪除,反之5被刪除:

    heap.remove();

    FastArrayList﹑FastHashMap和FastTreeMap類使用兩種模式操作相應的Collection類。第一種為慢模式,是這些類初始化后的默認模式。在慢模式下,這些類的結構變化是同步的。在快模式下,對這些類的訪問被認為是只讀的,因此更快一些,而且不發生同步。在快模式下要改變類的結構,要先克隆該類,在克隆類上修改,然后覆蓋該類。這些類在多數訪問為只讀的多線程環境中十分有用。

    Iterator包提供了許多常規Java Collections包中沒有的聚集和對象的iterator。例子程序中演示了iterator數組的ArrayIterator。這些iterator同普通Java iterators的用法相同。

    最后,comparator包中提供了一些有用的比較器,它們用來定義比較和決定同一類的兩個對象的順序。例如,在我們前面提到的Buffer中,可以定義自己比較器,用它替代自然排序決定順序。如下:

    1.這次使用NullComparator創建BinaryHeap。NullComparator根據標志nullAreHigh的值決定null與其他對象的大小。如果取值為false,表示null比其他對象小:

    BinaryHeap heap2 = new BinaryHeap(new NullComparator(false));

    2.添加對象,包括一些null

    heap2.add(null);

    heap2.add(new Integer("6"));

    heap2.add(new Integer("-6"));

    heap2.add(null);

    3.最后,執行刪除操作。因為null小于其他對象,Bag最后剩下的是null

    heap2.remove();

    到這里,小程序類就介紹完了。更多的細節請看API文檔,或者這些包的源代碼。



    Web相關類

    Web相關類中組件幫助Java程序員完成Web相關的任務。

    1.FileUpload

    概要:現成的文件上傳組件。

    在那得到:主頁。

    何時使用:當Java服務器環境中需要簡單易用并且高效的文檔上傳組件時。

    例子程序:fileuploaddemo.jsp,fileuploaddemo.htm,msg.jsp。需要將commons-fileupload-1.0-dev.jar添加到程序的WEB-INF/lib目錄下。

    描述:FileUpload解決了文件上傳時服務端的常見問題,提供了一個控制文件上傳的易用的接口,可用在JSP頁和servlet中。它符合RFC1867協議標準,解析輸入請求,并將上傳到服務器的一系列文件的分塊交給應用程序。上傳的文件保存在內存中或臨時目錄中(這由一個表示文件大小的參數決定,如果上傳的文件大小超過該參數值,文件將被寫入臨時目錄)。你也可以設置其他參數,例如可接收的文件的最大尺寸以及臨時文件目錄。

    FileUpload的使用分為幾步,我將用一個在一個頁中同時上傳兩個不同文件的例子說明。

    1.創建HTML頁。注意為了確保上傳文件的類型是被允許的,enctype參數必須為multipart/form-data,請求參數method必須為POST。還有一點要注意的是該頁面不但有兩個文件控件還有一個普通文本控件。

    <form name="myform" action="fileuploaddemo.jsp"

    method="post" enctype="multipart/form-data">

    Specify your name:<br />

    <input type="text" name="name" size="15"/><br />

    Specify your Image:<br />

    <input type="file" name="myimage"><br/>

    Specify your File:<br />

    <input type="file" name="myfile"><br /><br />

    <input type="submit" name="Submit" value="Submit your files"/>

    </form>

    2.創建JSP頁。

    a.檢查輸入請求是不是多段數據。

    boolean isMultipart = FileUpload.isMultipartContent(request);

    b.創建請求處理器,解析請求,結果存于一個list中。

    DiskFileUpload upload = new DiskFileUpload();

    List items = upload.parseRequest(request);

    c.遍歷這個list訪問每個單獨的文件項。用isFormField()函數區分上傳文件和常規類型域。根據需要,可以逐字節的讀取上傳的文件,或者使用輸入流。

    Iterator itr = items.iterator();



    while(itr.hasNext()) {

    FileItem item = (FileItem) itr.next();



    // check if the current item is a form field or an uploaded file

    if(item.isFormField()) {



    // get the name of the field

    String fieldName = item.getFieldName();



    // if it is name, we can set it in request to thank the user

    if(fieldName.equals("name"))

    request.setAttribute("msg", "Thank You: " + item.getString());



    } else {



    // the item must be an uploaded file save it to disk. Note that there

    // seems to be a bug in item.getName() as it returns the full path on

    // the client's machine for the uploaded file name, instead of the file

    // name only. To overcome that, I have used a workaround using

    // fullFile.getName().

    File fullFile = new File(item.getName());

    File savedFile = new File(getServletContext().getRealPath("/"),

    fullFile.getName());

    item.write(savedFile);

    }

    }

    可以在上傳處理器中用upload.setSizeMax限制上傳文件的最大尺寸,當上傳文件大小超過該尺寸將會拋出異常。上例中,若將該尺寸設為-1,就可以上傳任何大小的文件。

    這個例子還可以有一個小變化。想上面提到的,可以使用輸入流上傳文件。過程是將上傳的內容駐留在內存中直到某一閾值,取得內容的類型,把它們存為字符串或字節數組,最后從內存中刪除。FileItem中函數完成了該過程(DefaultFileItem是它的實現)。

    2.HttpClient

    概要:擴展java.net包,提供類似瀏覽器的功能。

    在那得到:主頁,程序,源代碼。源代碼和程序為beta1版。

    何時使用:當要實現Web瀏覽器時,或你的程序需要有效的控制HTTP/HTTPS連接時。

    例子程序:HttpClientDemo.java。需要將commons-httpclient.jar和common-logging.jar加入CLASSPATH中,JDK為1.4或更高版本。

    描述:HttpClient是java.net的擴展程序包,它提供許多函數幫助你創建基于HTTP協議的各種分布式應用或者嵌入應用程序處理HTTP操作。這個庫提供比Commons的其他包更詳細的文檔,并附帶很多例子。這里將講解怎樣開發一個提取Web網頁的程序。HttpClient附帶的文檔中有一個類似的例子,我將擴展它使它支持SSL。注意這個例子必須運行于JDK 1.4或更高版本上,因為它需要JDK1.4中的Java Secure Socket Connection庫。

    1.找一個可以通過HTTPS下載的網頁,例如https://www.paypal.com/。確保文件%JAVA_HOME%/jre/lib/security/java.security有類似如下的一行:

    security.provider.2=com.sun.net.ssl.internal.ssl.Provider

    這樣,至少在你的程序中處理HTTPS連接的方式是沒有區別的。如果遠端的站點需要驗證,那么你必須做相應的配置。

    2.創建HttpClient類的一個實例,所有的函數都將用到它。這個類包含一個連接管理器操作實際的連接。HttpConnectionManager接口允許你創建自己的管理器,否則可以使用內建的SimpleHttpConnectionManager或MultiThreadedHttpConnectionManager。如果無參數創建HttpClient,那么默認連接管理器為SimpleHttpConnectionManager。

    HttpClient client = new HttpClient();

    3.創建一個method實例,用來定義使用那種HTTP方法與遠端站點傳遞信息,可以選擇的方法有GET, POST, PUT, DELETE, HEAD, OPTIONS和TRACE。這些method類是HttpMethod接口的不同實現。在這個例子中使用GetMethod,創建時將要GET的URL作為參數。

    HttpMethod method = new GetMethod(url);

    4.連接這個URL,也就是用剛才定義的方法連接URL。這個方法將返回server返回的狀態碼。注意executeMethod是client的函數而不是method的。

    statusCode = client.executeMethod(method);

    5.讀取服務器的返回。如果連接失敗,將拋出HttpException或IOException異常。IOException異常說明是網絡出了問題,重試也不會成功。返回值可以字節數組﹑輸入流或字符串的格式讀取。這樣,就可以隨意處理輸入了。

    byte[] responseBody = method.getResponseBody();

    6.最后,釋放連接,使之在需要時可重用。

    method.releaseConnection();

    這時一個關于HttpClient庫的很粗略的介紹,它還有很多功能,十分健壯。

    3.Net

    概要:基本Internet協議的底層API。

    在那得到:主頁,程序,源代碼。

    何時使用:當在Java應用程序中需要Internet協議的底層互連時。

    例子程序:NetDemo.java。需要將commons-net-1.0.0.jar加入CLASSPATH中。

    描述:Net包是很多健壯的和專業的類的集合。這些類來自于一個叫做NetComponents的商業產品的一部分。

    Net包中的類既提供對協議的底層訪問也有高層的抽象。在大多數情況下,抽象是足夠的,它可以使你不必編寫解析各種協議的底層套接字的代碼。使用抽象不會損失任何功能。

    SocketClient是所有協議的基類,它是一個抽象類包含所有協議的共同功能。各種協議的使用方法是很相近的:首先使用connect方法建立與遠端服務器的連接,執行服務,最后斷開連接。讓我們通過例子來看:

    1.創建一個client。我們將使用一個NNTPClient從新聞服務器上下載新聞組列表。

    client = new NNTPClient();

    2.連接服務器,我用的是新聞組列表較短的服務器。

    client.connect("aurelia.deine.net");

    3.提取新聞組列表。如下的命令返回NewsGroupInfo數組。如果服務器上沒有新聞組則數組為空,出錯則返回null。注意當新聞組列表很大時,這個命令會花很長時間。每個NewsGroupInfo對象包含關于新聞組的詳細信息,有公用函數可以解析它們(如文章數,最后發表的文章,發表權限等)。

    list = client.listNewsgroups();

    4.最后,斷開與服務器的連接。

    if (client.isConnected())

    client.disconnect();

    其余的client如FingerClient, POP3Client, TelnetClient等用法相似。

    結束語

    這篇文章介紹了Web相關和小程序類,下篇文章包括XML相關和打包類,工具類在最后一篇文章中。

    希望你能從這篇文章的例子得到收獲。最后,我希望這篇文章能夠激起你對Commons子項目的興趣。

    posted on 2006-05-02 15:36 chenhui 閱讀(502) 評論(0)  編輯  收藏 所屬分類: Jakarta Commons


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    介紹 IOC

    友情鏈接

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产传媒在线观看视频免费观看| AAA日本高清在线播放免费观看| 亚洲综合一区国产精品| 亚洲第一区视频在线观看| 日韩精品亚洲人成在线观看| 91精品国产亚洲爽啪在线影院 | 免费一级不卡毛片| 免费人成激情视频在线观看冫| 国色精品va在线观看免费视频| 国产日韩一区二区三免费高清| 成全视频高清免费观看电视剧| a毛片在线免费观看| 久久免费动漫品精老司机| 日韩插啊免费视频在线观看 | GOGOGO高清免费看韩国| 巨胸喷奶水www永久免费| a级毛片100部免费观看| 日韩精品内射视频免费观看 | 成人免费毛片内射美女-百度| 欧洲精品成人免费视频在线观看| 最近最新的免费中文字幕| 男女交性永久免费视频播放| 免费a级毛片大学生免费观看| 亚洲裸男gv网站| 亚洲Av无码专区国产乱码DVD| 亚洲综合成人网在线观看| 亚洲av成人一区二区三区| 久久亚洲色WWW成人欧美| 一进一出60分钟免费视频| 免费91麻豆精品国产自产在线观看 | 亚洲伊人久久精品影院| 日本久久久久亚洲中字幕| 亚洲人成色4444在线观看| 一级毛片在线播放免费| 久久精品无码精品免费专区| 999国内精品永久免费观看| 亚洲av无码不卡私人影院| 久久久综合亚洲色一区二区三区 | 亚洲欧洲久久av| 99亚洲精品高清一二区| 亚洲欧美日韩中文无线码 |