亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Spring中的持久性

2019-11-18 16:12:57
字體:
來源:轉載
供稿:網友

  編者按:簡單而有技巧地解決問題總是比蠻力解決要好。這就是最近出版的Better, Faster, Lighter java一書中所遵循的原則。從這本書的第八章中節選出來的這個關于SPRing的兩部分的系列文章,也體現了書的作者BrUCe Tate和Justin Gehtland所信奉的這個原則。本周Bruce和Justin將繼續第一部分,向Pet Store示例添加持久性,并探討Spring框架中的持久性邏輯方面。

添加持久性
  CartItem對象不一定非要是持久的。另一方面,您希望從數據庫中獲取產品和類別。J2EE應用程序開發人員一直在尋求一種成熟的持久性方法而沒有成功。好的持久性框架應該支持透明,并且不侵入域模型。Spring允許您將透明對象與數據訪問層分離開來。然后Spring使您可以很容易地在持久性之上建層??梢允褂肑DBC抽象層,它可以分離掉JDBC中許多冗長乏味、易于出錯的方面,比如連接管理和錯誤處理。Spring JDBC層使用一個稱為回調模板 的特性來將控制權由應用程序交給Spring框架。借助于該策略,Spring不再需要管理連接、結果集和特定于RDBMS的錯誤。當想要使用JDBC直接處理關系查詢時,該框架就非常有用了。

  通常,我們都寧愿處理對象而不愿處理關系。Spring也有一個用于透明持久性的模型。jPetStore使用Spring的OR映射層,該層提供了許多預包裝的選項?,F在Spring支持針對基本JDBC DAO、Hibernate和JDO的映射層。這個例子使用一個稱為iBATIS SQL Maps的DAO框架來實現Spring DAO層。

模型
  每個Spring解決方案都從一個透明域模型開始。例8-3從透明模型對象(一個產品)開始。

  例8-3. Product.java

public class Product implements Serializable {  private String productId;  private String categoryId;  private String name;  private String description;  public String getProductId( ) { return productId; }  public void setProductId(String productId) { this.productId = productId.trim( ); }  public String getCategoryId( ) { return categoryId; }  public void setCategoryId(String categoryId) { this.categoryId = categoryId; }  public String getName( ) { return name; }  public void setName(String name) { this.name = name; }  public String getDescription( ) { return description; }  public void setDescription(String description) { this.description = description; }  public String toString( ) {    return getName( );  }}

  這里沒什么特別的。它完全由屬性組成,通過getter、setter以及一個實用方法toString進行訪問。如果您看一下jPetStore應用程序,就會發現域中其他每個持久性對象都有類似的類:Account、Order、Category、Item和LineItem。

映射
  至于Hibernate,iBATIS SQL Maps框架有一個映射文件。在該文件中,Java bean中的每個持久性屬性都映射到一個數據庫列。使用SQL Maps,可以在該映射文件中創建所有的SQL,將所有的SQL與xml映射文件隔離開來。例8-4顯示了Product的XML映射支持。

  例8-4. Product.xml

[1]  [2]       [3]                                   [4]          select PRODUCTID, NAME, DESCN, CATEGORY from PRODUCT where PRODUCTID = #value#     [5]          select PRODUCTID, NAME, DESCN, CATEGORY from PRODUCT where CATEGORY = #value#     [6]          select PRODUCTID, NAME, DESCN, CATEGORY from PRODUCT                             lower(name) like #keyWordList[]# OR lower(category) like #keywordList[]# OR lower(descn) like #keywordList[]#                          


  下面是注釋的含義:

  [1]每個映射文件對應于一個域對象。本例中的域對象關系到為該DAO所指定的查詢的返回類型。

  [2]關于DAO層的其他信息,比如緩存策略,也屬于映射文件。這里,iBatis將緩存維持24小時,然后刷新。

  [3]當然了,每個查詢都返回一個產品。該映射將結果集中的每一列與產品中的一個字段聯系起來。

  [4]該SQL語句找出給定productID的產品。

  [5]該SQL語句找出一個類別中的所有產品。它返回一個產品列表。

  [6]該SQL語句是動態的。IBatis迭代關鍵字列表,形成一個動態查詢。

  到目前為止,您已經看到了Product及其映射的域模型,包括查詢。您已經上路了。

