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

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

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

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks
    http://www-900.ibm.com/developerworks/cn/java/j-pg03155/index.shtml
    用 Groovlet 和 GSP 進(jìn)行動(dòng)態(tài)服務(wù)器端編程

    級(jí)別: 中級(jí)

    Andrew Gloveraglover@vanwardtechnologies.com
    首席技術(shù)官, Vanward Technologies
    2005 年 3 月

    Groovlet 和 GroovyServer Pages(GSP)框架都是建立在 Java Servlet API 基礎(chǔ)之上。不過,與 Strut 和 JSF 不同,Groovy 的服務(wù)器端實(shí)現(xiàn)不意味著適用于所有情況。相反,它提供了一種快速而又方便地開發(fā)服務(wù)器端應(yīng)用程序的簡(jiǎn)化方法。下面請(qǐng)跟隨 Groovy 的鼓吹者 Andrew Glover,聽聽他如何介紹這些框架,并展示它們的應(yīng)用。

    Java 平臺(tái)為自己贏得了服務(wù)器端應(yīng)用程序開發(fā)的首選平臺(tái)的名聲。Servlet 是服務(wù)器端 Java 技術(shù)的強(qiáng)大支柱,因此有無數(shù)的框架是圍繞著 Servlet API 建立起來的,其中包括 Strut、JavaServer Faces (JSF) 和 Tapestry。您可能已經(jīng)猜到,Groovy 也是以 Servlet API 為基礎(chǔ)建立起來的框架,不過,這個(gè)框架的目的是簡(jiǎn)化開發(fā)。

    Groovlet 和 GroovyServer Pages(GSP)框架的目的是提供一種優(yōu)雅而又簡(jiǎn)單的平臺(tái),將它用于構(gòu)建復(fù)雜程度不高的 Web 應(yīng)用程序。就像 GroovySql 不是數(shù)據(jù)庫(kù)開發(fā)的惟一選擇一樣,Groovlet 框架也不是 像 Strut 那樣具有更豐富功能的框架的替代品。Groovlet 只是開發(fā)人員尋求容易配置和產(chǎn)生工作代碼的快速方法時(shí)的一種選擇。

    例如,不久前,我需要 —— 快速地 —— 提供一個(gè) stub 應(yīng)用程序,以測(cè)試像 xml-rpc API 這樣的客戶端。顯然可以用一個(gè) servlet 快速編寫出所需要的功能,但是我從沒想過鉆研 Strut,一秒鐘也沒有。我考慮過使用基本的普通 Java Servlet API 編寫 servlet 及其相關(guān)的邏輯,但是由于需要盡快地使用這項(xiàng)功能,所以我選擇了使用 Groovlet 快速完成它。

    很快您就可看到,這種選擇是顯而易見的。

    在深入研究使用 Groovlet 進(jìn)行編程之前,我想簡(jiǎn)單介紹一個(gè)在示例代碼中會(huì)用到的 Groovy 特性。在幾個(gè)月前的 alt.lang.jre: 感受 Groovy 一文中,我第一次介紹了 def 關(guān)鍵字。

    關(guān)于本系列
    將任何工具添加到開發(fā)實(shí)踐中的關(guān)鍵是了解什么時(shí)候使用它和什么時(shí)候不使用它。腳本語言可以為您增加特別強(qiáng)大的工具,但前提是在相關(guān)的場(chǎng)景中正確地使用它。因此,實(shí)戰(zhàn) Groovy 的系列文章專門探討 Groovy 的實(shí)際使用,并指導(dǎo)讀者什么時(shí)候以及如何成功地使用這些工具。

    在腳本中定義函數(shù)
    在普通 Java 編程中,方法必須存在于類對(duì)象中。事實(shí)上,所有行為都必須在類的上下文中定義。不過在 Groovy 中,行為可以在函數(shù) 中定義,而函數(shù)可以在類定義之外定義。

    這些函數(shù)可以直接用名稱引用,并且可以在 Groovy 腳本中定義,這樣非常有助于它們的重復(fù)使用。Groovy 函數(shù)需要 def 關(guān)鍵字,可以將關(guān)鍵字想像為在腳本范圍內(nèi)可用的全局靜態(tài)方法。因?yàn)?Groovy 是動(dòng)態(tài)類型的語言,所以 def 不需要對(duì)參數(shù)作任何類型聲明,def 也不需要 return 語句。

    例如,在清單 1 中,我定義了一個(gè)簡(jiǎn)單的函數(shù),它將輸出一個(gè)集合的內(nèi)容,而不管這個(gè)集合是 list 還是 map。然后我定義一個(gè) list,填充它,并調(diào)用我新定義的 def。之后,我創(chuàng)建一個(gè) map,并對(duì)這個(gè)集合做了同樣的操作。

    清單 1. 這就是 def!
    
    def logCollection(coll){
      counter = 0;
      coll.each{ x | 
        println "${++counter} item: ${x}"
      }
    }
    lst = [12, 3, "Andy", 'c']
    logCollection(lst)
    mp = ["name" : "Groovy", "date" : new Date()]
    logCollection(mp)
    

    def 不需要 return 語句,因此如果最后一行產(chǎn)生某個(gè)值,那么這個(gè)值由 def 返回。例如,在清單 2 中,代碼定義了一個(gè) def,它返回傳遞進(jìn)來的變量的名稱。我可以編寫它,讓它帶有或者不帶 return 語句,得到的結(jié)果是相同的。

    清單 2. 在 def 中 return 語句是可選的
    
    def getJavaType(val){
      val.class.getName()
    }
    tst = "Test"
    println getJavaType(tst)
    

    在編寫簡(jiǎn)單的腳本時(shí),def 關(guān)鍵字會(huì)非常好用。您很快就會(huì)看到,在開發(fā) Groovlet 時(shí),這個(gè)關(guān)鍵字也會(huì)派上用場(chǎng)。

    Groovlet 和 GSP
    使用 Groovlet 和 GSP 的前提條件相當(dāng)簡(jiǎn)單:需要一個(gè) servlet 容器,以及最新、最偉大版本的 Groovy。這些框架的好處是它們通過一個(gè) web.xml 文件將所選模式的所有 URL 映射到特定的 servlet。因此,建立 Groovlet 和 GSP 的實(shí)現(xiàn)的第一步是定義一個(gè) Web 應(yīng)用程序上下文,并更新它的相關(guān) web.xml 文件。這個(gè)文件將包括特定的 servlet 類定義以及它們對(duì)應(yīng)的 URL 模式。

    我將使用 Apache Jakarta Tomcat,并且已創(chuàng)建了一個(gè)名為 groove 的上下文。目錄結(jié)構(gòu)如清單 3 所示:

    清單 3. groove 上下文的目錄列表
    
    ./groove:
    drwxrwxrwx+   3 aglover  users        0 Jan 19 12:14 WEB-INF
    ./WEB-INF:
    -rwxrwxrwx+   1 aglover  users      906 Jan 16 14:37 web.xml
    drwxrwxrwx+   2 aglover  users        0 Jan 19 17:12 lib
    ./WEB-INF/lib:
    -rwxrwxrwx+   1 aglover  users   832173 Jan 16 14:28 groovy-1.0-beta-9.jar
    -rwxrwxrwx+   1 aglover  users    26337 Jan 16 14:29 asm-1.5.2.jar
    

    在 WEB-INF 目錄中要有一個(gè) web.xml 文件,它至少有一個(gè)清單 4 中的元素:

    清單 4. 一個(gè)完全配置的 web.xml 文件
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation=
        "http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
        version="2.4">
        <servlet>
          <servlet-name>GroovyServlet</servlet-name>
          <servlet-class>groovy.servlet.GroovyServlet</servlet-class>
        </servlet>
        <servlet>
            <servlet-name>GroovyTemplate</servlet-name>
            <servlet-class>groovy.servlet.TemplateServlet</servlet-class>    
    	</servlet>
        <servlet-mapping>
            <servlet-name>GroovyServlet</servlet-name>
            <url-pattern>*.groovy</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>GroovyTemplate</servlet-name>
            <url-pattern>*.gsp</url-pattern>
        </servlet-mapping>
    </web-app>
    

    上述 web.xml 文件中的定義聲明了以下內(nèi)容:所有以 .groovy 結(jié)尾的請(qǐng)求(如 http://localhost:8080/groove/hello.groovy)都將發(fā)送給類 groovy.servlet.GroovyServlet,而所有以 .gsp 結(jié)尾的請(qǐng)求都將送給類 groovy.servlet.TemplateServlet

    下一步是將兩個(gè) jar 放到 lib 目錄中:groovy 發(fā)行版本的 jar(在這里是 groovy-1.0-beta-9.jar)和對(duì)應(yīng)的 asm jar (對(duì)于 groovy beta-9 來說是 asm-1.5.2.jar)。

    瞧,就是這么簡(jiǎn)單 —— 我已經(jīng)準(zhǔn)備好了。

    Groovlet,請(qǐng)出場(chǎng)
    編寫 Groovlet 無疑很簡(jiǎn)單,因?yàn)?Groovy 只有很少的幾個(gè)對(duì)類繼承擴(kuò)展的要求。使用 Groovlet 不需要擴(kuò)展 javax.servlet.http.HttpServletjavax.servlet.GenericServlet 或者一些華而不實(shí)的 GroovyServlet 類。事實(shí)上,創(chuàng)建 Groovlet 就像創(chuàng)建一個(gè) Groovy 腳本一樣簡(jiǎn)單。甚至不必創(chuàng)建一個(gè)類。在清單 5 中,我編寫了一個(gè)簡(jiǎn)單的 Groovlet,它做兩件事:打印一些 HTML,然后提供一些關(guān)于它所在的容器的信息。

    清單 5. 開始使用 Groovlet
    
    println """
    <html><head>
    <title>Groovlets 101</title>
    </head>
    <body>
    <p>
    Welcome to Groovlets 101. As you can see
    this Groovlet is fairly simple.
    </p>
    <p>
    This course is being run on the following servlet container: </br>
    ${application.getServerInfo()}
    </p>
    </body>
    </html>
    """
    

    如果在瀏覽器中觀看這個(gè) Groovy,它看起來與圖 1 所示類似。

    圖 1. 簡(jiǎn)單 Groovlet 的輸出

    仔細(xì)觀察清單 5 中的 Groovlet,會(huì)讓您回想起第一次編寫 Groovy 腳本的時(shí)候。首先,沒有 main 方法或者類定義,只有一些簡(jiǎn)單的代碼。而且,Groovlet 框架隱式地提供實(shí)例變量,比如 ServletRequestServletResponseServletContextHttpSession。注意我是如何通過 application 變量引用 ServletContext 的實(shí)例的。如果想獲得 HttpSession 的實(shí)例,那么就要使用 session 變量名。與此類似,可以對(duì) ServletRequestServletResponse 分別使用 requestresponse

    一個(gè)診斷 Groovlet
    編寫 Groovlet 不僅像創(chuàng)建一個(gè) Groovy 腳本那樣簡(jiǎn)單,而且還可以用 def 關(guān)鍵字定義函數(shù),并在 Groovlet 中直接調(diào)用它們。為了展示這一點(diǎn),我將創(chuàng)建一個(gè)非凡的 Groovlet,它將對(duì) Web 應(yīng)用程序進(jìn)行一些診斷。

    假設(shè)您編寫了一個(gè) Web 應(yīng)用程序,它被世界上不同的客戶所購(gòu)買。您有一個(gè)大客戶群,并且不斷發(fā)布這個(gè)應(yīng)用程序有一段時(shí)間了。從過去的支持問題中,您注意到許多急切的客戶電話都與錯(cuò)誤的 JVM 版本和錯(cuò)誤的對(duì)象關(guān)系映射(ORM)所導(dǎo)致的問題有關(guān)。

    您很忙,所以讓我拿出一個(gè)解決方案。我用 Groovlet 迅速地 創(chuàng)建了一個(gè)簡(jiǎn)單的診斷腳本,它將驗(yàn)證 VM 版本,并試圖創(chuàng)建一個(gè) Hibernate 會(huì)話(請(qǐng)參閱參考資料)。我首先創(chuàng)建兩個(gè)函數(shù),并在瀏覽器連接腳本時(shí)調(diào)用它們。清單 6 定義了這個(gè)診斷 Groovlet:

    清單 6. 一個(gè)診斷 Groovlet
    
    import com.vanward.resource.hibernate.factory.DefaultHibernateSessionFactory
    /**
     * Tests VM version from environment- note, even 1.5 will
     * cause an assertion error.
     */
    def testVMVersion(){
      println "<h3>JVM Version Check: </h3>"
      vers = System.getProperty("java.version")
      assert vers.startsWith("1.4"): "JVM must be at least 1.4"
      println "<p>JVM version: ${vers} </p>"
    }
    /**
     * Attempts to create an instance of a hibernate session. If this
     * works we have a connection to a database; additionally, we 
     * have a properly configured hibernate instance.
     */
    def testHibernate(){
      println "<h3>Hibernate Configuration Check: </h3>"
      try{
        sessFactory = DefaultHibernateSessionFactory.getInstance()
        session = sessFactory.getHibernateSession()
        assert session != null: "Unable to create hibernate session. 
        Session was null"
        println "<p>Hibernate configuration check was successful</p>"
      }catch(Throwable tr){
        println """
        <p>Unable to create hibernate session. Exception type is: <br/>
        <i>${tr.toString()} </i><br/>		
        </p>
        """
      }   
    }
    println """
    <html><head>
    <title>Diagnostics Check</title></head>
    <body>
    """
    testVMVersion()
    testHibernate()
    println """
    </body></html>
    """
    

    這個(gè) Groovlet 的驗(yàn)證邏輯非常簡(jiǎn)單,但是它可以完成這項(xiàng)工作。只要將診斷腳本綁定到 web 應(yīng)用程序即可,當(dāng)客戶服務(wù)臺(tái)收到電話時(shí),它們將指點(diǎn)客戶用瀏覽器訪問 Diagnostics.groovy 腳本,并讓這些腳本報(bào)告它們的發(fā)現(xiàn)。結(jié)果可能看起來像圖 2 這樣。

    圖 2. 診斷 Groovlet 的輸出

    那些 GSP 呢?
    到目前為止,我主要關(guān)注于編寫 Groovlet。不過,正如您將會(huì)看到的那樣,很容易用 Groovy 的 GSP 頁(yè)對(duì) Groovlets 框架進(jìn)行補(bǔ)充,就像 JSP 補(bǔ)充 Servlet API 一樣。

    表面上,GSP 看起來很像 JSP,實(shí)際上它們不可能有太大的差別,因?yàn)?GSP 框架其實(shí)就是一個(gè)模板引擎。如果不熟悉模板引擎,那么可能需要快速地回顧一下上月的文章

    雖然 GSP 和 JSP 是根本不同的技術(shù),但是 GSP 是加入表達(dá) Web 應(yīng)用程序的視圖的很好候選人,這一點(diǎn)它們是類似的。您可能會(huì)想起來,在上月的文章中,有一項(xiàng)促進(jìn)視圖的技術(shù)可以將應(yīng)用程序的業(yè)務(wù)邏輯問題與其相應(yīng)的視圖分離。如果快速查看一下清單 6 中的診斷 Groovlet,就可以看出 GSP 代碼改進(jìn)了哪些地方。

    是的,Groovlet 有些簡(jiǎn)陋,不是嗎?問題在于它混合了應(yīng)用程序邏輯和大量輸出 HTML 的 println。幸運(yùn)的是,可以通過創(chuàng)建一個(gè)簡(jiǎn)單的 GSP 來補(bǔ)充這個(gè) Groovlet,從而解決這個(gè)問題。

    示例 GSP
    創(chuàng)建 GSP 與創(chuàng)建 Groovlet 一樣容易。GSP 開發(fā)的關(guān)鍵是認(rèn)識(shí)到 GSP 實(shí)質(zhì)上是一個(gè)模板,因此,它最適合有限的邏輯。我將在清單 7 中創(chuàng)建一個(gè)簡(jiǎn)單的 GSP 作為開始:

    清單 7. 一個(gè)簡(jiǎn)單的 GSP
    
    <html>
    <head><title>index.gsp</title></head>
    <body>
    <b><% println "hello gsp" %></b>
    <p>
    <% wrd = "Groovy"
       for (i in wrd){ 
     %>
     <h1> <%=i%> <br/>
       
     <%} %>
    </p>
    </body>
    </html>
    

    觀察上面的 GSP 可能很容易讓您回想起標(biāo)準(zhǔn) Groovy 模板開發(fā)。像 JSP 一樣,它使用 <%, 但是,與 Groovlet 框架類似,它允許您訪問常用 servlet 對(duì)象,比如 ServletRequestServletResponseServletContextHttpSession 對(duì)象。

    重構(gòu)應(yīng)用程序 ...
    在練習(xí)編程語言或者平臺(tái)發(fā)展的時(shí)候,重構(gòu)老的代碼可以學(xué)到很多東西。我將重構(gòu)一月份專欄中的簡(jiǎn)單報(bào)告應(yīng)用程序,那時(shí)候您才剛開始學(xué)習(xí) GroovySql。

    您還記得嗎,我構(gòu)建了一個(gè)快速但不完善的報(bào)告應(yīng)用程序,它可以在組織中有多次使用。但結(jié)果是,它變成了研究公司數(shù)據(jù)庫(kù)活動(dòng)的相當(dāng)流行的應(yīng)用程序。現(xiàn)在,非技術(shù)人員希望可以訪問這個(gè)巨大的報(bào)告,但是他們不想很費(fèi)事地在自已的計(jì)算機(jī)上安裝 Groovy 來運(yùn)行它。

    我多少預(yù)計(jì)到了這種情況的發(fā)生,解決方案實(shí)際上 是顯而易見的:讓報(bào)告應(yīng)用程序支持 Web。很幸運(yùn),Groovlet 和 GSP 使重構(gòu)變成小事一樁。

    重構(gòu)報(bào)告應(yīng)用程序
    首先,我將處理 > GroovySql 一文的清單 12 中的簡(jiǎn)單應(yīng)用程序。重構(gòu)這個(gè)應(yīng)用程序很容易:只要將所有 println 替換成用 setAttribute() 方法,然后將實(shí)例變量放入 HttpRequest 對(duì)象的邏輯中即可。

    下一步是用 RequestDispatcherrequest 轉(zhuǎn)發(fā)給 GSP,它會(huì)處理報(bào)告應(yīng)用程序的視圖部分。清單 8 定義了新的報(bào)告 Groovlet:

    清單 8. 重構(gòu)后的數(shù)據(jù)庫(kù)報(bào)告應(yīng)用程序
    
    import groovy.sql.Sql
    /**
     * forwards to passed in page
     */
    def forward(page, req, res){
      dis = req.getRequestDispatcher(page);
      dis.forward(req, res);
    }
    sql = Sql.newInstance("jdbc:mysql://yourserver.anywhere/tiger", "scott",
            "tiger", "org.gjt.mm.mysql.Driver")
       
    uptime = null
    questions = null
    insertnum = null
    selectnum = null
    updatenum = null
    sql.eachRow("show status"){ status |
      if(status.variable_name == "Uptime"){
             uptime =  status[1]
    	 request.setAttribute("uptime", uptime)
      }else if (status.variable_name == "Questions"){
             questions =  status[1]
    	 request.setAttribute("questions", questions)
      }
    }
    request.setAttribute("qpm", Integer.valueOf(questions) / 
    Integer.valueOf(uptime) )
    sql.eachRow("show status like 'Com_%'"){ status |
        if(status.variable_name == "Com_insert"){
             insertnum =  Integer.valueOf(status[1])
        }else if (status.variable_name == "Com_select"){
             selectnum =  Integer.valueOf(status[1])
        }else if (status.variable_name == "Com_update"){
              updatenum =  Integer.valueOf(status[1])
        }
    }
    request.setAttribute("qinsert", 100 * (insertnum / Integer.valueOf(uptime)))
    request.setAttribute("qselect", 100 * (selectnum / Integer.valueOf(uptime)))
    request.setAttribute("qupdate", 100 * (updatenum / Integer.valueOf(uptime)))
    forward("mysqlreport.gsp", request, response)
    

    清單 8 中的代碼應(yīng)當(dāng)是您相當(dāng)熟悉的。我只是將以前應(yīng)用程序中的所有 println 替換掉,并添加了 forward 函數(shù)來處理報(bào)告的視圖部分。

    添加視圖部分
    下一步是創(chuàng)建 GSP 來處理報(bào)告應(yīng)用程序的視圖。因?yàn)槲沂枪こ處煻皇且粋€(gè)藝術(shù)家,所以我的視圖是相當(dāng)簡(jiǎn)單的 —— 一些 HTML 加上一個(gè)表,如清單 9 所示:

    清單 9. 報(bào)告的視圖部分
    
    <html><head>
    <title>MySql Health Report</title>
    </head>
    <body>
    <table>
    <tr>
      <td>Database Uptime:</td><td><% println
      "${request.getAttribute("uptime")}" %></td>
    </tr>
    <tr>
      <td>Number of Queries:</td><td><% println
      "${request.getAttribute("questions")}" %></td>
    </tr>
    <tr>
      <td>Queries per Minute =</td><td><% println
      "${request.getAttribute("qpm")}" %></td>
    </tr>
    <tr>
      <td>% Queries Inserts =</td><td><% println
      "${request.getAttribute("qinsert")}" %></td>
    </tr>
    <tr>
      <td>% Queries Selects =</td><td><% println
      "${request.getAttribute("qselect")}" %></td>
    </tr>
    <tr>
      <td>% Queries Updates =</td><td><% println
      "${request.getAttribute("qupdate")}" %></td>
    </tr>
    </table>
    </body>
    </html>
    

    運(yùn)行新的報(bào)告應(yīng)當(dāng)生成如圖 3 所示的輸出,數(shù)字會(huì)有變化。

    圖 3. 重構(gòu)后的報(bào)告應(yīng)用程序的輸出

    結(jié)束語
    如您所見,當(dāng)所需要的功能相當(dāng)簡(jiǎn)單并且需要盡快完成時(shí),Groovlet 和 GSP 是進(jìn)行服務(wù)器端開發(fā)的當(dāng)然之選。這兩個(gè)框架都特別靈活,并且其代碼到視圖的轉(zhuǎn)化時(shí)間事實(shí)上是無可匹敵的。

    不過,需要強(qiáng)調(diào)的是,Groovlet 不是 Strut 的替代品。GSP 框架不是直接 在速度上與其他產(chǎn)品競(jìng)爭(zhēng)。GroovySql 不是 Hibernate 的替代品。而 Groovy 也不是 Java 語言的替代品。

    無論如何,這些技術(shù)是補(bǔ)充,在大多數(shù)情況下,Groovy 是快速開發(fā)的更簡(jiǎn)單的一種選擇。就像 GroovySql 是直接使用 JDBC 的替代方法一樣,Groovlet 和 GSP 實(shí)際上是直接使用 Servlet API 的替代品。

    下個(gè)月,我將探討 GroovyMarkup 的奇妙世界。

    參考資料

    關(guān)于作者
    Andrew Glover 是 Vanward Technologies 的首席技術(shù)官,該公司位于華盛頓特區(qū)的大都會(huì)地區(qū) ,公司的專業(yè)領(lǐng)域是專門從事自動(dòng)測(cè)試工具和框架的構(gòu)造 ,自動(dòng)測(cè)試框架可以幫助降低軟件 bug 數(shù)量,縮短集成和測(cè)試的時(shí)間,并改進(jìn)代碼的整體穩(wěn)定性。Andrew Glover 還是 Java Testing Patterns(Wiley,2004 年 9 月)一書的合著者之一。
    posted on 2005-04-08 16:09 笨笨 閱讀(917) 評(píng)論(0)  編輯  收藏 所屬分類: J2EEALL
    主站蜘蛛池模板: 亚洲精品无码你懂的| 最近中文字幕无吗免费高清| 亚洲情A成黄在线观看动漫软件 | 亚洲成av人在线视| 日韩免费无码一区二区视频| 最近中文字幕高清免费中文字幕mv| 一区二区三区AV高清免费波多| 456亚洲人成影院在线观| 亚洲va在线va天堂va不卡下载| 亚洲av区一区二区三| 免费无码又爽又刺激高潮| 最近免费最新高清中文字幕韩国| 国产精品hd免费观看| 免费手机在线看片| 理论亚洲区美一区二区三区| 亚洲 暴爽 AV人人爽日日碰| 亚洲国产精品人久久电影| 亚洲AV日韩精品久久久久久久| 亚洲日本乱码在线观看| 伊人久久亚洲综合| 亚洲国产精品无码久久九九| 国产成人免费a在线资源| 免费观看的a级毛片的网站| 国产在线国偷精品产拍免费| 免费视频爱爱太爽了| 91在线老王精品免费播放| 特级精品毛片免费观看| 久久成人a毛片免费观看网站| 中文字幕在线免费看| 国产免费一区二区三区免费视频| 日本激情猛烈在线看免费观看| 立即播放免费毛片一级| 337p日本欧洲亚洲大胆人人 | 曰批全过程免费视频播放网站| 无码AV片在线观看免费| 久久国产乱子免费精品| 日韩精品无码专区免费播放| 69视频免费观看l| 青青在线久青草免费观看| 免费电视剧在线观看| 在线a人片天堂免费观看高清|