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

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

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

    走在架構師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
     

    Restlet是一個Java下的輕量級REST框架。通過擁抱RESTREST是一種Web架構風格)它模糊了Web站點和Web服務之間的界限,從而幫助開發人員構建Web應用。每一個主要的REST概念(REST concept)都有一個對應的Java類。你的REST化的Web設計和你的代碼之間的映射是非常簡單直接的。

    為什么有必要創建另一種框架?難道Servlet API還不夠好用嗎?

    Servlet AIP1998年發布,從那個時候起它的核心設計一直沒有很大的變化。它是Java EE的眾多API中最成功的一個,但是它的幾個設計缺陷和一些限制損害了它。舉個例子,URI模式和它的處理者(handler)之間的映射是受限制的,而且其配置都集中在一個配置文件中。還有,它把socket流的控制直接交給了應用系統開發人員,Servlet容器阻礙了我們充分使用NIO特性對IO操作進行優化。另一個主要問題就是Servlet API鼓勵應用開發者在應用或者用戶會話級別直接將session狀態保存于內存中,盡管這看上去不錯,但它造成了Servlet容器擴展性和高可用性的主要問題。為了克服這些問題,就必須實現復雜的負載均衡session復制、持久化機制。這導致了可擴展性必然成為災難。

    如何看待別的框架中對REST的支持(例如Axis2,或者CXF/XFire)?

    這些支持非常有效,但是作用非常有限。我的主要觀點是設計這些項目是為了符合WS-*/SOAP Stack,它們與REST世界并不非常契合。在REST世界里,定義了一個全新的范例:面向資源的設計,而非通過遠程方法調用這樣的范例。例如Axis2僅僅支持GETPOST兩種HTTP方法,它需要遠程方法的傳遞需要一個URI參數。這在REST中式不允許的,這種做法也不能被稱之為REST化。XFire1.2不支持REST,但是它發布了一個項目用于將POJO映射到REST化的Web服務。這有點類似最近發布的JSR-311,此JSR試圖基于一套annotation和助手類標準化這種映射。

    REST與HTTP協議

    REST軟件架構是由Roy Thomas Fielding博士在2000年首次提出的。他為我們描繪了開發基于互聯網網絡軟件的藍圖。REST軟件架構是一個抽象的概念,是一種為了實現這一互聯網的超媒體分布式系統的行動指南。利用任何的技術都可以實現這種理念。而實現這一軟件架構最著名的就是HTTP協議。通常我們把REST也寫作為REST/HTTP,在實際中往往把REST理解為基于HTTP的REST軟件架構,或者更進一步把REST和HTTP看作為等同的概念。今天,HTTP是互聯網上應用最廣泛的計算機協議。HTTP不是一個簡單的運載數據的協議,而是一個具有豐富內涵的網絡軟件的協議。它不僅僅能夠對于互聯網資源進行唯一定位,而且還能告訴我們對于該資源進行怎樣運作。這也是REST軟件架構當中最重要的兩個理念。而REST軟件架構理念是真正理解HTTP協議而形成的。有了REST軟件架構理念出現,才使得軟件業避免了對HTTP協議的片面理解。只有正確的理論指導,才能避免在軟件開發的實際工作過程中少走彎路。

    REST與URI(資源定位)
    REST軟件架構之所以是一個超媒體系統,是因為它可以把網絡上所有資源進行唯一的定位,不管你的文件是圖片、文件Word還是
    視頻文件,也不管你的文件是txt文件格式、xml文件格式還是其它文本文件格式。它利用支持HTTP的TCP/IP協議來確定互聯網上的資源。

    REST與CRUD原則
    REST軟件架構遵循了CRUD原則,該原則告訴我們對于資源(包括網絡資源)只需要四種行為:創建(Create)、獲取(Read)、更新(Update)和銷毀(DELETE)就可以完成對其操作和處理了。其實世界萬物都是遵循這一規律:生、變、見、滅。所以計算機世界也不例外。這個原則是源自于我們對于數據庫表的數據操作:insert(生)、select(見)、update(變)和delete(滅),所以有時候CRUD也寫作為RUDI,其中的I就是insert。這四個操作是一種原子操作,即一種無法再分的操作,通過它們可以構造復雜的操作過程,正如數學上四則運算是數字的最基本的運算一樣。
     
    REST與網絡服務
    盡管在Java語言世界中網絡服務目前是以SOAP技術為主,但是REST將是是網絡服務的另一選擇,并且是真正意義上的網絡服務。基于REST思想的網絡服務不久的將來也會成為是網絡服務的主流技術。REST不僅僅把HTTP作為自己的數據運輸協議,而且也作為直接進行數據處理的工具。而當前的網絡服務技術都需要使用其它手段來完成數據處理工作,它們完全獨立于HTTP協議來進行的,這樣增加了大量的復雜軟件架構設計工作。REST的思想充分利用了現有的HTTP技術的網絡能力。在德國電視臺上曾經出現過一個這樣的五十萬歐元智力題:如何實現網絡服務才能充分利用現有的HTTP協議?該問題給出了四個答案:去問微軟;WSDL2.0/SOAP1.2;WS-Transfer;根本沒有。這個問題告訴我們HTTP并不是一個簡單的數據傳來傳去的協議,而是一個聰明的會表現自己的協議,這也許是REST = Representational State Transfer的真正含義。實際上目前很多大公司已經采用了REST技術作為網絡服務,如Google、Amazon等。在Java語言中重要的兩個以SOAP技術開始的網絡服務框架XFire和Axis也把REST作為自己的另一種選擇。它們的新的項目分別是
    Apache CXF
    Axis2。Java語言也制定關于REST網絡服務規范:JAX-RS: Java API for RESTful Web Services (JSR 311)。相信還會出現更多與REST相關的激動人心的信息。

    REST與AJAX技術
    盡管AJAX技術的出現才不到兩年時間,但是AJAX技術遵循了REST的一些重要原則。AJAX技術充分利用了HTTP來獲取網絡資源并且實現了HTTP沒有的對于異步數據進行傳輸的功能。AJAX技術還使得軟件更好地實現分布性功能,在一個企業內只要一個人下載了AJAX引擎,其它企業內部的人員,就可以共享該資源了。AJAX技術遵守REST準則的應用程序中簡單和可伸縮的架構,凡是采用AJAX技術的頁面簡潔而又豐富,一個頁面表現了豐富多彩的形態。AJAX技術還使用了一種不同于XML格式的JSON文件格式,這個意義在哪里呢?在REST軟件架構下我們不能對于XML文件進行序列化處理,這樣程序員必須要使用自己的XML綁定框架。而以序列化的JavaScript對象為基礎的JSON已經獲得了廣泛認可,它被認為能以遠比XML更好的方式來序列化和傳輸簡單數據結構,而且它更簡潔。這對REST是一個極大貢獻和補充。當前的網絡應用軟件還違背了REST的“無狀態
    服務器”約束。REST服務器只知道自己的狀態。REST不關心客戶端的狀態,客戶端的狀態自己來管理,這是AJAX技術的應用之地。通過AJAX技術,可以發揮有狀態網絡客戶機的優勢。而REST的服務器關心的是從所有網絡客戶端發送到服務器操作的順序。這樣使得互聯網這樣一個巨大的網絡得到有序的管理。

    REST與Rails框架
    Ruby on Rails框架(簡稱Rails或者Rails框架)是一個基于Ruby語言的越來越流行的網絡應用軟件開發框架。它提供了關于REST最好的支持,也是當今應用REST最成功的一個軟件開發框架。Rails框架(從版本1.2.x起)成為了第一個引入REST作為核心思想的主流網絡軟件開發框架。在Rails框架的充分利用了REST軟件架構之后,人們更加堅信REST的重要性和必要性。Rails利用REST軟件架構思想對網絡服務也提供了一流的支持。從最直觀的角度看待REST,它是網絡服務最理想的手段,但是Rails框架把REST帶到了網絡應用軟件開發框架。這是一次飛躍,讓REST的思想從網絡服務的應用提升到了網絡應用軟件開發。利用REST思想的simply_restful插件已經成為了Rails框架的核心內容。

    REST
    安全
    我們把現有基于SOAP的網絡服務和基于REST/HTTP網絡服務作個比喻,前者是一種傳統的寄信方式,而后者是現代網絡的電子郵件方式。要是是寄信和電子郵件都有病毒存在的話,傳統的寄信被送到對方就很危險,而電子郵件是開發的,電子郵件供應商比如Google為我們檢查了電子郵件是否有病毒。這里并不是說明SOAP網絡服務消息包含義病毒,而是說明HTTP是無法處理SOAP信息包究竟好不好,需要額外的軟件工具
    解決這一問題,包括防火墻也用不上和管不了。

    REST/HTTP網絡服務的信息包可以被防火墻理解和控制。你可以按照操作和鏈接進行過濾信息包,如你可以規定從外部來的只能讀取(GET操作)自己服務器的資源。這樣對于系統管理員而言使得軟件管理更為簡單。REST的安全性還可以利用傳輸安全協議SSL/TLS、基本和摘要式認證(Basic und Digest Authentication)。除了這些REST自身的安全性功能外,還可以利用像基于信息的Web Services Security(JSR 155)作為REST不錯的補充。

    Restlet第一步:

    這篇文章讓你在10分鐘內嘗試簡單的Restlet框架。告訴你如何創建一個說“hello, world”的Resource。
    1.我需要什么?
    2.“hello, world”應用
    3.在Servlet容器中運行
    4.作為一個單獨的Java應用運行
    5.結尾

    1.我需要什么?
    我們假設你已經有了一個可以馬上使用的開發環境,并且你已經安裝了JRE1.5(或更高)。如果你還沒有下載Restlet,請選擇最新的
    Restlet Framework 1.0發行版。

    2.“hello, world”
    程序
    讓我們從REST應用的核心---資源開始入手。下面的代碼是這個程序涉及的唯一資源。拷貝/粘貼代碼到“HelloWorldResource”類中。

    Java代碼

    01packagefirstSteps;
    02
    03importorg.restlet.Context;
    04importorg.restlet.data.MediaType;
    05importorg.restlet.data.Request;
    06importorg.restlet.data.Response;
    07importorg.restlet.resource.Representation;
    08importorg.restlet.resource.Resource;
    09importorg.restlet.resource.StringRepresentation;
    10importorg.restlet.resource.Variant;
    11
    12/**
    13* Resource which has only one representation.
    14*
    15*/
    16publicclassHelloWorldResourceextendsResource {
    17
    18publicHelloWorldResource(Context context, Request request,
    19 Response response) {
    20super(context, request, response);
    21
    22// This representation has only one type of representation.
    23 getVariants().add(newVariant(MediaType.TEXT_PLAIN));
    24 }
    25
    26/**
    27* Returns a full representation for a given variant.
    28*/
    29 @Override
    30publicRepresentation getRepresentation(Variant variant) {
    31 Representation representation =newStringRepresentation(
    32 "hello, world", MediaType.TEXT_PLAIN);
    33returnrepresentation;
    34 }
    35 }

    然后創建應用例子。我們創建名為“FirstStepsApplication”的類并拷貝/粘貼下面的代碼:

    01packagefirstSteps;
    02
    03importorg.restlet.Application;
    04importorg.restlet.Context;
    05importorg.restlet.Restlet;
    06importorg.restlet.Router;
    07
    08publicclassFirstStepsApplicationextendsApplication {
    09
    10publicFirstStepsApplication(Context parentContext) {
    11super(parentContext);
    12 }
    13
    14/**
    15* Creates a root Restlet that will receive all incoming calls.
    16*/
    17 @Override
    18publicsynchronizedRestlet createRoot() {
    19// Create a router Restlet that routes each call to a
    20// new instance of HelloWorldResource.
    21 Router router =newRouter(getContext());
    22
    23// Defines only one route
    24 router.attachDefault(HelloWorldResource.class);
    25
    26returnrouter;
    27 }
    28 }

    3.在Servlet容器中運行
    你可能更熟悉Servlets,我們建議你在你喜歡的Servlet容器里運行Restlet應用。像往常一樣創建一個新的Servlet應用,把下面列出的jar包放入lib目錄。
    org.restlet.jar
    com.noelios.restlet.jar
    com.noelios.restlet.ext.servlet_2.4.jar
    然后按下面的配置修改“web.xml”配置文件:

    01 <?xml version="1.0" encoding="UTF-8"?>
    02<web-appid="WebApp_ID" version="2.4"
    03 xmlns="
    http://java.sun.com/xml/ns/j2ee"
    04 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    05 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    06http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    07<display-name>first steps servlet</display-name>
    08<!-- Application class name -->
    09<context-param>
    10<param-name>org.restlet.application</param-name>
    11<param-value>
    12 firstSteps.FirstStepsApplication
    13</param-value>
    14</context-param>
    15
    16<!-- Restlet adapter -->
    17<servlet>
    18<servlet-name>RestletServlet</servlet-name>
    19<servlet-class>
    20 com.noelios.restlet.ext.servlet.ServerServlet
    21</servlet-class>
    22</servlet>
    23
    24<!-- Catch all requests -->
    25<servlet-mapping>
    26<servlet-name>RestletServlet</servlet-name>
    27<url-pattern>/*</url-pattern>
    28</servlet-mapping>
    29</web-app>

    最后,將程序打包成一個war文件,例如“firstStepsServlet.war”,并部署到你的Servlet容器里。啟動Servlet容器后,打開你喜歡的瀏覽器,輸入URL:“http://<你的服務器名>:<端口號>/firstStepsServlet”。服務器將很高興地用“hello, world”歡迎你。

    4.作為一個單獨的Java應用運行
    Restlet應用并不是只能運行在Servlet容器里,也可以使用下面幾個Jar包所為一個獨立應用運行:
    org.restlet.jar
    com.noelios.restlet.jar
    com.noelios.restlet.ext.simple.jar
    org.simpleframework.jar
    如果你想要理解后面兩個Jar包的意義,你可以參考連接器(
    http://www.restlet.org/documentation/1.0/connectors)。
    創建一個主類,拷貝/粘貼下面的代碼。建立一個新的HTTP服務器監聽端口8182并委托所有的請求給“FirstStepsApplication”。

    代碼:

    01packagefirstSteps;
    02importorg.restlet.Component;
    03importorg.restlet.data.Protocol;
    04
    05publicclassFirstStepsMain {
    06
    07publicstaticvoidmain(String[] args) {
    08try{
    09// Create a new Component.
    10 Component component =newComponent();
    11// Add a new HTTP server listening on port 8182.
    12 component.getServers().add(Protocol.HTTP, 8182);
    13
    14// Attach the sample application.
    15 component.getDefaultHost().attach(
    16newFirstStepsApplication(component.getContext()));
    17
    18// Start the component.
    19 component.start();
    20 }catch(Exception e) {
    21// Something is wrong.
    22 e.printStackTrace();
    23 }
    24 }
    25 }
    啟動Main對象,打開你喜歡的瀏覽器,輸入URL:“http://localhost:8182/,服務器將高興地用“hello, world”歡迎你。否則,確認Classpath正確且沒有其他應用占用8182端口。

    RestLet第二步:晉級篇

    這里說明Resource如何處理GET,POST,PUT和DELETE方法。
    1.引言
    2.示例程序
    3.實現Items Resource
    4.實現Item Resource
    5.實現Base Resource
    6.運行應用
    7.客戶端應用
    8.總結

    1.      引言
    在開始開發前,我們需要簡單介紹一下Restlet框架的Resource概念。REST告訴我們,Resource根據URI進行辨認,同時能夠有一種或多種表現(也被稱作變量),用以響應方法調用。
    在Restlet框架中,服務器連接器(server connectors)收到的調用最終由Resource的實例對象處理。一個Resource負責聲明支持的表現方式列表(Variant對象的實例)和實現你想要支持的REST方法。
     GET依賴可更改的“variants”列表和“getRepresentation(Variant)”方法。
     POST依賴“allowPost”方法和“post(Representation)”方法。
     DELETE依賴“allowPut”方法和“put(Representation)”方法。
    DELETE依賴“allowDelete”方法和“delete()”方法。
    還有,每一個到達的響應由一個專門的Resource實例處理,你不需要操心這些方法的線程安全問題。
    我們假設你已經讀過“第一步”,并且有了一些元件和應用的概念。

    2.示例程序

    一個Item列表用來管理創建,讀取,更新,和刪除活動,如一個典型的CRUD應用。一個Item包含名字和描述。在簡短的分析后,我們定義了兩個資源:
     Items Resource代表所有可用Item的集合。
     Item Resource代表一個單獨的item。
    現在,讓我們定義用來標志item的Resource URIs。假設我們的應用運行在本機“localhost”并且監聽8182端口:
    http://localhost:8182/firstResource/items
    :“items”Resource URI。
    http://localhost:8182/firstResource/items/{itemName}
    :“item”Resource URI,每個{itemName}代表一個Item的名字。
    下一步,定義每個Resource允許訪問的方法列表。
     “items”Resource響應GET請求并以一個XML文檔展示當前注冊的所有Item列表。另外,Resource支持通過POST請求創建新的Item。提交的實體包含新的Item的名字和描述,這些是以格式化的Web表單方式提交的。如果Resource成功創建新Item,它返回一個“Success - resource created”狀態(HTTP 201狀態代碼)并且告訴客戶端新Resource在哪里可以找到(HTTP "Location" header)。否則,它返回一個“Client error”狀態(HTTP 404狀態代碼)和一個簡單的錯誤信息。
     “item”Resource響應GET請求并以一個XML文檔來展示該Resource的名字和描述。也可以通過PUT和DELETE請求更新和刪除Resource。
    在描述兩個Resource對象前,首先編寫應用的代碼。為簡化起見,注冊的Item列表做為應用的一個屬性簡單地保存到內存里,并不保存到一個真實的數據庫。不管怎樣,我們假設你想邀請你的朋友們同時測試這個應用。因為我們只有一個“FirstResourceApplication”實例在運行,所以不得不考慮線程安全。這也就是為什么你會發現Map對象Items是不不可更改的,它是一個ConcurrentHashMap對象的實例。

    代碼:

    01packagefirstResource;
    02
    03importjava.util.Map;
    04importjava.util.concurrent.ConcurrentHashMap;
    05
    06importorg.restlet.Application;
    07importorg.restlet.Context;
    08importorg.restlet.Restlet;
    09importorg.restlet.Router;
    10
    11publicclassFirstResourceApplicationextendsApplication {
    12
    13   /** The list of items is persisted in memory. */
    14   privatefinalMap<String, Item> items;
    15
    16   publicFirstResourceApplication(Context parentContext) {
    17      super(parentContext);
    18      // We make sure that this attribute will support concurrent access.
    19       items =newConcurrentHashMap<String, Item>();
    20    }
    21
    22   /**
    23    * Creates a root Restlet that will receive all incoming calls.
    24    */
    25    @Override
    26   publicsynchronizedRestlet createRoot() {
    27      // Create a router Restlet that defines routes.
    28       Router router =newRouter(getContext());
    29
    30      // Defines a route for the resource "list of items"
    31       router.attach("/items", ItemsResource.class);
    32      // Defines a route for the resource "item"
    33       router.attach("/items/{itemName}", ItemResource.class);
    34
    35      returnrouter;
    36    }
    37
    38   /**
    39    * Returns the list of registered items.
    40    *
    41    * @return the list of registered items.
    42    */
    43   publicMap<String, Item> getItems() {
    44      returnitems;
    45    }
    46 }

    2.      實現Items Resource
      讓我們開始編寫Items Resource。如上文所述,它允許GET和POST請求。POST請求支持實現“post(Representation)”方法賦予處理消息實體的權限。此外,資源通過“allowPost”方法來確定是否開啟POST支持。缺省情況下,資源是不可更改的,拒絕POST、PUT和DELETE方法并返回“Method not allowed”狀態(HTTP 405狀態代碼)。

    同樣,通過實現“represent(Variant)”方法確定你可以接受GET請求并根據指定的Variant生成實體。在這個例子中,我們只生成“text/xml”這種形式。

    代碼:

    001packagefirstResource;
    002
    003importjava.io.IOException;
    004importjava.util.Collection;
    005
    006importorg.restlet.Context;
    007importorg.restlet.data.Form;
    008importorg.restlet.data.MediaType;
    009importorg.restlet.data.Request;
    010importorg.restlet.data.Response;
    011importorg.restlet.data.Status;
    012importorg.restlet.resource.DomRepresentation;
    013importorg.restlet.resource.Representation;
    014importorg.restlet.resource.StringRepresentation;
    015importorg.restlet.resource.Variant;
    016importorg.w3c.dom.Document;
    017importorg.w3c.dom.Element;
    018
    019/**
    020* Resource that manages a list of items.
    021*
    022*/
    023publicclassItemsResourceextendsBaseResource {
    024
    025   /** List of items. */
    026    Collection<Item> items;
    027
    028   publicItemsResource(Context context, Request request, Response response) {
    029      super(context, request, response);
    030
    031      // Get the items directly from the "persistence layer".
    032       items = getItems().values();
    033
    034      // Declare the kind of representations supported by this resource.
    035       getVariants().add(newVariant(MediaType.TEXT_XML));
    036    }
    037
    038    @Override
    039   publicbooleanallowPost() {
    040      returntrue;
    041    }
    042
    043   /**
    044    * Returns a listing of all registered items.
    045    */
    046    @Override
    047   publicRepresentation getRepresentation(Variant variant) {
    048      // Generate the right representation according to its media type.
    049      if(MediaType.TEXT_XML.equals(variant.getMediaType())) {
    050         try{
    051             DomRepresentation representation =newDomRepresentation(
    052                   MediaType.TEXT_XML);
    053            // Generate a DOM document representing the list of
    054            // items.
    055             Document d = representation.getDocument();
    056             Element r = d.createElement("items");
    057             d.appendChild(r);
    058            for(Item item : items) {
    059                Element eltItem = d.createElement("item");
    060
    061                Element eltName = d.createElement("name");
    062                eltName.appendChild(d.createTextNode(item.getName()));
    063                eltItem.appendChild(eltName);
    064
    065                Element eltDescription = d.createElement("description");
    066                eltDescription.appendChild(d.createTextNode(item
    067                      .getDescription()));
    068                eltItem.appendChild(eltDescription);
    069
    070                r.appendChild(eltItem);
    071             }
    072             d.normalizeDocument();
    073
    074            // Returns the XML representation of this document.
    075            returnrepresentation;
    076          }catch(IOException e) {
    077             e.printStackTrace();
    078          }
    079       }
    080
    081      returnnull;
    082    }
    083
    084   /**
    085    * Handle POST requests: create a new item.
    086    */
    087    @Override
    088   publicvoidpost(Representation entity) {
    089      // Parse the given representation and retrieve pairs of
    090      // "name=value" tokens.
    091       Form. form. =newForm(entity);
    092       String itemName = form.getFirstValue("name");
    093       String itemDescription = form.getFirstValue("description");
    094
    095      // Check that the item is not already registered.
    096      if(getItems().containsKey(itemName)) {
    097          generateErrorRepresentation(
    098                "Item " + itemName + " already exists.", "1", getResponse());
    099       }else{
    100         // Register the new item
    101          getItems().put(itemName,newItem(itemName, itemDescription));
    102
    103         // Set the response's status and entity
    104          getResponse().setStatus(Status.SUCCESS_CREATED);
    105          Representation rep =newStringRepresentation("Item created",
    106                MediaType.TEXT_PLAIN);
    107         // Indicates where is located the new resource.
    108          rep.setIdentifier(getRequest().getResourceRef().getIdentifier()
    109                + "/" + itemName);
    110          getResponse().setEntity(rep);
    111       }
    112    }
    113
    114   /**
    115    * Generate an XML representation of an error response.
    116    *
    117    * @param errorMessage
    118    *            the error message.
    119    * @param errorCode
    120    *            the error code.
    121    */
    122   privatevoidgenerateErrorRepresentation(String errorMessage,
    123          String errorCode, Response response) {
    124      // This is an error


    轉載地址:http://blog.ixpub.net/html/07/12399407-251280.html



    本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
    posted on 2008-10-07 10:41 Jack.Wang 閱讀(6503) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 国内精品久久久久影院亚洲| 亚洲精品在线播放| 免费国产高清毛不卡片基地 | 久久久久久AV无码免费网站| 久久精品国产亚洲一区二区三区| 日韩欧美亚洲国产精品字幕久久久| 性感美女视频在线观看免费精品 | 日韩免费一级毛片| 色婷婷亚洲一区二区三区| 亚洲精品免费观看| 久久免费的精品国产V∧| 亚洲国语精品自产拍在线观看| 久久aⅴ免费观看| 亚洲精品自在线拍| 成年人在线免费看视频| 亚洲人成电影网站色www| 国产一区二区视频免费| 国产精品免费视频观看拍拍| 亚洲Av无码专区国产乱码DVD| 亚洲欧洲免费视频| 在线亚洲午夜片AV大片| 免费女人18毛片a级毛片视频| 在线免费观看h片| 亚洲日本乱码一区二区在线二产线| 久久精品a一国产成人免费网站| 亚洲AV日韩AV无码污污网站 | 四虎成人精品在永久免费| 国产免费牲交视频免费播放| 亚洲伊人tv综合网色| 人妻视频一区二区三区免费| 国产亚洲综合视频| 亚洲成年轻人电影网站www| 无码少妇一区二区浪潮免费| 色爽黄1000部免费软件下载| 久久亚洲精品无码| 免费看的成人yellow视频| 91福利免费网站在线观看| 亚洲日本在线免费观看| 亚洲国产综合无码一区二区二三区 | 无码人妻精品中文字幕免费| 亚洲综合无码一区二区痴汉|