DAO接口
  應用程序必須與Spring和SQL Maps都進行集成。應用程序通過一個DAO接口和一個具體實現將二者聯系起來。例8-5就是該接口。

  例8-5. ProductDAO.java

public interface ProductDao {  List getProductListByCategory(String categoryId) throws DataaccessException;  List searchProductList(String keywords) throws DataAccessException;  Product getProduct(String productId) throws DataAccessException;}

  這非常簡單??梢钥吹?,定義在映射中的每個查詢都有一個接口。具體來說,getProduct接口通過ID查找產品,getProductListByCategory接口返回一個類別中的所有產品,還有一個基于關鍵字的動態查詢接口?,F在,DAO拋出Spring異常,任何使用DAO的邏輯都有一致的異常,即使您之后決定更改實現。

DAO實現
  余下的就是要使用SQL Map來實現接口。例8-6是Product的SQL Map實現。

  例8-6. SqlMapProductDao.java

    public class SqlMapProductDao extends SqlMapDaoSupport implements ProductDao {[1]  public List getProductListByCategory(String categoryId) throws DataAccessException {       return getSqlMapTemplate( ).executeQueryForList("getProductListByCategory",      }[1]  public Product getProduct(String productId) throws DataAccessException {       return (Product) getSqlMapTemplate( ).executeQueryForObject("getProduct", productId);     }[1]  public List searchProductList(String keywords) throws DataAccessException {       Object parameterObject = new ProductSearch(keywords);       return getSqlMapTemplate( ).executeQueryForList("searchProductList", parameterObject);     }     /* Inner Classes */[2]  public static class ProductSearch {        private List keywordList = new ArrayList( );        public ProductSearch(String keywords) {          StringTokenizer splitter = new StringTokenizer(keywords, " ", false);          while (splitter.hasMoreTokens( )) {            this.keywordList.add("%" + splitter.nextToken( ) + "%");          }        }        public List getKeywordList( ) {          return keywordList;        }     }    }

  下面是注釋的含義:

  [1]這些方法提供了接口的SQL Map實現。其他的實現可能使用Hibernate、JDO或straight JDBC。在本例中,getTemplate調用指示Spring獲取支持iBATIS SQL Map的模板,并使用該框架執行適當的查詢。

  [2]我并非特別喜歡內部類,但是這是通常實現關鍵字查詢的方法。在本例中,內部類通過實現getKeywordList來支持searchProductList方法。使用余下的DAO實現,內部類有助于組織代碼基址,將所有的支持都保存在一個地方。

  現在我們看到了映射、模型和DAO。有了一個完全持久性的模型。接下來,我們要使用代碼訪問DAO層。jPetStore通過一個外觀層來接受所有的DAO訪問。

通過外觀使用模型
  正如第3章一樣,通常對模型使用一個高級接口非常有用,它稱為外觀。在本例中,jPetStore外觀有三個作用:
  • 合并數據訪問層所有的客戶端;
  • 為其他的應用程序提供一個公共用戶界面;
  • 用作與其他服務(比如事務支持)的連接點。


  在本例中,外觀是一個非常薄的層,它環繞所有的DAO。通過配置和方法攔截器,Spring使外觀具有聲明式事務支持。在本例中,外觀存在于兩個部分中:接口和實現。接口允許不影響其他代碼地更改外觀的實現。例8-7顯示了接口。

  例8-7. PetStoreFacade.java

public interface PetStoreFacade {  Account getAccount(String username);  Account getAccount(String username, String password);  void insertAccount(Account account);  void updateAccount(Account account);  List getUsernameList( );  List getCategoryList( );  Category getCategory(String categoryId);  List getProductListByCategory(String categoryId);  List searchProductList(String keywords);  Product getProduct(String productId);  List getItemListByProduct(String productId);  Item getItem(String itemId);  boolean isItemInStock(String itemId);  void insertOrder(Order order);  Order getOrder(int orderId);  List getOrdersByUsername(String username);}

  可以將該接口視為所有創建、讀、更新或刪除任何Pet Store對象的方法的統一列表。注意,您不能看到來自所有DAO的方法,而只能看到我們希望公開給外界的方法。還要注意接口中的命名一致性。這很重要,因為,在我們的配置文件中,您可以看到用來傳播以get、search、update或insert開頭的方法的事務支持。

  實現調用底層的DAO來執行適當的操作。必須在接口中實現所有的方法。例8-8是與ProductDAO相關的方法的實現。

  例8-8. Excerpt fromPetStoreImpl.java

[1] private ProductDao productDao;  ...    public void setProductDao(ProductDao productDao) {       this.productDao = productDao;	}  ...[2] public List getProductListByCategory(String categoryId) {       return this.productDao.getProductListByCategory(categoryId);    }	    public List searchProductList(String keywords) {       return this.productDao.searchProductList(keywords);    }  ...

  下面是注釋的含義:

  [1]顯示DAO訪問(包括粗體文本)。Spring框架使用反射將DAO插入到外觀中。這意味著外觀必須支持一個set方法和一個私有成員變量。

  [2]提供數據訪問的方法使用底層的DAO來做實際工作(包括對粗體文本的處理)。

  當然了,我沒有給出接口的所有方法的實現。只顯示了與產品相關的方法。它們分為兩部分。

  首先,應用程序上下文將每個DAO連接到外觀。Spring使用反射和bean工廠來創建產品DAO,并使用setProductDAO API來對其進行設置。為此,外觀需要一個變量來保存DAO以及一個set方法來通過反射訪問它。

  其次,實現非常簡單。外觀只將請求傳遞給下面的模型層。但是,最終的實現要強大得多。外觀用作一個支持聲明式事務的EJB會話bean。通過配置,POJO變成了一個聲明式事務協調程序!它也是整個數據庫層的中心控制點。余下的工作就是配置DAO層了。

配置DAO層
  剛才我們只看到了模型的配置。例8-9則顯示了一個使用簡單事務管理的數據庫的數據層配置。正如您所預料的,您將看到JDBC驅動程序的配置和所有DAO bean的聲明。

  例8-9. dataAccessContext-local.xml

   [1]        /WEB-INF/jdbc.properties    [2]                                 [3]            [4]               classpath:/sql-map-config.xml    [5]        	   		 		   	   		 		   	   		 		   	   		 		   	   	       			   	   	   


  下面是注釋的含義:

  [1]這個bean處理JDBC配置。JDBC配置屬性在一個標準的JDBC配置文件中,這使得它們的維護和讀取更為容易。Spring提供了一個配置類,使得用戶可以輕松地讀取屬性文件,而無需將其轉換為XML。

  [2]這里是數據源。它是一個標準的J2EE數據源。許多J2EE應用程序或框架都將應用程序或框架硬連接到一個給定的數據源上。而對其進行配置,就可以輕松地選擇自己的數據源(以及池化策略)了。

  [3]applicationContext.xml配置設置事務策略。該配置指定實現。該應用程序使用數據源事務管理器,它通過JDBC將事務管理委托給數據庫(使用提交和回滾)。

  [4]必須對構建DAO的iBATIS SQL Map實用工具進行配置。這里配置了。

  [5]最后,我們看到了實際的DAO配置。不知道您是否記得,applicationContext.xml文件通過名稱引用每個bean。

  配置不止從模型或視圖中解除了持久性層的耦合。還從持久性層解除事務管理的耦合,將事務策略與實現分離開來,并隔離數據源。下面我們來看除了配置之外的眾多好處。

優點
  這就是Product的所有持久性代碼。JPetStore其余的代碼也都類似于此。應用程序有效地將整個域模型隔離到單獨的一個層中。域對任何服務都沒有依賴性,包括數據層。我們還將所有的數據訪問都封裝到一個整潔的DAO層中,該層獨立于數據存儲。要注意您沒有看到的:

數據源配置
  由Spring框架處理。您不必管理一整套單元素集合(針對會話管理)、數據源等等。您還可以將重要決定(如:數據源類型)延遲到部署時。

連接處理
  Spring框架管理所有的連接處理。一個最常見的JDBC錯誤就是連接泄漏。如果不對連接的關閉非常小心,特別是在異常條件中,應用程序就很容易失去穩定而崩潰。

特化的異常
  許多框架將SQL異常傳至頂層。它們通常都將可能特化到您自己的RDBMS中的代碼內置,這使得難以編碼可移植的應用程序。Spring有它自己的異常層次結構,從而使您遠離這些問題。此外,如果換為使用Hibernate或JDO方法,不需要對異常處理做任何更改。

  到現在為止,我們有了一個整潔、透明的域模型和一個獨立于數據庫的、不怎么需要維護的服務層。每個層都巧妙地封裝起來了??赐炅撕笈_邏輯,現在我們來為應用程序添加一個用戶界面。

呈現
  大多數情況下,Spring框架并不重新改造現行的技術。但是,在呈現邏輯方面,Spring引入了一個稱為MVC Web的簡單的模型-視圖-控制器框架,它包括許多競爭性的架構,比如Struts和Java Server Faces (JSF)。使用Spring不一定非得使用MVC Web。但是如果決定使用它,就會得到一些好處:
  • MVC Web不指定視圖選擇。其他框架可能會對您所喜歡的視圖技術提供更好的支持,比如Velocity(專有的)和Struts (jsp)。例如,Struts通過請求屬性公開模型。因此,要使用諸如Velocity之類不理解Servlet API的技術,就需要構建一個橋梁servlet。Spring則是通過一種通用的映射來公開模型,所以它可以與任何視圖技術一起使用。
  • MVC Web提供Spring應用程序的所有方面的一致配置。它使用與其他框架相同的反向控制范例。
  • MVC Web使測試變得更輕松。因為無需再擴展一個類(比如Struts中的Action或ActionForm),所以可以很容易地模擬請求和響應。

  如果曾經使用過Struts,您就應該很熟悉MVC Web的基本范例。圖8-4顯示了它的工作機制??刂破骰旧咸幚砹怂袕妮斎胍晥D傳入的請求。如果輸入請求是一個提交的表單,控制器就調用一個(由程序員創建和配置的)業務驗證例程,并根據結果向用戶發送相關的錯誤視圖或者成功視圖。

Spring中的持久性(圖一)
圖8-4. MVC Web框架的工作機制類似于Struts

配置
  就像對Spring框架的其他元素一樣,要了解一個新的應用程序,要從配置文件開始深入研究。在本例中,用戶界面是在petstore-servlet.xml文件中進行配置的。

  考慮搜索一個類別中的產品的Html頁面,以及根據關鍵字搜索產品的HTML頁面。配置文件需要兩個應用程序上下文文件的控制器。每個記錄項指定一個控制器以及模型對象,如例8-10所示。

  例8-10. web.xml節選

                  


  還記得吧,所有對數據層的訪問都是通過外觀進行的。是的,這些bean ID記錄項指定了外觀,稱為petstore。應用程序中的每個表單都以同樣的方式工作。我們進一步來看看searchProducts的控制器。

控制器
  對于MVC Web,每個表單共享一個控制器實例,它發送所有與給定表單相關的請求。它還將表單封送到正確的驗證邏輯,并向用戶返回適當的視圖。例8-11顯示了searchProducts視圖的控制器。

  例8-11. SearchProductsController.java

   public class SearchProductsController implements Controller {[1] private PetStoreFacade petStore;    public void setPetStore(PetStoreFacade petStore) {       this.petStore = petStore;    }[2] public ModelAndView handleRequest(HttpServletRequest request,                                      HttpServletResponse response)       throws Exception {[3]    if (request.getParameter("search") != null) {          String keyword = request.getParameter("keyword");          if (keyword == null  keyword.length( ) == 0) {             return new ModelAndView("Error",                                  "message",       "Please enter a keyword to search for, then press the search button.");          }          else {[4]          PagedListHolder productList = new PagedListHolder(                     this.petStore.searchProductList(keyword.toLowerCase( )));             productList.setPageSize(4);             request.getsession( ).setAttribute(                     "SearchProductsController_productList", productList);[5]          return new ModelAndView("SearchProducts", "productList", productList);          }       }       else {[6]       String page = request.getParameter("page");            PagedListHolder productList = (PagedListHolder) request.getSession( ).              getAttribute("SearchProductsController_productList");          if ("next".equals(page)) {             productList.nextPage( );          }          else if ("previous".equals(page)) {             productList.previousPage( );          }          return new ModelAndView("SearchProducts", "productList", productList);       }      }	     }

  下面是注釋的含義:

  [1]每個控制器都有對適當的域模型的控制權。在本例中,視圖自然是通過外觀來訪問模型的。

  [2]控制器有一個類似于servlet但是實際上不是servlet的接口。因此用戶請求通過一個調度servlet傳入,該servlet將請求發送給適當的控制器,填充request成員??刂破髦豁憫m當的請求,調用業務數據,并將控制權發送給適當的頁面。

  [3]在本例中,請求是“search”??刂破鞅仨毞治龀鲞m當的關鍵字。

  [4]控制器使用用戶所提供的關鍵字調用業務邏輯。

  [5]控制器將適當的視圖(以及適當的模型)發送給用戶。

  [6]在本例中,請求是“page”。我們的用戶界面支持適用于同一個頁面的多種產品。

表單
  像Struts一樣,Spring可以將HTML表單映射為Java對象。例8-12是當一個Pet Store用戶注冊一個帳號時所返回的Java bean。

  例8-12. AccountForm.java

public class AccountForm {  private Account account;  private boolean newAccount;  private String repeatedPassword;  public AccountForm(Account account) {    this.account = account;    this.newAccount = false;  }  public AccountForm( ) {    this.account = new Account( );    this.newAccount = true;  }  public Account getAccount( ) {    return account;  }  public boolean isNewAccount( ) {    return newAccount;  }  public void setRepeatedPassword(String repeatedPassword) {    this.repeatedPassword = repeatedPassword;  }  public String getRepeatedPassword( ) {    return repeatedPassword;  }}


  這些bean的每個字段都直接對應于一個HTML輸入字段或控制權。Spring框架將一個提交請求轉換為表單,然后可以將它當作POJO來訪問以進行驗證、映射輸入數據或用于其他用途。與Struts不同的是,Spring表單對象可以是任何Java bean。沒有必要擴展ActionForm。這非常重要,因為你不必從一個ActionForm復制屬性到域對象或值對象。

驗證
  您可能已經注意到了原始applciationContext.xml中的驗證邏輯。這些bean通常都被視為業務邏輯,但是它們與用戶界面關系密切,而且它們是由Spring框架直接調用的。當用戶提交表單后,Spring就激活驗證邏輯。Spring根據結果向適當的頁面發送控制權。例8-13顯示了驗證帳號表單的AccountValidator類。

  例8-13. AccountValidator.java

public class AccountValidator implements Validator {   public boolean supports(Class clazz) {      return Account.class.isAssignableFrom(clazz);   }   public void validate(Object obj, Errors errors) {      ValidationUtils.rejectIfEmpty(errors, "firstName", "FIRST_NAME_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "lastName", "LAST_NAME_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "email", "EMAIL_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "phone", "PHONE_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "address1", "ADDRESS_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "city", "CITY_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "state", "STATE_REQUIRED",       ValidationUtils.rejectIfEmpty(errors, "zip", "ZIP_REQUIRED", "ZIP is required.");      ValidationUtils.rejectIfEmpty(errors, "country", "COUNTRY_REQUIRED",    }}

  在本例中,Spring框架從幾個方面使開發人員的生活變得更為輕松。開發人員不需要手動編寫驗證方法。有許多預包裝的方法。框架負責驗證和發送??蚣茇撠煾鶕晒蚴〉慕Y果發送控制權。

  僅僅一章還不足以判斷Spring框架,但是您已經看到了它的整體要點。該框架——更重要的是,這種編碼方式——的優點應該顯而易見了。特別要注意整潔的分層架構所提供的清晰性和簡單性。您可以預料到,將業務邏輯與一個類似于Spring的透明框架相結合是多么輕松的事情。

小結
  我選擇jPetStore應用程序是有很多原因的。最主要的原因是,可以很快就看到一個簡單、快速、輕量級的應用程序與其他可選方案之間的區別。如果您還不是Spring的信徒,我建議您看一看Pet Store的EJB版本。如果您還沒有看過,您會為二者的差別而感到震驚。Spring版本是透明而獨立的,而EJB則是侵入式的,而且還依賴于容器。Spring版本可讀性非常好,而J2EE版本則被EJB最佳實踐的復雜性所淹沒。

  我并非一直是Spring的信徒。實際上,在Rod Johnson與我在波士頓的一次會議上被介紹認識之前,我根本不知道他是誰。后來我逐漸欣賞起這個簡單、優雅而重要的框架。如果您對Spring還很陌生,那么您只能看到一個應用程序。我希望通過這個應用程序,您能夠領會它如何體現本書中的這些原則:

盡可能地簡單
  Spring的易用性和可讀性。在僅僅一章之中,我們介紹了一個具有事務、持久性、一個完整的web前端以及一個完全的模塊化配置引擎的應用程序。

只做一件事,但是要做好
  Spring的框架有許多不同的方面和子框架。但是,它將每個概念很好地分離開來。Spring最基本的意義在于它的bean工廠和配置服務,它們使得用戶可以管理依賴性而無需耦合代碼。Spring的每個附加層都是完全去耦合并且獨立的。

爭取透明
  Spring應用程序完全不需要依賴于基礎容器。實際上,這些應用程序可以輕松自如地存在于容器外。用戶只需手動創建和配置它們。這種能力使得Spring應用程序成為開發人員樂于測試的應用程序。

內容決定形式
  Spring利用它所包含的各種框架為用戶提供了靈活的選擇。針對數據源和登錄的Apache項目為它奠定了良好的基礎。Spring提供了多種可配置的選項,使用戶可以針對給定的解決方案選擇最佳的框架。

支持擴展
  Spring可能是現存的最為開放和可擴展的容器。它允許使用常見的配置服務和整潔的抽象快速有效地進行擴展。

  此處對Spring的介紹并不全面。我的目標只是向您說明,利用本書前六章所介紹的概念是可以構建現實世界的應用程序的。如果想了解得更多,一定要研究一下Spring的高級特性:

  • 與Hibernate和JDO的集成
  • 面向方面編程(AOP)的概念
  • 包含JTA支持的事務模板

  《Better, Faster, Lighter Java》一書的兩位作者將在其他章節中繼續探討使用了本書所介紹的基本原則的實際例子。例如,一個稱為Simple Spider的服務的實現,您還將看到該服務被集成到Spring中。之后您將會看到類似框架的更多優點。


  原文出處 Persistence in Spring: http://www.onjava.com/pub/a/onjava/excerpt/BFLJava_chap8/index1.html

Spring中的持久性(圖二)
 作者簡介Bruce A.ate是一名山地車手和皮劃艇手,也是2個孩子的父親。在閑暇時間里,他還是一名獨立顧問。他住在德克薩斯州的首府奧斯汀。他編寫了4本書,其中包括最暢銷的《Bitter Java》一書,最近出版了《Better,Faster,Lighter Java》(O'Reilly)。 Alexander Ananiev是一個程序員、作者、導師和指導員,他專攻現實世界軟件應用程序。

(出處:http://www.49028c.com)



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美乱人伦中文字幕在线| 亚洲美女精品成人在线视频| 精品av在线播放| 国产精品美女久久久免费| 国产精品18久久久久久麻辣| 亚洲女人天堂av| 亚洲美女www午夜| 亚洲综合日韩中文字幕v在线| 在线精品国产成人综合| 久久精品亚洲热| 国产精品中文在线| 久久久av亚洲男天堂| 韩国三级电影久久久久久| 国产日韩欧美电影在线观看| 精品视频偷偷看在线观看| 亚洲国产成人av在线| 国产日韩中文字幕| 国外色69视频在线观看| 成人免费视频网| 日韩欧美在线观看| 日韩亚洲成人av在线| 亚洲一区二区三区毛片| 国产精品wwww| 亚洲欧美一区二区三区久久| 91日本在线观看| 国语自产精品视频在线看一大j8| 国产精品国内视频| 日韩av在线一区二区| 亚洲视屏在线播放| 国产精品永久免费视频| 日韩欧美国产免费播放| 亚洲国产精品va在线看黑人动漫| 亚洲四色影视在线观看| 国产精品网站大全| 国产精品久久久久久av福利软件| 中文字幕日韩免费视频| 另类天堂视频在线观看| 亚洲自拍小视频免费观看| 国产精品一区二区三区在线播放| 庆余年2免费日韩剧观看大牛| 久久久精品欧美| 亚洲欧美中文日韩在线v日本| 国产精品一区二区久久| 在线观看久久久久久| 91精品国产777在线观看| 亚洲精品自拍偷拍| 国产日韩欧美日韩| 国产精品一区专区欧美日韩| 怡红院精品视频| 日韩精品高清视频| 欧美精品日韩三级| 国产亚洲欧洲高清一区| 国产精品海角社区在线观看| 神马国产精品影院av| 国外色69视频在线观看| 久久久中精品2020中文| 久久亚洲国产精品成人av秋霞| 亚洲美女又黄又爽在线观看| 亚洲人成亚洲人成在线观看| 欧美一级电影免费在线观看| 欧亚精品在线观看| 欧美裸体xxxx极品少妇| 国产精品久久久久久久久久久不卡| 国产日产欧美a一级在线| 欧美激情在线观看视频| 国产精品久久久| 91成人在线观看国产| 亚洲男人天堂2019| 国产在线拍偷自揄拍精品| 国产999精品久久久| 伊人久久大香线蕉av一区二区| 色偷偷88888欧美精品久久久| 国产精品久久久久不卡| 91中文字幕一区| 91精品视频在线| 久久久久久香蕉网| 国产精品女人久久久久久| 国产精品高潮呻吟视频| 日韩av一区在线观看| 日韩视频免费大全中文字幕| 亚洲国产中文字幕在线观看| 欧美日韩亚洲国产一区| 亚洲国产精品女人久久久| 欧美激情va永久在线播放| 日韩欧美aⅴ综合网站发布| 国产精品久久精品| 国产免费一区二区三区在线能观看| 2019最新中文字幕| 久久久精品欧美| 国内精品久久久久久影视8| 亚洲香蕉av在线一区二区三区| 97视频在线观看亚洲| 欧美日韩亚洲高清| 日韩的一区二区| 成人精品久久av网站| 欧洲s码亚洲m码精品一区| 日韩电影大片中文字幕| 亚洲人成网站免费播放| 久久最新资源网| 成人国产精品av| 精品久久久久久中文字幕大豆网| 超碰91人人草人人干| 国产亚洲一级高清| 福利二区91精品bt7086| 亚洲人成电影网站| 国自产精品手机在线观看视频| 精品偷拍各种wc美女嘘嘘| 国产精品日本精品| 91av在线网站| 亚洲成人网av| 日韩国产精品视频| 日韩av在线最新| 国模gogo一区二区大胆私拍| 亚洲精品一区二区三区婷婷月| 亚洲香蕉伊综合在人在线视看| 亚洲欧美一区二区三区久久| 国产va免费精品高清在线| 久久免费在线观看| 欧美日韩另类视频| 国产精品成av人在线视午夜片| 最近更新的2019中文字幕| 久久精品国产96久久久香蕉| 成人两性免费视频| 伊人久久男人天堂| 国产精品一二三在线| 久久久精品一区二区三区| 亚洲国产私拍精品国模在线观看| 国产999精品久久久| 国产亚洲成av人片在线观看桃| 亚洲精品久久久久国产| 亚洲精品乱码久久久久久金桔影视| 成人精品视频在线| 国产97人人超碰caoprom| 亚洲美女av黄| 欧美激情欧美狂野欧美精品| 久久久精品网站| 欧美日韩在线免费| 欧美中文字幕视频在线观看| 日韩电影中文 亚洲精品乱码| 另类专区欧美制服同性| 日韩中文在线观看| 成人激情在线观看| 欧美一区二区三区……| 日韩成人免费视频| 国产一区二区丝袜高跟鞋图片| 欧美日韩国产精品一区二区三区四区| 亚洲午夜久久久久久久| 亚洲综合成人婷婷小说| 亚洲最大福利网| 亚洲精品98久久久久久中文字幕| 久久亚洲精品中文字幕冲田杏梨| 91欧美精品午夜性色福利在线| 日韩中文有码在线视频| 日韩网站免费观看| 精品中文视频在线| 亚洲在线视频观看| 国自在线精品视频| 另类天堂视频在线观看| 国产精品入口福利| 这里只有精品视频在线| 日韩一级裸体免费视频| 日韩中文字幕欧美| www.久久撸.com| 久久久久久久999精品视频|