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

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

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

    Shao Fan

    關(guān)于JAVA與軟件工程
    posts - 31, comments - 71, trackbacks - 0, articles - 4
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    2006年9月8日

    目前開發(fā)人員對(duì)系統(tǒng)開發(fā)的一個(gè)共識(shí)是使用三層架構(gòu),分為表示層,業(yè)務(wù)層,和持久層。而這三層之間的依賴關(guān)系如何?比較常見的一種看法是

    表示層 --> 業(yè)務(wù)層 --> 持久層

    這表明了層與層之間的調(diào)用關(guān)系,表示層通過調(diào)用業(yè)務(wù)層來完成任務(wù),而業(yè)務(wù)層則調(diào)用持久層。從另一個(gè)角度來看,一種依賴關(guān)系是

    表示層 --> 領(lǐng)域模型(Domain Model) <-- 持久層

    表示層和持久層都應(yīng)該理解(recognize)領(lǐng)域模型。而領(lǐng)域模型則是業(yè)務(wù)層的一部分。業(yè)務(wù)層正是系統(tǒng)的價(jià)值所在。雖說表示和持久也很重要,在某些系統(tǒng)中可以說是很關(guān)鍵,但是它們的最終目的都是為業(yè)務(wù)服務(wù),所以業(yè)務(wù)層應(yīng)該是系統(tǒng)的核心

    基于以上的認(rèn)識(shí),在系統(tǒng)設(shè)計(jì)的時(shí)應(yīng)首先分析需求得到領(lǐng)域模型,找出系統(tǒng)中的實(shí)體、對(duì)象(靜態(tài)的一面),并明確大致的業(yè)務(wù)流程(動(dòng)態(tài)的一面)。 而另兩層應(yīng)盡最大努力為業(yè)務(wù)層服務(wù),且盡量減少業(yè)務(wù)層受另兩層的限制。


    各層的職責(zé):

    表示層:負(fù)責(zé)顯示信息,及從系統(tǒng)外部得到輸入。表示層的設(shè)計(jì)決定系統(tǒng)界面的可用性,及信息輸入和展示的可靠性。表示層只知道如何展示信息,及收集用戶輸入,并不知道該如何對(duì)這些輸入進(jìn)行處理來完成業(yè)務(wù)。

    業(yè)務(wù)層:完成業(yè)務(wù)邏輯。業(yè)務(wù)層設(shè)計(jì)決定客戶價(jià)值是否能夠得到實(shí)現(xiàn)。這是系統(tǒng)的關(guān)鍵。外在的表現(xiàn)是功能性。業(yè)務(wù)層設(shè)計(jì)和實(shí)現(xiàn)的失誤表現(xiàn)在用戶端即功能缺失,功能不可靠等。如果需要對(duì)業(yè)務(wù)層的業(yè)務(wù)規(guī)則進(jìn)行解耦,則可以使用規(guī)則引擎如Drools,把業(yè)務(wù)規(guī)則分離出來。但分離后的業(yè)務(wù)規(guī)則仍屬于業(yè)務(wù)層。業(yè)務(wù)層知道如何對(duì)用戶輸入進(jìn)行處理,能夠應(yīng)用業(yè)務(wù)規(guī)則完成用戶所需的業(yè)務(wù),但它不知道數(shù)據(jù)如何讀取和保存。

    持久層:負(fù)責(zé)用戶信息的持久化。持久層的失誤表現(xiàn)在外即數(shù)據(jù)處理(儲(chǔ)存,展示等)不可靠。持久層完全不知道業(yè)務(wù),只專注于數(shù)據(jù)存儲(chǔ)和讀取。所謂持久化并不一定是指數(shù)據(jù)庫,任何方式的持久化(通過文件,網(wǎng)絡(luò)的持久化等)都應(yīng)由持久層完成。

    各層的設(shè)計(jì)都會(huì)直接影響系統(tǒng)性能。

    三層的體積大小和復(fù)雜度在不同的系統(tǒng)中可能會(huì)有很大的不同。比如說GOOGLE的搜索引擎,它的界面很簡(jiǎn)單,可以想像表示層是比較容易實(shí)現(xiàn)的,而它的業(yè)務(wù)層,關(guān)系到處理關(guān)鍵字,分析搜索結(jié)果,決定排名等,而持久層則要負(fù)責(zé)處理超大量的數(shù)據(jù)。業(yè)務(wù)層和持久層則相當(dāng)復(fù)雜。而有的系統(tǒng)持久層會(huì)很小,比如殺毒軟件,媒體播放軟件等。業(yè)務(wù)層小而另兩層大的例子暫時(shí)還沒有想到:)


    posted @ 2007-09-08 19:45 shaofan 閱讀(5130) | 評(píng)論 (2)編輯 收藏

    help是一個(gè)內(nèi)置函數(shù),所謂內(nèi)置函數(shù),就是在Python中被自動(dòng)加載的函數(shù),任何時(shí)候都可以用。參數(shù)分兩種:

    • 如果傳一個(gè)字符串做參數(shù)的話,它會(huì)自動(dòng)搜索以這個(gè)字符串命名的模塊,方法,等。
    • 如果傳入的是一個(gè)對(duì)象,就會(huì)顯示這個(gè)對(duì)象的類型的幫助。

    比如輸入help(’print’),它就會(huì)尋找以’print’為名的模塊,類,等,找不到就會(huì)看到提示信息。而print在python里是一個(gè)保留字,和pass,return同等,而非對(duì)象,所以help(print)也會(huì)出錯(cuò)((kkkkkkk))。

    舉個(gè)例子:

    1 help(’sys’) #會(huì)列出sys模塊的幫助
    2 = [1,2,3]
    3 help(a) #會(huì)顯示list的幫助
    4 help(a.append) #會(huì)顯示list的append方法的幫助

    python安裝自帶的library reference,2.1節(jié)是關(guān)于內(nèi)置函數(shù)的。

    Reference Manual的6.6節(jié)可以找到關(guān)于print的東東。

    posted @ 2007-06-05 06:28 shaofan 閱讀(2766) | 評(píng)論 (0)編輯 收藏

    Struts2默認(rèn)theme是xhtml,它用表格來對(duì)表單中的控件進(jìn)行排版。它也提供一個(gè)客戶端的js驗(yàn)證功能,但是它的js腳本卻有些問題,在某些情況下,前次驗(yàn)證的提示信息無法被清除,提示信息會(huì)不斷的累積顯示在屏幕上。而按照設(shè)計(jì),每次提交表單時(shí)應(yīng)只顯示每次驗(yàn)證的出錯(cuò)信息。

    它的客戶端驗(yàn)證的流程大概是這樣,用戶提交表單時(shí),對(duì)各個(gè)控件的輸入按預(yù)先設(shè)置的規(guī)則進(jìn)行驗(yàn)證,如果有問題,則清除表單里原有的出錯(cuò)提示信息,并寫入新的提示。其設(shè)計(jì)的功能是把出錯(cuò)信息寫表格里出錯(cuò)控件的上方,以便用戶看得更加清楚。問題就出在其用來清除原出錯(cuò)信息的函數(shù),其代碼是這樣的(在struts.jar的template/xhtml目錄下可以找到):

     1 function clearErrorMessages(form) {
     2 
     3     var table = form.childNodes[1];
     4     iftypeof table == "undefined" ) {
     5         table = form.childNodes[0];
     6     }
     7 
     8     // clear out any rows with an "errorFor" attribute
     9     var rows = table.rows;
    10     var rowsToDelete = new Array();
    11     if (rows == null){
    12         return;
    13     }
    14 
    15     for(var i = 0; i < rows.length; i++) {
    16         var r = rows[i];
    17         if (r.getAttribute("errorFor")) {
    18             rowsToDelete.push(r);
    19         }
    20     }
    21 
    22     // now delete the rows
    23     for (var i = 0; i < rowsToDelete.length; i++) {
    24         var r = rowsToDelete[i];
    25         table.deleteRow(r.rowIndex);
    26         //table.removeChild(rowsToDelete[i]);
    27     }
    28 }


    看這個(gè)函數(shù)的前三行,它試圖取得form的第1個(gè)或第2個(gè)子節(jié)點(diǎn),并把它作為table來處理(看接下來的幾行)。要想清除表格里的錯(cuò)誤信息,首先要取得表格本身,這沒錯(cuò),但是如果第1個(gè)或第2個(gè)子節(jié)點(diǎn)不是table的話,腳本就會(huì)出錯(cuò),造成原出錯(cuò)信息無法清除,這樣每次提交后的提示信息就會(huì)累積在屏幕上。

    要解決這個(gè)問題有兩個(gè)辦法:
    • 寫代碼時(shí)要小心,保證form的第1或2個(gè)子節(jié)點(diǎn)是table,不要在生成table前加其他代碼。
    • 或,修改xhtml的validation.js,使它總能獲得正確的table元素,重新打包到struts.jar。
    剛看了一下Struts的JIRA,已經(jīng)有人報(bào)告了這個(gè)問題(id WW-1802),而且這個(gè)bug在2.1版本中已經(jīng)解決了。

    posted @ 2007-06-03 17:56 shaofan 閱讀(2537) | 評(píng)論 (3)編輯 收藏

    假設(shè):用兩者寫一個(gè)最小的WEB程序。
    過程可以參照:
    1.struts的就太多了,隨便哪個(gè)都可以
    2.python/django可以看limodou寫的Django step by step

     

    Java/Struts/JSP  Python/Django
    開發(fā)步驟 1.在web.xml里配置struts的servlet
    2.在struts-config.xml里配置URL和action的映射
    3.寫action
    4.寫JSP
    1.在urls.py里配置URL到方法的映射
    2.寫相應(yīng)的方法
    3.寫HTML模板
    調(diào)用過程 1.根據(jù)web.xml的映射調(diào)用struts的servlet controller
    2.servlet controller根據(jù)struts-config.xml的映射調(diào)用相應(yīng)的action
    3.action處理請(qǐng)求
    4.JSP渲染顯示
    1.根據(jù)urls.py的映射調(diào)用相應(yīng)的方法
    2.方法處理請(qǐng)求
    3.HTML渲染顯示


    相比之下前者用了兩層才把一個(gè)HTTP請(qǐng)求映射到實(shí)際處理的方法:第一次是servlet的映射,第二次是struts action的映射。
    而django則一次就從URL映射到相應(yīng)的方法了。

    另外一個(gè)比較顯著的區(qū)別,也是基于java和python的語言上的區(qū)別吧,java的所有方法必需包含在一個(gè)類中,因此action mapping配置時(shí)是映射到類,而action在實(shí)現(xiàn)類則應(yīng)實(shí)現(xiàn)事先約定的方法(通過繼承或?qū)崿F(xiàn)接口)。而django則直接得多,可以直接在配置里寫明處理請(qǐng)求的方法名。


    posted @ 2007-04-06 19:11 shaofan 閱讀(4975) | 評(píng)論 (0)編輯 收藏

    DOM (Document Object Model)是一套語言無關(guān)的XML解析的接口定義。它定義了在XML解析中需要的類型,方法,以及屬性,比如如何獲得一個(gè)XML標(biāo)簽,如何改變標(biāo)簽的內(nèi)容,如何改變它的屬性,等等。

    DOM只是一個(gè)定義,并不是具體的實(shí)現(xiàn),它的目的就是為了讓大家在各個(gè)平臺(tái)上都能用相同的方式來處理XML,這樣一來,我只要了解DOM,基本上在各個(gè)平臺(tái)上都可以方便的處理XML,而不用重新學(xué)習(xí)了。比如說,Java, JavaScript, Python都有DOM的實(shí)現(xiàn),用它們來處理XML,方式基本上都是一樣的(當(dāng)然也有非DOM的XML解析方式)。在Java下,實(shí)現(xiàn)DOM的類庫就有很多,比如JDom,Xerces, 用GOOGLE一搜就一大把。現(xiàn)在Java 5.0內(nèi)置的就是Xerces。而JavaScript本身就內(nèi)置了DOM的實(shí)現(xiàn)。Python也默認(rèn)安裝了DOM的庫。

    正因?yàn)镈OM致力于實(shí)現(xiàn)各個(gè)平臺(tái)上對(duì)XML一致的處理方式,它定義了一堆自己的接口。因此在用DOM的時(shí)候,會(huì)有很多非NATIVE的東東。比如說,返回節(jié)點(diǎn)的子節(jié)點(diǎn)的方法,childNodes,返回的類型是NodeList。我第一次在Java上用,就以為是返回一個(gè)List,然后用get(n)方法來取得某元素。而實(shí)際上NodeList是用item(n)的方法來取得某元素的。這就讓我覺得很怪。而DOM正是用這種方式來獲得“語言無關(guān)”的能力的。

    DOM是用IDL(Interface Definition Language)來定義的。完整的定義可以在這里找到 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html。IDL也很容易看懂。定義的1.1節(jié)列出了所有的接口。

    這些接口里,最重要而且常用的是Node,NodeList,Document,Element,Text,Attr這幾個(gè)。DOM把XML文檔看作一棵樹,樹上的每個(gè)元素都是Node。每個(gè)Node都屬于某個(gè)類型,比如Element,attribute,text等。這些類型就表明這個(gè)節(jié)點(diǎn)在XML文檔里的類型了。

    比如Node里有個(gè)屬性:

    ??readonly?attribute?unsigned? short ??nodeType;

    根據(jù)這個(gè)定義,對(duì)于取得的節(jié)點(diǎn),我們就可以通過讀取nodeType這個(gè)屬性來判斷這個(gè)節(jié)點(diǎn)的類型。在Java里,所有的屬性都是用getter來取得的,因此對(duì)某節(jié)點(diǎn)n,就可以用n.getNodeType()取得它的類型。Node接口里也定義了類型常量:

    ??const?unsigned?short??????ELEMENT_NODE???????????????????=?1;
    ??const?unsigned?short??????ATTRIBUTE_NODE?????????????????=?2;
    ??const?unsigned?short??????TEXT_NODE??????????????????????=?3;
    ??const?unsigned?short??????CDATA_SECTION_NODE?????????????=?4;
    ??const?unsigned?short??????ENTITY_REFERENCE_NODE??????????=?5;
    ??const?unsigned?short??????ENTITY_NODE????????????????????=?6;
    ??const?unsigned?short??????PROCESSING_INSTRUCTION_NODE????=?7;
    ??const?unsigned?short??????COMMENT_NODE???????????????????=?8;
    ??const?unsigned?short??????DOCUMENT_NODE??????????????????=?9;
    ??const?unsigned?short??????DOCUMENT_TYPE_NODE?????????????=?10;
    ??const?unsigned?short??????DOCUMENT_FRAGMENT_NODE?????????=?11;
    ??const?unsigned?short??????NOTATION_NODE??????????????????=?12;

    用這些常量和和n.getNodeType()的結(jié)果比較,就可以知道它是不是某種類型。

    Node接口中也定義了一些方法,比如:

    ?Node?????appendChild(in?Node?newChild)????raises(DOMException);

    表明appendChild方法需要一個(gè)Node類型的參數(shù),返回一個(gè)Node。 具體的說明可以點(diǎn)文檔上的鏈接進(jìn)去,也很容易看懂。

    Node接口里定義了操縱節(jié)點(diǎn)的方法,比如增加子節(jié)點(diǎn),返回父節(jié)點(diǎn),插入新節(jié)點(diǎn),返回節(jié)點(diǎn)類型,等等。Document,Element等接口都繼承Node接口,因此在它們上面都可以使用操縱節(jié)點(diǎn)的方法。

    Document:代表整個(gè)XML文檔。所有DOM元素都不能用類似Java里new的方式來生成,而是要通過調(diào)用Document里的相應(yīng)方法來生成。因此它提供了生成諸如Element, Attr, Text的方法。比如createElement, createTextNode, createComment等。它也提供了名為getElementsByTagName的方法,用來通過標(biāo)簽名稱來取得其對(duì)象。比如getElementByTagName("ul")就可以獲得所有ul標(biāo)簽。它也提供一些文檔的屬性,比如xmlEncoding,inputEncoding等。它的一個(gè)屬性,documentElement代表文檔的根節(jié)點(diǎn)。所有對(duì)XML元素的操作,基本上都是從Document開始的。

    Element:代表一個(gè)XML標(biāo)簽。它可以有屬性,子標(biāo)簽,等。比如<ul id="booklist"><li>hello</li></ul>。標(biāo)簽ul是一個(gè)Element,它有一個(gè)屬性叫id,屬性的值是booklist。它有一個(gè)子結(jié)點(diǎn)li。li也是一個(gè)標(biāo)簽,它也有個(gè)子節(jié)點(diǎn)hello,是一個(gè)Text類型的節(jié)點(diǎn)。這個(gè)接口提供操縱其標(biāo)簽屬性的方法,比如getAttribute,setAttribute,removeAttribute等。它也提供了和Document中一樣的getElementsByTagName的方法,用來獲得在這個(gè)節(jié)點(diǎn)下的元素。

    Attr:代表標(biāo)簽中的屬性。比如上面的id。它也是一個(gè)Node。它有名字,值,也可以獲得它的所屬標(biāo)簽。

    Text:代表一段文字,比如上面的hello,它也一個(gè)Node,但比較特殊,它不是直接繼承Node,而是繼承CharacterData接口,后者繼承了Node。但是它不能有子節(jié)點(diǎn)。

    用JavaScript給一個(gè)例子。假設(shè)有一個(gè)HTML文檔:

    < html >< head >< title > Try?DOM </ title ></ head >< body >
    < ul >
    < li > hello </ li >
    < li > world </ li >
    </ ul >
    </ body ></ html >

    下面是增加一個(gè)li的JavaScript方法:

    ulList? = ?document.getElementsByTagName( " ul " );
    ul?????
    = ?ulList.item( 0 );
    txt????
    = ?document.createTextNode( " I?am?new?li " );
    li?????
    = ?document.createElement( " li " );
    li.appendChild(txt);
    ul.appendChild(li);

    用Java來寫,是這樣:

    NodeList?ulList? = ?document.getElementsByTagName( " ul " );
    Node??????? ul??????
    = ?ulList.item( 0 );
    Text????????? txt???? ?
    = ?document.createTextNode( " I?am?new?li " );
    Element??? li??? ????
    = ?document.createElement( " li " );
    li.appendChild(txt);
    ul.appendChild(li);

    可以看到處理方式和數(shù)據(jù)類型都是一樣的。如果要了解更多,可以看看DOM的定義,都是IDL。

    posted @ 2007-04-01 18:45 shaofan 閱讀(856) | 評(píng)論 (0)編輯 收藏

    我的博客已搬家,請(qǐng)移步到 http://shao-fan.com/blog 閱讀最新內(nèi)容!


    Ubuntu/Debian中的update-alternative用來對(duì)系統(tǒng)中不同版本的同個(gè)軟件進(jìn)行管理。
    比如,系統(tǒng)中可能裝有GNU的Java編譯器,和SUN的Java編譯器。可以用update-alternatives來設(shè)置當(dāng)前使用它們中的哪一個(gè)。

    它的原理是在/usr/bin中建立一個(gè)link,指向/etc/alternatives中的一個(gè)文件,而些文件又是一個(gè)link,指向當(dāng)前使用的命令。比如java命令,查看如下:

     $ which java
    /usr/bin/java
    $ ls -l /usr/bin/java
    lrwxrwxrwx /usr/bin/java -> /etc/alternatives/java
    $ ls -l /etc/alternatives/java
    lrwxrwxrwx /etc/alternatives/java -> /usr/lib/j2re1.5-sun/bin/java
    $ ls -l /usr/lib/j2re1.5-sun/bin/java
    -rwxr-xr-x /usr/lib/j2re1.5-sun/bin/java

    參數(shù)--display可以某個(gè)軟件的當(dāng)前配置,如:

     $ /usr/sbin/update-alternatives --display java
    java - status is auto.
    link currently points to /usr/lib/j2re1.5-sun/bin/java
    /usr/lib/kaffe/bin/java - priority 300
    slave java.1.gz: /usr/share/man/man1/java.kaffe.1.gz
    /usr/lib/j2re1.5-sun/bin/java - priority 315
    slave java.1.gz: /usr/lib/j2re1.5-sun/man/man1/java.1.gz
    Current `best' version is /usr/lib/j2re1.5-sun/bin/java.

    status有auto和manual兩種。一旦用戶更改了系統(tǒng)的默認(rèn)設(shè)置,它就變?yōu)閙anual。在auto的狀態(tài)下,系統(tǒng)會(huì)根據(jù)幾套配置的priority來判斷當(dāng)前應(yīng)該使用哪套配置。

    每套配置可以設(shè)定多個(gè)link,它們被稱為slave。上面的例子中,有兩套java的配置。一套是/usr/lib/kafe/bin/java,另一套是/usr/lib/j2re1.5-sun/bin/java,它們各有一個(gè)slave。在些例中這些slave設(shè)置的是java命令的 manual。當(dāng)更改了配置時(shí),用man命令查看的幫助也會(huì)相應(yīng)更改。

    參數(shù)--config可以用來更改當(dāng)前的配置。

     $ sudo /usr/sbin/update-alternatives --config java 
    There are 2 alternatives which provide `java'.
    Selection Alternative
    -----------------------------------------------
    1 /usr/lib/kaffe/bin/java
    *+ 2 /usr/lib/j2re1.5-sun/bin/java
    Press enter to keep the default*, or type selection number: 1
    Using `/usr/lib/kaffe/bin/java' to provide `java'.

    參數(shù)--install用來設(shè)置一套新的配置。具體參見 http://blog.stevenkroon.com/2006/08/29/debian-update-alternatives/

    posted @ 2006-12-25 01:43 shaofan 閱讀(6308) | 評(píng)論 (1)編輯 收藏

    Web開發(fā)真是越來越有意思了。現(xiàn)在居然可以在JavaScript里直接調(diào)用Java寫的方法。大水牛Buffalo的最新版1.2.3發(fā)行離現(xiàn)在已有半年時(shí)間了,現(xiàn)在才注意到。在客戶端的代碼相當(dāng)簡(jiǎn)單:

    buffalo.remoteCall("userService.listAll",[],function(reply){
     //?不用擔(dān)心,reply.getResult會(huì)從聰明的判斷服務(wù)器端遠(yuǎn)程調(diào)用的結(jié)果類型。
     var?userList?=?reply.getResult();?
     var?firstUserFamilyName?=?userList[0].name.familyName;
    });

    給Web程序加上Buffalo也相當(dāng)容易。只要下載幾個(gè)jar文件放到lib目錄下,外加幾個(gè)JS文件,然后在web.xml里加一個(gè)Servlet即可。用的時(shí)候是需要有個(gè)properties文件來定義哪些JAVA方法可以被JS調(diào)用。而服務(wù)器端的JAVA代碼不需要做任何改動(dòng)。

    暫時(shí)手頭上還想不起來哪些地方會(huì)用,但是這個(gè)東東可是我很久以前曾經(jīng)想過的,現(xiàn)在有人實(shí)現(xiàn)了,還是很激動(dòng)人心的啊。Buffalo的主頁是 http://www.amowa.net/buffalo/zh/index.html?。


    posted @ 2006-09-08 03:59 shaofan 閱讀(8923) | 評(píng)論 (6)編輯 收藏

    主站蜘蛛池模板: 久久亚洲国产成人影院| 在线观看av永久免费| 天天综合亚洲色在线精品| 亚洲今日精彩视频| 四虎永久在线免费观看| 99久久免费国产精品特黄| 久久免费福利视频| 巨胸狂喷奶水视频www网站免费| 亚洲国产成人无码AV在线影院| 亚洲永久中文字幕在线| 亚洲精品综合一二三区在线| 久久久久亚洲?V成人无码| 四虎影库久免费视频| 免费看韩国黄a片在线观看| 91福利免费视频| 久久久久国产精品免费看| 男女一边桶一边摸一边脱视频免费| 国产精品亚洲综合网站| 亚洲精品天堂无码中文字幕| 亚洲va精品中文字幕| 亚洲日韩在线视频| 亚洲免费在线视频| 亚洲一区二区影院| 亚洲好看的理论片电影| 亚洲AV成人片色在线观看| 亚洲大尺度无码专区尤物| 久久精品国产亚洲综合色| 亚洲精品一品区二品区三品区| 狠狠综合久久综合88亚洲| 在线观看午夜亚洲一区| 亚洲综合精品香蕉久久网| 亚洲韩国精品无码一区二区三区| 狠狠综合久久综合88亚洲| 亚洲处破女AV日韩精品| 亚洲国产天堂久久综合网站| 亚洲人成电影福利在线播放| 精品日韩亚洲AV无码一区二区三区 | 97人妻无码一区二区精品免费| 在线观看永久免费| 亚洲人成网站免费播放| 免费看美女让人桶尿口|