<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的一個子項目,目的是創(chuàng)建和維護獨立于其他框架和產(chǎn)品的程序包(packages)。這些程序包是一些服務(wù)于小范圍的有效組件的集合,通常適用于服務(wù)器端編程。

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

    簡要介紹

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

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

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

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


    組件

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

    組件類別
    組件

    Web相關(guān)
    FileUpload,HTTPClient和Net

    XML相關(guān)
    Betwixt,Digester,Jelly和JXPath

    工具
    BeanUtils,Logging,DBCP,Pool和 Validator

    打包
    Codec 和 Modeler

    小程序
    CLI,Discovery,Lang和 Collections


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

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

    1.CLI

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

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

    3.根據(jù)用戶輸入執(zhí)行相應(yīng)操作:

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

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

    2.Discovery

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

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

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

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

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

    1.取得ClassLoader:

    ClassLoaders loaders =

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

    2.創(chuàng)建DiscoverClass用于查找實現(xiàn)類:

    DiscoverClass discover = new DiscoverClass(loaders);

    3.查找實現(xiàn)類:

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

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

    運行以上代碼(DiscoveryDemo.java)將得到MyInterface文件中注冊的類,如下所示。再次提醒,如果實現(xiàn)包含在一個包結(jié)構(gòu)內(nèi),文件名必須做相應(yīng)的修改。如果這個文件不在規(guī)定目錄下,或?qū)崿F(xiàn)類不能實例化或定位,將拋出DiscoveryException異常,表明找不到MyInterface的實現(xiàn)。

    MyImpl2 # Implementation 2

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

    java -DMyInterface=MyImpl1 DiscoveryDemo

    Discovery也可用于創(chuàng)建(單例)服務(wù)提供者的實例并調(diào)用它們的函數(shù)。如下:

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

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

    3.Lang

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

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

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

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

    描述:這個包中提供的很多工具函數(shù)可以簡化Java程序員的工作。這些函數(shù)可以減少實現(xiàn)日常功能的編程量。特別是StringUtils類,它提供比標準的java.lang.String包更強的操作字符串的功能。它們的使用十分簡單,只要用正確的參數(shù)調(diào)用一個靜態(tài)函數(shù)。例如,要將一句話變?yōu)橐源髮戦_頭只要:

    StringUtils.capitalise("name");

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

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

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

    Builder包中的類提供為類添加toString,hashCode,compareTo和equals函數(shù)的功能。也就是說,自己不需編碼就可以在類中添加高質(zhì)量的toString,hashCode,compareTo和equals函數(shù),只要使用Builder包中的函數(shù)就可以了。例如,用ToStringBuilder函數(shù)給類添加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();
    }
    }
    為什么使用這個函數(shù)那?因為它使用通用的方法處理所有的數(shù)據(jù)類型,恰當?shù)姆祷豱ull,同時可以控制對象和聚集的細節(jié)層次。這對于所有builder中的函數(shù)有效,而且語法同上所示相近。

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

    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.現(xiàn)在就可以在你的方法中使用枚舉了:

    OnTV.getEnum("Idol");

    該行代碼從我們創(chuàng)建的枚舉數(shù)據(jù)類型中返回Idol項。Enum類還有其他有用的函數(shù)。

    4.Collections

    概要:對Java Collection框架的擴展,加入了新的數(shù)據(jù)結(jié)構(gòu),iterators和比較器。

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

    何時使用:強烈建議在需要處理數(shù)據(jù)結(jié)構(gòu)的Java項目盡可能使用Collections API,從中你會獲得比Java默認實現(xiàn)大的多的好處。

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

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

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

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

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

    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.調(diào)用remove方法。按自然排序,-10將被刪除,反之5被刪除:

    heap.remove();

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

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

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

    1.這次使用NullComparator創(chuàng)建BinaryHeap。NullComparator根據(jù)標志nullAreHigh的值決定null與其他對象的大小。如果取值為false,表示null比其他對象?。?br />
    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.最后,執(zhí)行刪除操作。因為null小于其他對象,Bag最后剩下的是null

    heap2.remove();

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



    Web相關(guān)類

    Web相關(guān)類中組件幫助Java程序員完成Web相關(guān)的任務(wù)。

    1.FileUpload

    概要:現(xiàn)成的文件上傳組件。

    在那得到:主頁。

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

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

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

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

    1.創(chuàng)建HTML頁。注意為了確保上傳文件的類型是被允許的,enctype參數(shù)必須為multipart/form-data,請求參數(shù)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.創(chuàng)建JSP頁。

    a.檢查輸入請求是不是多段數(shù)據(jù)。

    boolean isMultipart = FileUpload.isMultipartContent(request);

    b.創(chuàng)建請求處理器,解析請求,結(jié)果存于一個list中。

    DiskFileUpload upload = new DiskFileUpload();

    List items = upload.parseRequest(request);

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

    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限制上傳文件的最大尺寸,當上傳文件大小超過該尺寸將會拋出異常。上例中,若將該尺寸設(shè)為-1,就可以上傳任何大小的文件。

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

    2.HttpClient

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

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

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

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

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

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

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

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

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

    HttpClient client = new HttpClient();

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

    HttpMethod method = new GetMethod(url);

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

    statusCode = client.executeMethod(method);

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

    byte[] responseBody = method.getResponseBody();

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

    method.releaseConnection();

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

    3.Net

    概要:基本Internet協(xié)議的底層API。

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

    何時使用:當在Java應(yīng)用程序中需要Internet協(xié)議的底層互連時。

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

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

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

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

    1.創(chuàng)建一個client。我們將使用一個NNTPClient從新聞服務(wù)器上下載新聞組列表。

    client = new NNTPClient();

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

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

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

    list = client.listNewsgroups();

    4.最后,斷開與服務(wù)器的連接。

    if (client.isConnected())

    client.disconnect();

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

    結(jié)束語

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

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

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


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


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    介紹 IOC

    友情鏈接

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲不卡av不卡一区二区| 特级做A爰片毛片免费看无码| 亚洲人成色777777在线观看| 无码国产精品一区二区免费式影视 | 亚洲一级大黄大色毛片| 国产av天堂亚洲国产av天堂| 亚洲国产精品日韩专区AV| 在线成人a毛片免费播放| 小草在线看片免费人成视久网| 特级毛片在线大全免费播放| 亚洲欧洲无卡二区视頻| 亚洲免费福利视频| 亚洲男人的天堂在线播放| 亚洲综合色区在线观看| 又粗又大又猛又爽免费视频 | 亚洲老熟女@TubeumTV| 亚洲色欲色欲www在线丝| 亚洲高清成人一区二区三区| 国产成人青青热久免费精品 | 久久亚洲精品高潮综合色a片| 亚洲国产成人精品无码区在线秒播| 亚洲成在人线av| 亚洲男同帅GAY片在线观看| 亚洲A∨午夜成人片精品网站| 日韩免费福利视频| 麻豆成人精品国产免费| 久久久www成人免费毛片| 成人无码区免费A片视频WWW| 久久精品无码专区免费青青| 国产精品免费观看调教网| 另类免费视频一区二区在线观看 | 国产成人亚洲精品91专区手机| 午夜国产大片免费观看| 国产精品久久香蕉免费播放| 最近中文字幕mv手机免费高清| 一个人看www在线高清免费看 | 亚洲一区二区三区无码国产| 亚洲成人黄色在线观看| 亚洲av无码不卡久久| 亚洲入口无毒网址你懂的| 日韩亚洲国产综合高清|