日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用 Drools 规则引擎实现业务逻辑,可调试drl文件

發布時間:2024/4/17 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用 Drools 规则引擎实现业务逻辑,可调试drl文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?http://www.srcsky.com/tech/arts/389.html

代碼下載http://download.csdn.net/detail/zhy011525/2462313

?

  • 使用 Drools 規則引擎實現業務邏輯

  • 時間:2010-04-02來源:ibm作者:Ricardo閱讀:0 次字體:[ 大中 小 ]
  •   要求施加在當今軟件產品上的大多數復雜性是行為和功能方面的,從而導致組件實現具有復雜的業務邏輯。實現 J2EE 或 J2SE 應用程序中業務邏輯最常見的方法是編寫 Java 代碼來實現需求文檔的規則和邏輯。在大多數情況下,該代碼的錯綜復雜性使得維護和更新應用程序的業務邏輯成為一項令人畏懼的任務,甚至對于經驗豐富的開發人員來說也是如此。任何更改,不管多么簡單,仍然會產生重編譯和重部署成本。

      規則引擎試圖解決(或者至少降低)應用程序業務邏輯的開發和維護中固有的問題和困難。可以將規則引擎看作實現復雜業務邏輯的框架。大多數規則引擎允許您使用聲明性編程來表達對于某些給定信息或知識有效的結果。您可以專注于已知為真的事實及其結果,也就是應用程序的業務邏輯。

      有多個規則引擎可供使用,其中包括商業和開放源碼選擇。商業規則引擎通常允許使用專用的類似英語的語言來表達規則。其他規則引擎允許使用腳本語言(比如 Groovy 或 Python)編寫規則。這篇更新的文章為您介紹 Drools 引擎,并使用示例程序幫助您理解如何使用 Drools 作為 Java 應用程序中業務邏輯層的一部分。

      更多事情在變化……

      俗話說得好,“惟一不變的是變化。”軟件應用程序的業務邏輯正是如此。出于以下原因,實現應用程序業務邏輯的組件可能必須更改:

      在開發期間或部署后修復代碼缺陷

      應付特殊狀況,即客戶一開始沒有提到要將業務邏輯考慮在內

      處理客戶已更改的業務目標

      符合組織對敏捷或迭代開發過程的使用

      如果存在這些可能性,則迫切需要一個無需太多復雜性就能處理業務邏輯更改的應用程序,尤其是當更改復雜 if-else 邏輯的開發人員并不是以前編寫代碼的開發人員時。

      Drools 是用 Java 語言編寫的開放源碼規則引擎,使用 Rete 算法對所編寫的規則求值。Drools 允許使用聲明方式表達業務邏輯。可以使用非 XML 的本地語言編寫規則,從而便于學習和理解。并且,還可以將 Java 代碼直接嵌入到規則文件中,這令 Drools 的學習更加吸引人。Drools 還具有其他優點:

      非常活躍的社區支持

      易用

      快速的執行速度

      在 Java 開發人員中流行

      與 Java Rule Engine API(JSR 94)兼容

      免費

      當前 Drools 版本

      在編寫本文之際,Drools 規則引擎的最新版本是 4.0.4。這是一個重要更新。雖然現在還存在一些向后兼容性問題,但這個版本的特性讓 Drools 比以前更有吸引力。例如,用于表達規則的新的本地語言比舊版本使用的 XML 格式更簡單,更優雅。這種新語言所需的代碼更少,并且格式易于閱讀。

      另一個值得注意的進步是,新版本提供了用于 Eclipse IDE(Versions 3.2 和 3.3)的一個 Drools 插件。我強烈建議您通過這個插件來使用 Drools。它可以簡化使用 Drools 的項目開發,并且可以提高生產率。例如,該插件會檢查規則文件是否有語法錯誤,并提供代碼完成功能。它還使您可以調試規則文件,將調試時間從數小時減少到幾分鐘。您可以在規則文件中添加斷點,以便在規則執行期間的特定時刻檢查對象的狀態。這使您可以獲得關于規則引擎在特定時刻所處理的知識(knowledge)(在本文的后面您將熟悉這個術語)的信息。

      要解決的問題

      本文展示如何使用 Drools 作為示例 Java 應用程序中業務邏輯層的一部分。為了理解本文,您應該熟悉使用 Eclipse IDE 開發和調試 Java 代碼。并且,您還應該熟悉 JUnit 測試框架,并知道如何在 Eclipse 中使用它。

      下列假設為應用程序解決的虛構問題設置了場景:

      名為 XYZ 的公司構建兩種類型的計算機機器:Type1 和 Type2。機器類型按其架構定義。

      XYZ 計算機可以提供多種功能。當前定義了四種功能:DDNS Server、DNS Server、Gateway 和 Router。

      在發運每臺機器之前,XYZ 在其上執行多個測試。

      在每臺機器上執行的測試取決于每臺機器的類型和功能。目前,定義了五種測試:Test1、Test2、Test3、Test4 和 Test5。

      當將測試分配給一臺計算機時,也將測試到期日期 分配給該機器。分配給計算機的測試不能晚于該到期日期執行。到期日期值取決于分配給機器的測試。

      XYZ 使用可以確定機器類型和功能的內部開發的軟件應用程序,自動化了執行測試時的大部分過程。然后,基于這些屬性,應用程序確定要執行的測試及其到期日期。

      目前,為計算機分配測試和測試到期日期的邏輯是該應用程序的已編譯代碼的一部分。包含該邏輯的組件用 Java 語言編寫。

      分配測試和到期日期的邏輯一個月更改多次。當開發人員需要使用 Java 代碼實現該邏輯時,必須經歷一個冗長乏味的過程。

      何時使用規則引擎

      并非所有應用程序都應使用規則引擎。如果業務邏輯代碼包括很多 if-else 語句,則應考慮使用一個規則引擎。維護復雜的 Boolean 邏輯可能是非常困難的任務,而規則引擎可以幫助您組織該邏輯。當您可以使用聲明方法而非命令編程語言表達邏輯時,變化引入錯誤的可能性會大大降低。

      如果代碼變化可能導致大量的財政損失,則也應考慮規則引擎。許多組織在將已編譯代碼部署到托管環境中時具有嚴格的規則。例如,如果需要修改 Java 類中的邏輯,在更改進入生產環境之前,將會經歷一個冗長乏味的過程:

      必須重新編譯應用程序代碼。

      在測試中轉環境中刪除代碼。

      由數據質量審核員檢查代碼。

      由托管環境架構師批準更改。

      計劃代碼部署。

      即使對一行代碼的簡單更改也可能花費組織的幾千美元。如果需要遵循這些嚴格規則并且發現您頻繁更改業務邏輯代碼,則非常有必要考慮使用規則引擎。

      對客戶的了解也是該決策的一個因素。盡管您使用的是一個簡單的需求集合,只需 Java 代碼中的簡單實現,但是您可能從上一個項目得知,您的客戶具有在開發周期期間甚至部署之后添加和更改業務邏輯需求的傾向(以及財政和政治資源)。如果從一開始就選擇使用規則引擎,您可能會過得舒服一些。

      因為在對為計算機分配測試和到期日期的邏輯進行更改時,公司會發生高額成本,所以 XYZ 主管已經要求軟件工程師尋找一種靈活的方法,用最少的代價將對業務規則的更改 “推” 至生產環境。于是 Drools 走上舞臺了。工程師決定,如果它們使用規則引擎來表達確定哪些測試應該執行的規則,則可以節省更多時間和精力。他們將只需要更改規則文件的內容,然后在生產環境中替換該文件。對于他們來說,這比更改已編譯代碼并在將已編譯代碼部署到生產環境中時進行由組織強制的冗長過程要簡單省時得多(參閱側欄 何時使用規則引擎)。

      目前,在為機器分配測試和到期日期時必須遵循以下業務規則:

      如果計算機是 Type1,則只能在其上執行 Test1、Test2 和 Test5。

      如果計算機是 Type2 且其中一個功能為 DNS Server,則應執行 Test4 和 Test5。

      如果計算機是 Type2 且其中一個功能為 DDNS Server,則應執行 Test2 和 Test3。

      如果計算機是 Type2 且其中一個功能為 Gateway,則應執行 Test3 和 Test4。

      如果計算機是 Type2 且其中一個功能為 Router,則應執行 Test1 和 Test3。

      如果 Test1 是要在計算機上執行的測試之一,則測試到期日期距離機器的創建日期 3 天。該規則優先于測試到期日期的所有下列規則。

      如果 Test2 是要在計算機上執行的測試之一,則測試到期日期距離機器的創建日期 7 天。該規則優先于測試到期日期的所有下列規則。

      如果 Test3 是要在計算機上執行的測試之一,則測試到期日期距離機器的創建日期 10 天。該規則優先于測試到期日期的所有下列規則。

      如果 Test4 是要在計算機上執行的測試之一,則測試到期日期距離機器的創建日期 12 天。該規則優先于測試到期日期的所有下列規則。

      如果 Test5 是要在計算機上執行的測試之一,則測試到期日期距離機器的創建日期 14 天。

      捕獲為機器分配測試和測試到期日期的上述業務規則的當前 Java 代碼如清單 1 所示:

    清單 1. 使用 if-else 語句實現業務規則邏輯

    Machine machine = ... 
    // Assign tests 
    Collections.sort(machine.getFunctions()); 
    int index; 
     
    if (machine.getType().equals("Type1")) { 
      Test test1 = ... 
      Test test2 = ... 
      Test test5 = ... 
      machine.getTests().add(test1); 
      machine.getTests().add(test2); 
      machine.getTests().add(test5); 
    } else if (machine.getType().equals("Type2")) { 
      index = Collections.binarySearch(machine.getFunctions(), "Router"); 
      if (index >= 0) { 
       Test test1 = ... 
       Test test3 = ... 
       machine.getTests().add(test1); 
       machine.getTests().add(test3); 
      } 
      index = Collections.binarySearch(machine.getFunctions(), "Gateway"); 
      if (index >= 0) { 
       Test test4 = ... 
       Test test3 = ... 
       machine.getTests().add(test4); 
       machine.getTests().add(test3); 
      } 
    ... 
    } 
     
    // Assign tests due date 
    Collections.sort(machine.getTests(), new TestComparator()); 
    ... 
    Test test1 = ... 
    index = Collections.binarySearch(machine.getTests(), test1); 
    if (index >= 0) { 
      // Set due date to 3 days after Machine was created 
      Timestamp creationTs = machine.getCreationTs(); 
      machine.setTestsDueTime(...); 
      return; 
    } 
     
    index = Collections.binarySearch(machine.getTests(), test2); 
    if (index >= 0) { 
      // Set due date to 7 days after Machine was created 
      Timestamp creationTs = machine.getCreationTs(); 
      machine.setTestsDueTime(...); 
      return; 
    } 
    ... 

      清單 1 中的代碼不是太復雜,但也并不簡單。如果要對其進行更改,需要十分小心。一堆互相纏繞的 if-else 語句正試圖捕獲已經為應用程序標識的業務邏輯。如果您對業務規則不甚了解,就無法一眼看出代碼的意圖。

      導入示例程序

      使用 Drools 規則的示例程序附帶在本文的 ZIP 存檔中。程序使用 Drools 規則文件以聲明方法表示上一節定義的業務規則。它包含一個 Eclipse 3.2 Java 項目,該項目是使用 Drools 插件和 4.0.4 版的 Drools 規則引擎開發的。請遵循以下步驟設置示例程序:

      下載 ZIP 存檔(參見 下載)。

      下載并安裝 Drools Eclipse 插件。

      在 Eclipse 中,選擇該選項以導入 Existing Projects into Workspace,如圖 1 所示:

    圖 1. 將示例程序導入到 Eclipse 工作區


      然后選擇下載的存檔文件并將其導入工作區中。您將在工作區中發現一個名為 DroolsDemo 的新 Java 項目,如圖 2 所示:

    圖 2. 導入到工作區中的示例程序


      如果啟用了 Build automatically 選項,則代碼應該已編譯并可供使用。如果未啟用該選項,則現在構建 DroolsDemo 項目。

      檢查代碼

      現在來看一下示例程序中的代碼。該程序的 Java 類的核心集合位于 demo 包中。在該包中可以找到 Machine 和 Test 域對象類。Machine 類的實例表示要分配測試和測試到期日期的計算機機器。下面來看 Machine 類,如清單 2 所示:

    清單 2. Machine 類的實例變量

    public class Machine { 
     
      private String type; 
      private List functions = new ArrayList(); 
      private String serialNumber; 
      private Collection tests = new HashSet(); 
      private Timestamp creationTs; 
      private Timestamp testsDueTime; 
     
      public Machine() { 
       super(); 
       this.creationTs = new Timestamp(System.currentTimeMillis()); 
      } 
      ... 

      在清單 2 中可以看到 Machine 類的屬性有:

      type(表示為 string 屬性)—— 保存機器的類型值。

      functions (表示為 list)—— 保存機器的功能。

      testsDueTime (表示為 timestamp 變量)—— 保存分配的測試到期日期值。

      tests (Collection 對象)—— 保存分配的測試集合。

      注意,可以為機器分配多個測試,而且一個機器可以具有一個或多個功能。

      出于簡潔目的,機器的創建日期值設置為創建 Machine 類的實例時的當前時間。如果這是真實的應用程序,創建時間將設置為機器最終構建完成并準備測試的實際時間。

      Test 類的實例表示可以分配給機器的測試。Test實例由其 id 和 name 惟一描述,如清單 3 所示:

    清單 3. Test 類的實例變量

    public class Test { 
     
      public static Integer TEST1 = new Integer(1); 
      public static Integer TEST2 = new Integer(2); 
      public static Integer TEST3 = new Integer(3); 
      public static Integer TEST4 = new Integer(4); 
      public static Integer TEST5 = new Integer(5); 
     
      private Integer id; 
      private String name; 
      private String description; 
      public Test() { 
       super(); 
      } 
      ... 

      示例程序使用 Drools 規則引擎對 Machine 類的實例求值。基于 Machine 實例的 type 和 functions 屬性的值,規則引擎確定應分配給 tests 和 testsDueTime 屬性的值。

      在 demo 包中,還會發現 Test 對象的數據訪問對象 (TestDAOImpl) 的實現,它允許您按照 ID 查找 Test 實例。該數據訪問對象極其簡單;它不連接任何外部資源(比如關系數據庫)以獲得 Test 實例。相反,在其定義中硬編碼了預定義的 Test 實例集合。在現實世界中,您可能會具有連接外部資源以檢索 Test 對象的數據訪問對象。

      RulesEngine 類

      demo 中比較重要(如果不是最重要的)的一個類是 RulesEngine 類。該類的實例用作封裝邏輯以訪問 Drools 類的包裝器對象。可以在您自己的 Java 項目中容易地重用該類,因為它所包含的邏輯不是特定于示例程序的。清單 4 展示了該類的屬性和構造函數:

    清單 4. RulesEngine 類的實例變量和構造函數

    public class RulesEngine { 
     
      private RuleBase rules; 
      private boolean debug = false; 
     
      public RulesEngine(String rulesFile) throws RulesEngineException { 
       super(); 
       try { 
         // Read in the rules source file 
         Reader source = new InputStreamReader(RulesEngine.class 
          .getResourceAsStream("/" + rulesFile)); 
         // Use package builder to build up a rule package 
         PackageBuilder builder = new PackageBuilder(); 
         // This parses and compiles in one step 
         builder.addPackageFromDrl(source); 
         // Get the compiled package 
         Package pkg = builder.getPackage(); 
         // Add the package to a rulebase (deploy the rule package). 
         rules = RuleBaseFactory.newRuleBase(); 
         rules.addPackage(pkg); 
       } catch (Exception e) { 
         throw new RulesEngineException( 
          "Could not load/compile rules file: " + rulesFile, e); 
       } 
      } 
      ... 

      在清單 4 中可以看到,RulesEngine 類的構造函數接受字符串值形式的參數,該值表示包含業務規則集合的文件的名稱。該構造函數使用 PackageBuilder 類的實例解析和編譯源文件中包含的規則。(注意: 該代碼假設規則文件位于程序類路徑中名為 rules 的文件夾中。)然后,使用 PackageBuilder 實例將所有編譯好的規則合并為一個二進制 Package 實例。然后,使用這個實例配置 Drools RuleBase 類的一個實例,后者被分配給 RulesEngine 類的 rules 屬性。可以將這個類的實例看作規則文件中所包含規則的內存中表示。

      清單 5 展示了 RulesEngine 類的 executeRules() 方法:

    清單 5. RulesEngine 類的 executeRules() 方法

    public void executeRules(WorkingEnvironmentCallback callback) { 
      WorkingMemory workingMemory = rules.newStatefulSession(); 
      if (debug) { 
       workingMemory 
         .addEventListener(new DebugWorkingMemoryEventListener()); 
      } 
      callback.initEnvironment(workingMemory); 
      workingMemory.fireAllRules(); 
    } 

      executeRules() 方法幾乎包含了 Java 代碼中的所有魔力。調用該方法執行先前加載到類構造函數中的規則。Drools WorkingMemory 類的實例用于斷言或聲明知識,規則引擎應使用它來確定應執行的結果。(如果滿足規則的所有條件,則執行該規則的結果。)將知識當作規則引擎用于確定是否應啟動規則的數據或信息。例如,規則引擎的知識可以包含一個或多個對象及其屬性的當前狀態。

      規則結果在調用 WorkingMemory 對象的 fireAllRules() 方法時執行。您可能奇怪(我希望您如此)知識是如何插入到 WorkingMemory 實例中的。如果仔細看一下該方法的簽名,將會注意到所傳遞的參數是 WorkingEnvironmentCallback 接口的實例。executeRules() 方法的調用者需要創建實現該接口的對象。該接口只需要開發人員實現一個方法(參見清單 6 ):

    清單 6. WorkingEnvironmentCallback 接口

    public interface WorkingEnvironmentCallback { 
      void initEnvironment(WorkingMemory workingMemory) throws FactException; 
    } 

      所以,應該是 executeRules() 方法的調用者將知識插入到 WorkingMemory 實例中的。稍后將展示這是如何實現的。

      TestsRulesEngine 類

      清單 7 展示了 TestsRulesEngine 類,它也位于 demo 包中:

    清單 7. TestsRulesEngine 類

    public class TestsRulesEngine { 
     
      private RulesEngine rulesEngine; 
      private TestDAO testDAO; 
     
      public TestsRulesEngine(TestDAO testDAO) throws RulesEngineException { 
       super(); 
       rulesEngine = new RulesEngine("testRules1.drl"); 
       this.testDAO = testDAO; 
      } 
     
      public void assignTests(final Machine machine) { 
       rulesEngine.executeRules(new WorkingEnvironmentCallback() { 
         public void initEnvironment(WorkingMemory workingMemory) { 
          // Set globals first before asserting/inserting any knowledge! 
          workingMemory.setGlobal("testDAO", testDAO); 
          workingMemory.insert(machine); 
         }; 
       }); 
      } 
    } 

      TestsRulesEngine 類只有兩個實例變量。rulesEngine 屬性是 RulesEngine 類的實例。 testDAO 屬性保存對 TestDAO 接口的具體實現的引用。 rulesEngine 對象是使用 "testRules1.drl" 字符串作為其構造函數的參數實例化的。testRules1.drl 文件以聲明方式捕獲 要解決的問題 中的業務規則。 TestsRulesEngine 類的 assignTests() 方法調用 RulesEngine 類的 executeRules() 方法。在這個方法中,創建了 WorkingEnvironmentCallback 接口的一個匿名實例,然后將該實例作為參數傳遞給 executeRules() 方法。

      如果查看 assignTests() 方法的實現,可以看到知識是如何插入到 WorkingMemory 實例中的。 WorkingMemory 類的 insert() 方法被調用以聲明在對規則求值時規則引擎應使用的知識。在這種情況下,知識由 Machine 類的一個實例組成。被插入的對象用于對規則的條件求值。

      如果在對條件求值時,需要讓規則引擎引用未 用作知識的對象,則應使用 WorkingMemory 類的 setGlobal() 方法。在示例程序中,setGlobal() 方法將對 TestDAO 實例的引用傳遞給規則引擎。然后規則引擎使用 TestDAO 實例查找它可能需要的任何 Test 實例。

      TestsRulesEngine 類是示例程序中惟一的 Java 代碼,它包含專門致力于為機器分配測試和測試到期日期的實現的邏輯。該類中的邏輯永遠不需要更改,即使業務規則需要更新時也是如此。

      Drools 規則文件

      如前所述,testRules.xml 文件包含規則引擎為機器分配測試和測試到期日期所遵循的規則。它使用 Drools 本地語言表達所包含的規則。

      Drools 規則文件有一個或多個 rule 聲明。每個 rule 聲明由一個或多個 conditional 元素以及要執行的一個或多個 consequences 或 actions 組成。一個規則文件還可以有多個(即 0 個或多個)import 聲明、多個 global 聲明以及多個 function 聲明。

      理解 Drools 規則文件組成最好的方法是查看一個真正的規則文件。下面來看 testRules1.drl 文件的第一部分,如清單 8 所示:

    清單 8. testRules1.drl 文件的第一部分

    package demo; 
     
    import demo.Machine; 
    import demo.Test; 
    import demo.TestDAO; 
    import java.util.Calendar; 
    import java.sql.Timestamp; 
    global TestDAO testDAO; 

      在清單 8 中,可以看到 import 聲明如何讓規則執行引擎知道在哪里查找將在規則中使用的對象的類定義。global 聲明讓規則引擎知道,某個對象應該可以從規則中訪問,但該對象不應是用于對規則條件求值的知識的一部分。可以將 global 聲明看作規則中的全局變量。對于 global 聲明,需要指定它的類型(即類名)和想要用于引用它的標識符(即變量名)。global 聲明中的這個標識符名稱應該與調用 WorkingMemory 類的 setGlobal() 方法時使用的標識符值匹配,在此即為 testDAO (參見 清單 7)。

      function 關鍵詞用于定義一個 Java 函數(參見 清單 9)。如果看到 consequence(稍后將討論)中重復的代碼,則應該提取該代碼并將其編寫為一個 Java 函數。但是,這樣做時要小心,避免在 Drools 規則文件中編寫復雜的 Java 代碼。規則文件中定義的 Java 函數應該簡短易懂。這不是 Drools 的技術限制。如果想要在規則文件中編寫復雜的 Java 代碼,也可以。但這樣做可能會讓您的代碼更加難以測試、調試和維護。復雜的 Java 代碼應該是 Java 類的一部分。如果需要 Drools 規則執行引擎調用復雜的 Java 代碼,則可以將對包含復雜代碼的 Java 類的引用作為全局數據傳遞給規則引擎。

    清單 9. testRules1.drl 文件中定義的 Java 函數

    function void setTestsDueTime(Machine machine, int numberOfDays) { 
      setDueTime(machine, Calendar.DATE, numberOfDays); 
    } 
     
    function void setDueTime(Machine machine, int field, int amount) { 
      Calendar calendar = Calendar.getInstance(); 
      calendar.setTime(machine.getCreationTs()); 
      calendar.add(field, amount); 
      machine.setTestsDueTime(new Timestamp(calendar.getTimeInMillis())); 
    } 
     ... 

      清單 10 展示了 testRules1.drl 文件中定義的第一個規則:

    清單 10. testRules1.drl 中定義的第一個規則

    rule "Tests for type1 machine" 
    salience 100 
    when 
      machine : Machine( type == "Type1" ) 
    then 
      Test test1 = testDAO.findByKey(Test.TEST1); 
      Test test2 = testDAO.findByKey(Test.TEST2); 
      Test test5 = testDAO.findByKey(Test.TEST5); 
      machine.getTests().add(test1); 
      machine.getTests().add(test2); 
      machine.getTests().add(test5); 
      insert( test1 ); 
      insert( test2 ); 
      insert( test5 ); 
    end 

      如清單 10 所示,rule 聲明有一個惟一標識它的 name。還可以看到,when 關鍵詞定義規則中的條件塊,then 關鍵詞定義結果塊。清單 10 中顯示的規則有一個引用 Machine 對象的條件元素。如果回到 清單 7 可以看到, Machine 對象被插入到 WorkingMemory 對象中。這正是這個規則中使用的對象。條件元素對 Machine 實例(知識的一部分)求值,以確定是否應執行規則的結果。如果條件元素等于 true,則啟動或執行結果。從清單 10 中還可以看出,結果只不過是一個 Java 語言語句。通過快速瀏覽該規則,可以很容易地識別出這是下列業務規則的實現:

      如果計算機是 Type1,則只能在該機器上執行 Test1、Test2 和 Test5。

      因此,該規則的條件元素檢查( Machine 對象的) type 屬性是否為 Type1。 (在條件元素中,只要對象遵從 Java bean 模式,就可以直接訪問對象的屬性,而不必調用 getter 方法。)如果該屬性的值為 true,那么將 Machine 實例的一個引用分配給 machine 標識符。然后,在規則的結果塊使用該引用,將測試分配給 Machine 對象。

      在該規則中,惟一看上去有些奇怪的語句是最后三條結果語句。回憶 “要解決的問題” 小節中的業務規則,應該分配為測試到期日期的值取決于分配給機器的測試。因此,分配給機器的測試需要成為規則執行引擎在對規則求值時所使用的知識的一部分。這正是這三條語句的作用。這些語句使用一個名為 insert 的方法更新規則引擎中的知識。

      確定規則執行順序

      規則的另一個重要的方面是可選的 salience 屬性。使用它可以讓規則執行引擎知道應該啟動規則的結果語句的順序。具有最高顯著值的規則的結果語句首先執行;具有第二高顯著值的規則的結果語句第二執行,依此類推。當您需要讓規則按預定義順序啟動時,這一點非常重要,很快您將會看到。

      testRules1.drl 文件中接下來的四個規則實現與機器測試分配有關的其他業務規則(參見清單 11)。這些規則與剛討論的第一個規則非常相似。注意,salience 屬性值對于前五個規則是相同的;不管這五個規則的啟動順序如何,其執行結果將相同。如果結果受規則的啟動順序影響,則需要為規則指定不同的顯著值。

    清單 11. testRules1.drl 文件中與測試分配有關的其他規則

    rule "Tests for type2, DNS server machine" 
    salience 100 
    when 
      machine : Machine( type == "Type2", functions contains "DNS Server") 
    then 
      Test test5 = testDAO.findByKey(Test.TEST5); 
      Test test4 = testDAO.findByKey(Test.TEST4); 
      machine.getTests().add(test5); 
      machine.getTests().add(test4); 
      insert( test4 ); 
      insert( test5 ); 
    end 
     
    rule "Tests for type2, DDNS server machine" 
    salience 100 
    when 
      machine : Machine( type == "Type2", functions contains "DDNS Server") 
    then 
      Test test2 = testDAO.findByKey(Test.TEST2); 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      machine.getTests().add(test2); 
      machine.getTests().add(test3); 
      insert( test2 ); 
      insert( test3 ); 
    end 
     
    rule "Tests for type2, Gateway machine" 
    salience 100 
    when 
      machine : Machine( type == "Type2", functions contains "Gateway") 
    then 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      Test test4 = testDAO.findByKey(Test.TEST4); 
      machine.getTests().add(test3); 
      machine.getTests().add(test4); 
      insert( test3 ); 
      insert( test4 ); 
    end 
     
    rule "Tests for type2, Router machine" 
    salience 100 
    when 
      machine : Machine( type == "Type2", functions contains "Router") 
    then 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      Test test1 = testDAO.findByKey(Test.TEST1); 
      machine.getTests().add(test3); 
      machine.getTests().add(test1); 
      insert( test1 ); 
      insert( test3 ); 
    end 
    ... 

      清單 12 展示了 Drools 規則文件中的其他規則。您可能已經猜到,這些規則與測試到期日期的分配有關:

    清單 12. testRules1.drl 文件中與測試到期日期分配有關的規則

    rule "Due date for Test 5" 
    salience 50 
    when 
      machine : Machine() 
      Test( id == Test.TEST5 ) 
    then 
      setTestsDueTime(machine, 14); 
    end 
     
    rule "Due date for Test 4" 
    salience 40 
    when 
      machine : Machine() 
      Test( id == Test.TEST4 ) 
    then 
      setTestsDueTime(machine, 12); 
    end 
     
    rule "Due date for Test 3" 
    salience 30 
    when 
      machine : Machine() 
      Test( id == Test.TEST3 ) 
    then 
      setTestsDueTime(machine, 10); 
    end 
     
    rule "Due date for Test 2" 
    salience 20 
    when 
      machine : Machine() 
      Test( id == Test.TEST2 ) 
    then 
      setTestsDueTime(machine, 7); 
    end 
     
    rule "Due date for Test 1" 
    salience 10 
    when 
      machine : Machine() 
      Test( id == Test.TEST1 ) 
    then 
      setTestsDueTime(machine, 3); 
    end 

      這些規則的實現比用于分配測試的規則的實現要略微簡單一些,但我發現它們更有趣一些,原因有四。

      第一,注意這些規則的執行順序很重要。結果(即,分配給 Machine 實例的 testsDueTime 屬性的值)受這些規則的啟動順序所影響。如果查看 要解決的問題 中詳細的業務規則,您將注意到用于分配測試到期日期的規則具有優先順序。例如,如果已經將 Test3、Test4 和 Test5 分配給機器,則測試到期日期應距離機器的創建日期 10 天。原因在于 Test3 的到期日期規則優先于 Test4 和 Test5 的測試到期日期規則。如何在 Drools 規則文件中表達這一點呢答案是 salience 屬性。為 testsDueTime 屬性設置值的規則的 salience 屬性值不同。Test1 的測試到期日期規則優先于所有其他測試到期日期規則,所以這應是要啟動的最后一個規則。換句話說,如果 Test1 是分配給機器的測試之一,則由該規則分配的值應該是優先使用的值。所以,該規則的 salience 屬性值最低:10。

      第二,每個規則有兩個條件元素。第一個元素只檢查工作內存中是否存在一個 Machine 實例。(注意,這里不會對 Machine 對象的屬性進行比較。)當這個元素等于 true 時,它將一個引用分配給 Machine 對象,而后者將在規則的結果塊被用到。如果不分配這個引用,那么就無法將測試到期日期分配給 Machine 對象。第二個條件元素檢查 Test 對象的 id 屬性。當且僅當這兩個條件元素都等于 true 時,才執行規則的結果元素。

      第三,在 Test 類的一個實例成為知識的一部分(即,包含在工作內存中)之前,Drools 規則執行引擎不會(也不能)對這些規則的條件塊求值。這很符合邏輯,因為如果工作內存中還沒有 Test 類的一個實例,那么規則執行引擎就無法執行這些規則的條件中所包含的比較。如果您想知道 Test 實例何時成為知識的一部分,那么可以回憶,在與分配測試相關規則的結果的執行期間,一個或多個 Test 實例被插入到工作內存中。(參見 清單 10 和 清單 11)。

      第四,注意這些規則的結果塊相當簡短。原因在于在所有結果塊中調用了規則文件中之前使用 function 關鍵詞定義的 setTestsDueTime() Java 方法。該方法為 testsDueTime 屬性實際分配值。

      測試代碼

      既然已經仔細檢查了實現業務規則邏輯的代碼,現在應該檢查它是否能工作。要執行示例程序,運行 demo.test 中的 TestsRulesEngineTest JUnit 測試。

      在該測試中,創建了 5 個 Machine 對象,每個對象具有不同的屬性集合(序號、類型和功能)。為這五個 Machine 對象的每一個都調用 TestsRulesEngine 類的 assignTests() 方法。一旦 assignTests() 方法完成其執行,就執行斷言以驗證 testRules1.drl 中指定的業務規則邏輯是否正確(參見清單 13)。可以修改 TestsRulesEngineTest JUnit 類以多添加幾個具有不同屬性的 Machine 實例,然后使用斷言驗證結果是否跟預期一樣。

    清單 13. testTestsRulesEngine() 方法中用于驗證業務邏輯實現是否正確的斷言

    public void testTestsRulesEngine() throws Exception { 
      while (machineResultSet.next()) { 
       Machine machine = machineResultSet.getMachine(); 
       testsRulesEngine.assignTests(machine); 
       Timestamp creationTs = machine.getCreationTs(); 
       Calendar calendar = Calendar.getInstance(); 
       calendar.setTime(creationTs); 
       Timestamp testsDueTime = machine.getTestsDueTime(); 
     
       if (machine.getSerialNumber().equals("1234A")) { 
         assertEquals(3, machine.getTests().size()); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST1))); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST2))); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST5))); 
         calendar.add(Calendar.DATE, 3); 
         assertEquals(calendar.getTime(), testsDueTime); 
     
       } else if (machine.getSerialNumber().equals("1234B")) { 
         assertEquals(4, machine.getTests().size()); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST5))); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST4))); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST3))); 
         assertTrue(machine.getTests().contains(testDAO.findByKey(Test.TEST2))); 
         calendar.add(Calendar.DATE, 7); 
         assertEquals(calendar.getTime(), testsDueTime); 
    ... 

      關于知識的其他備注

      值得一提的是,除了將對象插入至工作內存之外,還可以在工作內存中修改對象或從中撤回對象。可以在規則的結果塊中進行這些操作。如果在結果語句中修改作為當前知識一部分的對象,并且所修改的屬性被用在 condition 元素中以確定是否應啟動規則,則應在結果塊中調用 update() 方法。調用 update() 方法時,您讓 Drools 規則引擎知道對象已更新且引用該對象的任何規則的任何條件元素(例如,檢查一個或多個對象屬性的值)應再次求值,以確定條件的結果現在是 true 還是 false。這意味著甚至當前活動規則(在其結果塊中修改對象的規則)的條件都可以再次求值,這可能導致規則再次啟動,并可能導致無限循環。如果不希望這種情況發生,則應該包括 rule 的可選 no-loop 屬性并將其賦值為 true。

      清單 14 用兩個規則的定義的偽代碼演示了這種情況。Rule 1 修改 objectA 的 property1。然后它調用 update() 方法,以允許規則執行引擎知道該更新,從而觸發對引用 objectA 的規則的條件元素的重新求值。因此,啟動 Rule 1 的條件應再次求值。因為該條件應再次等于 true(property2 的值仍相同,因為它在結果塊中未更改),Rule 1 應再次啟動,從而導致無限循環的執行。為了避免這種情況,添加 no-loop 屬性并將其賦值為 true,從而避免當前活動規則再次執行。

    清單 14. 修改工作內存中的對象并使用規則元素的 no-loop 屬性

    ... 
    rule "Rule 1" 
    salience 100 
    no-loop true 
    when 
      objectA : ClassA (property2().equals(...)) 
    then 
      Object value = ... 
      objectA.setProperty1(value); 
      update( objectA ); 
    end 
     
    rule "Rule 2" 
    salience 100 
    when 
      objectB : ClassB() 
      objectA : ClassA ( property1().equals(objectB) ) 
      ... 
    then 
      ... 
    end 
    ... 

      如果對象不再是知識的一部分,則應將該對象從工作內存中撤回(參見清單 15)。通過在結果塊中調用 retract() 方法實現這一點。當從工作內存中移除對象之后,引用該對象的(屬于任何規則的)任何條件元素將不被求值。因為對象不再作為知識的一部分存在,所以規則沒有啟動的機會。

    清單 15. 從工作內存中撤回對象

    ... 
    rule "Rule 1" 
    salience 100 
    when 
      objectB : ... 
      objectA : ... 
    then 
      Object value = ... 
      objectA.setProperty1(value); 
      retract(objectB); 
    end 
     
    rule "Rule 2" 
    salience 90 
    when 
      objectB : ClassB ( property().equals(...) ) 
    then 
     ... 
    end 
    ... 

      清單 15 包含兩個規則的定義的偽代碼。假設啟動兩個規則的條件等于 true。則應該首先啟動 Rule 1,因為 Rule 1 的顯著值比 Rule 2 的高。現在,注意在 Rule 1 的結果塊中,objectB 從工作內存中撤回(也就是說,objectB 不再是知識的一部分)。該動作更改了規則引擎的 “執行日程”,因為現在將不啟動 Rule 2。原因在于曾經為真值的用于啟動 Rule 2 的條件不再為真,因為它引用了一個不再是知識的一部分的對象(objectB)。如果清單 15 中還有其他規則引用了 objectB,且這些規則尚未啟動,則它們將不會再啟動了。

      作為關于如何修改工作內存中當前知識的具體例子,我將重新編寫前面討論的規則源文件。業務規則仍然與 “要解決的問題” 小節中列出的一樣。但是,我將使用這些規則的不同實現取得相同的結果。按照這種方法,任何時候工作內存中惟一可用的知識是 Machine 實例。換句話說,規則的條件元素將只針對 Machine 對象的屬性執行比較。這與之前的方法有所不同,之前的方法還要對 Test 對象的屬性進行比較(參見 清單 12)。 這些規則的新實現被捕獲在示例應用程序的 testRules2.drl 文件中。清單 16 展示了 testRules2.drl 中與分配測試相關的規則:

    清單 16. testRules2.drl 中與分配測試相關的規則

    rule "Tests for type1 machine" 
    lock-on-active true 
    salience 100 
     
    when 
      machine : Machine( type == "Type1" ) 
    then 
      Test test1 = testDAO.findByKey(Test.TEST1); 
      Test test2 = testDAO.findByKey(Test.TEST2); 
      Test test5 = testDAO.findByKey(Test.TEST5); 
      machine.getTests().add(test1); 
      machine.getTests().add(test2); 
      machine.getTests().add(test5); 
      update( machine ); 
    end 
     
    rule "Tests for type2, DNS server machine" 
    lock-on-active true 
    salience 100 
     
    when 
      machine : Machine( type == "Type2", functions contains "DNS Server") 
    then 
      Test test5 = testDAO.findByKey(Test.TEST5); 
      Test test4 = testDAO.findByKey(Test.TEST4); 
      machine.getTests().add(test5); 
      machine.getTests().add(test4); 
      update( machine ); 
    end 
     
    rule "Tests for type2, DDNS server machine" 
    lock-on-active true 
    salience 100 
     
    when 
      machine : Machine( type == "Type2", functions contains "DDNS Server") 
    then 
      Test test2 = testDAO.findByKey(Test.TEST2); 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      machine.getTests().add(test2); 
      machine.getTests().add(test3); 
      update( machine ); 
    end 
     
    rule "Tests for type2, Gateway machine" 
    lock-on-active true 
    salience 100 
     
    when 
      machine : Machine( type == "Type2", functions contains "Gateway") 
    then 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      Test test4 = testDAO.findByKey(Test.TEST4); 
      machine.getTests().add(test3); 
      machine.getTests().add(test4); 
      update( machine ); 
    end 
     
    rule "Tests for type2, Router machine" 
    lock-on-active true 
    salience 100 
     
    when 
      machine : Machine( type == "Type2", functions contains "Router") 
    then 
      Test test3 = testDAO.findByKey(Test.TEST3); 
      Test test1 = testDAO.findByKey(Test.TEST1); 
      machine.getTests().add(test3); 
      machine.getTests().add(test1); 
      update( machine ); 
    end 
    ... 

      如果將清單 16 中第一個規則的定義與 清單 10 中的定義相比較,可以看到,新方法沒有將分配給 Machine 對象的 Test 實例插入到工作內存中,而是由規則的結果塊調用 update() 方法,讓規則引擎知道 Machine 對象已被修改。(Test 實例被添加/指定給它。) 如果看看清單 16 中其他的規則,應該可以看到,每當將測試分配給一個 Machine 對象時,都采用這種方法:一個或多個 Test 實例被分配給一個 Machine 實例,然后,修改工作知識,并通知規則引擎。

      還應注意清單 16 中使用的 active-lock 屬性。該屬性的值被設為 true;如果不是這樣,在執行這些規則時將陷入無限循環。將它設為 true 可以確保當一個規則更新工作內存中的知識時,最終不會導致對規則重新求值并重新執行規則,也就不會導致無限循環。可以將 active-lock 屬性 看作 no-loop 屬性的加強版。 no-loop 屬性確保當修改知識的規則更新后不會再被調用,而 active-lock 屬性則確保在修改知識以后,文件中的任何規則(其 active-lock 屬性被設為 true)不會重新執行。

      清單 17 展示了其他規則有何更改:

    清單 17. testRules2.drl 中與分配測試到期日期有關的規則

    rule "Due date for Test 5" 
    salience 50 
    when 
      machine : Machine(tests contains (testDAO.findByKey(Test.TEST5))) 
    then 
      setTestsDueTime(machine, 14); 
    end 
     
    rule "Due date for Test 4" 
    salience 40 
    when 
      machine : Machine(tests contains (testDAO.findByKey(Test.TEST4))) 
    then 
      setTestsDueTime(machine, 12); 
    end 
     
    rule "Due date for Test 3" 
    salience 30 
    when 
      machine : Machine(tests contains (testDAO.findByKey(Test.TEST3))) 
    then 
      setTestsDueTime(machine, 10); 
    end 
     
    rule "Due date for Test 2" 
    salience 20 
    when 
      machine : Machine(tests contains (testDAO.findByKey(Test.TEST2))) 
    then 
      setTestsDueTime(machine, 7); 
    end 
     
    rule "Due date for Test 1" 
    salience 10 
    when 
      machine : Machine(tests contains (testDAO.findByKey(Test.TEST1))) 
    then 
      setTestsDueTime(machine, 3); 
    end 

      這些規則的條件元素現在檢查一個 Machine 對象的 tests 集合,以確定它是否包含特定的 Test 實例。因此,如前所述,按照這種方法,規則引擎只處理工作內存中的一個對象(一個 Machine 實例),而不是多個對象(Machine 和 Test 實例)。

      要測試 testRules2.drl 文件,只需編輯示例應用程序提供的 TestsRulesEngine 類(參見 清單 7):將 "testRules1.drl" 字符串改為 "testRules2.drl",然后運行 TestsRulesEngineTest JUnit 測試。所有測試都應該成功,就像將 testRules1.drl 作為規則源一樣。

      關于斷點的注意事項

      如前所述,用于 Eclipse 的 Drools 插件允許在規則文件中設置斷點。要清楚,只有在調試作為 “Drools Application” 的程序時,才會啟用這些斷點。否則,調試器會忽略它們。

      例如,假設您想調試作為 “Drools Application” 的 TestsRulesEngineTest JUnit 測試類。在 Eclipse 中打開常見的 Debug 對話框。在這個對話框中,應該可以看到一個 “Drools Application” 類別。在這個類別下,創建一個新的啟動配置。在這個新配置的 Main 選項卡中,應該可以看到一個 Project 字段和一個 Main class 字段。對于 Project 字段,選擇 Drools4Demo 項目。對于 Main class 字段,輸入 junit.textui.TestRunner(參見圖 3)。

    圖 3. TestsRulesEngineTest 類的 Drools application 啟動配置(Main 選項卡)

      查看原圖(大圖)

      現在選擇 Arguments 選項卡并輸入 -t demo.test.TestsRulesEngineTest 作為程序參數(參見圖 4)。輸入該參數后,單擊對話框右下角的 Apply 按鈕,保存新的啟動配置。然后,可以單擊 Debug 按鈕,開始以 “Drools Application” 的形式調試 TestsRulesEngineTest JUnit 類。如果之前在 testRules1.drl 或 testRules2.drl 中添加了斷點,那么當使用這個啟動配置時,調試器應該會在遇到這些斷點時停下來。

    圖 4. TestsRulesEngineTest 類的 Drools Application 啟動配置(Arguments 選項卡)

      查看原圖(大圖)

      結束語

      使用規則引擎可以顯著降低實現 Java 應用程序中業務規則邏輯的組件的復雜性。使用規則引擎以聲明方法表達規則的應用程序比其他應用程序更容易維護和擴展。正如您所看到的,Drools 是一種功能強大的靈活的規則引擎實現。使用 Drools 的特性和能力,您應該能夠以聲明方式實現應用程序的復雜業務邏輯。Drools 使得學習和使用聲明式編程對于 Java 開發人員來說相當容易。

      本文展示的 Drools 類是特定于 Drools 的。如果要在示例程序中使用另一種規則引擎實現,代碼需要作少許更改。因為 Drools 是 JSR 94 兼容的,所以可以使用 Java Rule Engine API(如 JSR 94 中所指定)設計特定于 Drools 的類的接口。(Java Rule Engine API 用于 JDBC 在數據庫中的規則引擎。)如果使用該 API,則可以無需更改 Java 代碼而將規則引擎實現更改為另一個不同的實現,只要這個不同的實現也是 JSR 94 兼容的。JSR 94 不解析包含業務規則的規則文件(在本文示例應用程序中為 testRules1.drl)的結構。文件的結構將仍取決于您選擇的規則引擎實現。作為練習,可以修改示例程序以使它使用 Java Rule Engine API,而不是使用 Java 代碼引用特定于 Drools 的類。

       本文示例源代碼或素材下載

?

總結

以上是生活随笔為你收集整理的使用 Drools 规则引擎实现业务逻辑,可调试drl文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

综合久久久久久 | 超碰在线97观看 | 在线免费观看视频一区二区三区 | 国产亚洲成人网 | 国产精品女主播一区二区三区 | 黄色不卡av | 就操操久久 | 九九热1 | www.黄色小说.com | 免费电影一区二区三区 | 国产一区二区免费 | a级一a一级在线观看 | 免费a一级 | 中文字幕第一页在线播放 | 亚洲综合视频在线播放 | av看片在线 | 国产99久久精品一区二区永久免费 | 91理论电影 | 成人影片在线免费观看 | 一区二区欧美激情 | 在线观看片 | 国产福利一区在线观看 | 国产精品麻豆视频 | 久久久久久99精品 | 国产精品爽爽久久久久久蜜臀 | 中文字幕网址 | 91久久奴性调教 | 四虎免费av| 中国一级片在线观看 | 午夜骚影| 91视频 - 114av| 91久久久久久久一区二区 | 久久1电影院 | 国产 日韩 在线 亚洲 字幕 中文 | 人人玩人人添人人澡97 | 日韩免费高清在线观看 | 日韩精品视频免费在线观看 | 久久男人影院 | 99精品免费久久久久久久久 | 精品国产亚洲一区二区麻豆 | 成人免费视频在线观看 | 久久女同性恋中文字幕 | 深夜免费福利网站 | 久久黄色免费 | 久久精品99国产精品日本 | 日韩一级网站 | 久久精品国产一区 | 99国内精品 | 缴情综合网五月天 | 亚洲欧美精品一区 | 国产亚洲精品久久网站 | 亚洲精品欧洲精品 | www亚洲国产 | 少妇高潮冒白浆 | 91色网址 | 午夜精品一区二区三区在线 | 99在线精品视频在线观看 | 狠狠色伊人亚洲综合网站野外 | 日本中文字幕在线观看 | 日韩精品高清不卡 | 国产在线高清视频 | 国产色视频一区二区三区qq号 | 91最新地址永久入口 | 日韩一级片大全 | 久久黄色片子 | 国产不卡精品视频 | 精品视频免费观看 | 国产精品美女久久久久久久久 | 亚洲不卡123 | 国产精品美 | 免费精品国产 | 久久久久久久av麻豆果冻 | 午夜精品99久久免费 | 国产一级久久 | 中文字幕视频观看 | 黄色一级大片免费看 | 日本性生活一级片 | 超碰电影在线观看 | 青草视频免费观看 | 精品一区久久 | 韩国视频一区二区三区 | 在线天堂中文www视软件 | 国产不卡免费av | 黄色网www| 西西444www高清大胆 | 在线日本看片免费人成视久网 | 热久久影视 | 久久国产一区 | av国产网站 | 91日韩在线 | 九九免费观看全部免费视频 | 国产视频首页 | 色在线最新 | 日韩高清一区 | 高清av网站| 国产一区在线不卡 | 国产精品自产拍 | 欧美日韩中文另类 | 国内精品久久久精品电影院 | 日日操操操 | 国产精品久久久久久久久久久免费看 | 久久一区二区三区日韩 | 免费三级a| 九九九九九精品 | 91日韩在线 | 久草在线中文视频 | 日韩欧美在线观看一区二区 | 国模精品一区二区三区 | 国产中文自拍 | 久久久久久国产一区二区三区 | 日韩精品一区二区三区在线播放 | 精品国产一区二区三区久久久蜜月 | 中文字幕制服丝袜av久久 | 91手机视频 | 天天狠狠干 | 国产伦理精品一区二区 | 91九色蝌蚪视频在线 | 天天艹天天操 | 欧美日韩精品在线观看视频 | 成人免费网站视频 | 欧美成人xxxxx | 国产精品一区二区三区99 | 久久免费精品 | 久久综合之合合综合久久 | 中文字幕一区二区三区四区在线视频 | 久久久黄视频 | 在线观看av黄色 | 天堂av在线7| 日韩精品一区二区三区水蜜桃 | 久草在线视频新 | 欧美日韩国产一区二 | 国产毛片在线 | 国产一级二级在线观看 | 久草在线视频免赞 | 国产精品福利无圣光在线一区 | 国产精品白浆视频 | 麻豆av一区二区三区在线观看 | 亚洲美女精品视频 | 亚洲精品国产第一综合99久久 | 国内精品久久久久久久久久久久 | 六月久久婷婷 | 日韩a级黄色片 | 性色av一区二区 | 久久久999免费视频 日韩网站在线 | 国产成人久久av977小说 | 91视频在线免费下载 | 国产精品观看 | 91中文字幕网 | 久久精品免费播放 | 黄色的视频 | 美女视频黄是免费的 | 香蕉视频免费在线播放 | 国产69精品久久久久久 | 久久久午夜电影 | 日本黄区免费视频观看 | av一级片 | 亚洲综合网站在线观看 | 欧美黄在线 | 国产精品久久久久久久7电影 | 久久av影视 | 国产97在线播放 | 97在线视频免费播放 | 国产一区欧美在线 | 久久久久国产精品午夜一区 | 久久99国产综合精品 | 国产视频 亚洲精品 | 精品国产一区二区三区在线观看 | 国产免费黄色 | 在线观看av网 | 日韩欧美在线第一页 | 美女中文字幕 | 国产97在线看 | 国产一区二区不卡视频 | 久久久久99精品成人片三人毛片 | 国产一区二区三区在线免费观看 | 日韩精品欧美专区 | 国产精品亚洲视频 | 国产精品久久久久久久久大全 | 日本黄色免费在线 | 亚洲天堂网视频在线观看 | 久久久wwww| 又爽又黄又刺激的视频 | www.久久色.com | 国产一区二区手机在线观看 | 婷婷夜夜 | 91精品国产91 | 亚洲影视资源 | 四虎国产永久在线精品 | 国产精品9999久久久久仙踪林 | 久草精品视频在线观看 | 精品亚洲一区二区三区 | 97人人精品 | 99免费视频 | 日韩高清在线一区二区三区 | 天天做天天爱天天爽综合网 | 亚洲成人精品在线 | 国产成人一二片 | 美女免费网视频 | 亚洲综合成人专区片 | 国产98色在线 | 日韩 | 免费手机黄色网址 | 国产精品 美女 | 激情五月网站 | 国产精品女同一区二区三区久久夜 | 99 久久久久 | 国产精品系列在线观看 | 国产成人三级一区二区在线观看一 | 天天干夜夜爽 | 日韩一区二区三区视频在线 | 免费一级片在线观看 | 欧美日韩国产精品一区二区 | 国产一区在线看 | 色国产视频 | 日韩欧美一区二区在线 | 色中色综合 | 在线免费观看国产视频 | 日韩免费在线观看视频 | 性色av免费在线观看 | 少妇超碰在线 | 久久视频免费 | 成年人在线视频观看 | 欧美性超爽| 天天操天天草 | 亚洲精品国产综合99久久夜夜嗨 | 天天操天天能 | 国产成人久久77777精品 | 97电影在线 | 日b视频在线观看网址 | 六月色播 | 日韩欧美69 | 亚洲天天摸日日摸天天欢 | 国产精品第三页 | 精品国产aⅴ麻豆 | 国产精品久久久久久妇 | 国产视频一区二区三区在线 | 四虎在线视频免费观看 | 欧美成年黄网站色视频 | av在线亚洲天堂 | 久久国产精品99久久人人澡 | 日韩免费视频观看 | 国内精品久久影院 | 精品久久久影院 | 午夜123| 亚洲精品白浆高清久久久久久 | 日韩精品久久久久久久电影99爱 | 激情网在线观看 | 婷婷综合影院 | 日韩一区在线播放 | av爱干 | 久久久久久久福利 | 亚洲精品资源在线观看 | 人人看人人艹 | 国产一级久久久 | av资源网在线播放 | 最新av在线播放 | 在线 视频 亚洲 | 奇米影视四色8888 | 极品久久久久久久 | 亚洲精品视频在线观看视频 | 视频一区在线免费观看 | 91色蜜桃 | 日韩精品视频在线免费观看 | 在线免费黄色av | 人人爽久久久噜噜噜电影 | 国产福利中文字幕 | 色婷婷视频在线观看 | 91.精品高清在线观看 | 欧美片一区二区三区 | 91试看| 国产美女无遮挡永久免费 | 国产色视频一区二区三区qq号 | 亚洲精品小视频在线观看 | 精品国产一区二区三区久久 | 亚洲视频在线观看 | 国产精品久久久区三区天天噜 | 一区二区中文字幕在线观看 | 亚洲日本欧美在线 | 99热在线国产精品 | 亚洲婷婷在线视频 | 久久综合精品一区 | 久久精品香蕉视频 | 成人久久久电影 | 中文字幕一区在线观看视频 | 亚洲精品高清在线观看 | 亚洲国产中文字幕在线观看 | 国产亚洲精品日韩在线tv黄 | 成人黄色在线电影 | 麻豆久久 | 久久国语露脸国产精品电影 | 首页国产精品 | 免费网站观看www在线观看 | 丁香五月亚洲综合在线 | 激情网综合| 日韩在线国产精品 | 亚洲精品在线免费观看视频 | 久久视频国产精品免费视频在线 | 青草草在线视频 | 欧美ⅹxxxxxx| 在线免费中文字幕 | 亚洲成aⅴ人片久久青草影院 | 成人在线一区二区三区 | 国产精品一二三 | 国产看片 色 | 国产精品一区二区吃奶在线观看 | 天天综合网天天 | 国产亚洲精品久久久久久久久久 | 精品中文字幕在线 | 久久a v视频 | 亚洲精品激情 | 国产精品成人免费精品自在线观看 | 久99久中文字幕在线 | 国产麻豆精品久久一二三 | 欧美日韩中文视频 | 一区二区三区电影在线播 | 国产一级片免费播放 | 一级黄色片在线免费看 | 91精品国产网站 | 日本中文不卡 | 五月天综合网站 | 久久久在线视频 | www.99久久.com | 久草精品在线观看 | 色综合国产 | 国精产品999国精产 久久久久 | 中文字幕亚洲五码 | 91一区啪爱嗯打偷拍欧美 | 2022中文字幕在线观看 | 91视频午夜| 4438全国亚洲精品在线观看视频 | 国产精品第十页 | 久久这里只有精品9 | 欧洲精品一区二区 | 欧美一级小视频 | 天天躁日日躁狠狠躁av麻豆 | 精品无人国产偷自产在线 | 国产美女永久免费 | 久久精品视频2 | 婷婷激情五月综合 | 久久成人在线视频 | 香蕉视频免费看 | 亚洲综合少妇 | 欧美日韩三级 | av免费电影网站 | 成人在线免费视频 | 最近免费观看的电影完整版 | 激情久久综合 | 久久伊人精品天天 | 亚洲天堂网站视频 | 久久久久久久看片 | 国产精品久久久毛片 | 精品美女久久久久久免费 | 成人综合免费 | 亚洲精品九九 | 国产成人免费观看 | 久久久久久蜜桃一区二区 | 国产精品欧美久久久久天天影视 | 亚洲成人中文在线 | 亚洲精品自在在线观看 | 国产日韩欧美精品在线观看 | 日本视频久久久 | 97视频免费观看2区 亚洲视屏 | 日韩毛片在线一区二区毛片 | 成人黄色在线观看视频 | 91视频啪| 人人干狠狠操 | 人人讲| 亚洲一区不卡视频 | 五月婷婷在线播放 | 国产精品一区二区三区视频免费 | 91av在线免费观看 | 免费在线视频一区二区 | 六月色播| 婷婷成人亚洲综合国产xv88 | 永久精品视频 | 久久久久久97三级 | 亚洲精品资源在线观看 | 久久久www | 久草在线看片 | 丁香六月中文字幕 | 午夜久久久久久久久久久 | 在线观看亚洲精品视频 | 天天做天天爱天天综合网 | 天天色天天射综合网 | 国产在线精品国自产拍影院 | 国产免费久久 | 在线v片免费观看视频 | 日韩中文字幕视频在线观看 | 在线观看视频你懂 | 日韩欧美一区二区三区视频 | 99色免费 | 欧美在线视频一区二区三区 | 99久久99久久精品国产片 | 美女网站视频免费都是黄 | 久久天堂网站 | 天天射天天射 | 日韩免费在线视频观看 | 五月网婷婷| www最近高清中文国语在线观看 | 又爽又黄又刺激的视频 | 日韩欧美xxx | 中文字幕视频观看 | 久久爱资源网 | 黄在线免费观看 | 国产美腿白丝袜足在线av | 日韩欧美视频二区 | 欧美成人精品三级在线观看播放 | 天天干天天操天天搞 | 有码视频在线观看 | 亚洲精品av中文字幕在线在线 | 久久婷婷一区二区三区 | 精品999| 天天综合成人网 | 天天爱天天 | 天天超碰 | 中国一级片在线观看 | 免费看一级 | 人人狠狠综合久久亚洲婷 | 99精品久久久久 | 国产日韩视频在线观看 | 亚洲欧美一区二区三区孕妇写真 | 亚洲国产视频直播 | 日本精品久久久久中文字幕 | 视频91 | 日韩综合视频在线观看 | 免费毛片一区二区三区久久久 | 天天操天天色天天射 | 久久黄色片 | 国产精品久久久久久久久久白浆 | 国产精品毛片一区视频 | 国产成人av网站 | 日韩精品在线视频免费观看 | 久久这里只有精品23 | 国产特级毛片aaaaaa毛片 | 亚洲成人频道 | 丰满少妇一级片 | 欧美少妇xxx| 午夜精品一区二区三区在线播放 | 国产视频一区二区在线播放 | 久久精品福利视频 | 日本韩国中文字幕 | 日韩精品电影在线播放 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 日韩字幕 | 999久久a精品合区久久久 | 午夜av一区 | 99视频在线精品国自产拍免费观看 | 成年人免费观看在线视频 | 久久久高清免费视频 | 国产黄网在线 | 福利视频区| 97人人视频 | 亚洲精品一区二区三区四区高清 | 免费黄a大片| av在线短片 | 中文网丁香综合网 | 成人一级影视 | 日韩av影片在线观看 | 在线亚洲观看 | 久草网在线视频 | 久久免费福利 | 久久免费视频3 | 免费三级大片 | 久久在现| 国产69精品久久99的直播节目 | 午夜视频99 | 超碰97人 | 九色91视频| 成人午夜精品福利免费 | 久久伊99综合婷婷久久伊 | 日韩在线视频线视频免费网站 | 亚洲国产三级在线观看 | 日韩av资源在线观看 | 久章操| 超碰在线人人艹 | 黄色影院在线播放 | 福利视频在线看 | 91网在线观看 | 美国三级黄色大片 | 午夜av在线 | 国产成人精品日本亚洲999 | 国产免费黄视频在线观看 | 国产最新精品视频 | 中文字幕二区在线观看 | 亚洲精品自拍视频在线观看 | 欧美精品久 | 免费日韩高清 | 日韩aⅴ视频 | 久久久久久久久久久久久久电影 | 天天爽夜夜操 | 中文字幕激情 | 99精品免费久久久久久日本 | 精品国产久 | 亚洲日本成人网 | 中文字幕在线观看视频一区 | 国产午夜小视频 | 四虎国产免费 | 国产精品久久久久久爽爽爽 | 国产精品美女毛片真酒店 | 国产福利精品在线观看 | 色91在线 | 综合激情 | 日韩中文免费视频 | 国产在线观看二区 | 91久久在线观看 | 久草在线精品观看 | 日本黄色免费电影网站 | 国产福利在线 | 精品99在线观看 | 国产精品久久久久久久久久直播 | 欧美专区国产专区 | 久久久久久国产精品999 | 亚洲精品视频久久 | 国产精品18videosex性欧美 | 国内精品久久久久 | 在线免费黄色毛片 | 国产精品一区二区中文字幕 | 成人污视频在线观看 | 中文字幕美女免费在线 | 97色在线观看 | 国产日本在线 | 婷婷色亚洲 | 在线免费观看涩涩 | 精品国产伦一区二区三区免费 | 亚洲一级免费观看 | 精品国产91亚洲一区二区三区www | 国产视频一区二区三区在线 | 久草综合在线 | 日韩在线中文字幕视频 | 国产成人精品av在线观 | 国产爽妇网 | 国产成人黄色网址 | 日本在线观看黄色 | 一区二区在线影院 | 亚洲综合色丁香婷婷六月图片 | 日本天天操 | 又爽又黄又刺激的视频 | 国产区免费在线 | 天堂av官网 | 欧美伦理电影一区二区 | 国产精品正在播放 | 免费视频久久 | 国产成人久久精品 | 激情综合五月天 | 免费国产黄线在线观看视频 | 国产精品9999久久久久仙踪林 | 天天摸日日操 | 一级片观看 | 中文字幕在线观看视频免费 | 国产成人av网站 | 国产又黄又猛又粗 | 最新日本中文字幕 | 久久精品亚洲综合专区 | 国产视频精品久久 | 天天视频亚洲 | 国产中文字幕在线免费观看 | 美女国产精品 | 在线国产片 | 91私密视频| 97精品国产97久久久久久粉红 | 中文字幕一区二区三区久久 | 国产在线观看你懂得 | 中文字幕亚洲字幕 | av天天干| 国产精品国产三级国产不产一地 | www.婷婷com| 国内精品亚洲 | 免费黄色av. | 国产精品久99 | 99麻豆久久久国产精品免费 | 黄色av成人在线观看 | 免费在线观看av网站 | 日韩精品在线视频免费观看 | 日本精品一区二区在线观看 | 日韩,中文字幕 | 天天爱综合 | 国产只有精品 | 国产精品视屏 | 最近中文字幕在线中文高清版 | 在线观看韩国av | 日韩精品视频免费在线观看 | 在线观看国产中文字幕 | 麻豆一精品传二传媒短视频 | 九九激情视频 | 911精品美国片911久久久 | 99久久婷婷国产综合精品 | 手机在线观看国产精品 | 操碰av| 国产麻豆成人传媒免费观看 | 中文字幕在线一区观看 | 免费看av片网站 | 啪啪免费观看网站 | 奇米影视8888在线观看大全免费 | 亚洲精品在线观看中文字幕 | 四虎影视8848dvd | 久久久久久久久久久综合 | 日日夜夜精品免费 | 国产精品久久婷婷六月丁香 | 午夜精品视频免费在线观看 | 亚洲欧美视屏 | 日韩久久久久久 | 久久综合影院 | 蜜臀av性久久久久av蜜臀妖精 | 色吊丝av中文字幕 | 日韩女同一区二区三区在线观看 | 99热精品国产一区二区在线观看 | 婷婷新五月 | 在线精品一区二区 | 欧美激情h | 国产久草在线观看 | 一区二区三区四区五区在线 | 精品久久一区 | 九七视频在线观看 | 色婷婷福利视频 | 婷婷社区五月天 | 99久久精品久久亚洲精品 | 亚洲欧美日本国产 | 国内精品久久久久影院优 | 91精品一区二区三区蜜桃 | 一区二区三区在线观看 | 麻豆视频免费在线 | 欧美贵妇性狂欢 | 国产免费大片 | 9色在线视频 | 久久天堂网站 | 91久草视频 | 91久久影院 | 一级性视频 | 国产精品久久久久四虎 | 国产成人精品一区二区三区免费 | 久av电影| 国产精品成人一区二区 | 中文字幕久久久精品 | 色婷婷av国产精品 | 亚洲九九 | 天天干,夜夜爽 | 福利二区视频 | 中文字幕av一区二区三区四区 | 色综合天天干 | 亚洲精品国偷自产在线91正片 | 五月天婷婷在线观看视频 | 国产电影黄色av | 国产精品夜夜夜一区二区三区尤 | 国产成人精品一区一区一区 | 国产精品手机看片 | 午夜国产福利在线观看 | 日韩精品一区二区免费 | av三级av | 2019中文最近的2019中文在线 | 日本中文字幕网址 | 91色在线观看视频 | 69精品视频在线观看 | 亚洲午夜久久久久 | 九九免费精品视频 | 黄色三级在线观看 | 天天翘av | 91亚洲视频在线观看 | 91麻豆产精品久久久久久 | 蜜臀av网址 | 色婷婷综合激情 | 免费人人干 | 日本色小说视频 | 久久精品一二三区 | 国产一区二三区好的 | 精品国内 | 久久久久久久影院 | 成人小视频在线观看免费 | 精品久久久久久久久中文字幕 | 日韩欧美在线第一页 | 日韩av视屏在线观看 | 免费人成在线观看网站 | 免费看黄电影 | 18女毛片 | 日韩性片| 成人精品亚洲 | 久久免费av电影 | 精品国产不卡 | 黄色成人91| 丁香六月在线观看 | 亚洲乱码在线 | 亚洲成人精品在线 | 在线观看中文字幕网站 | 日韩精品一区二区三区免费观看视频 | 999视频网站 | 国产亚洲免费的视频看 | 日本在线观看一区 | www久草 | 中文字幕乱码在线播放 | 91综合视频在线观看 | 手机在线看永久av片免费 | 92av视频| 一区二区三区四区五区六区 | 久久综合狠狠 | 五月天色婷婷丁香 | 91中文在线 | 中文字幕首页 | 人人揉人人揉人人揉人人揉97 | 九九热免费视频在线观看 | 久久国产二区 | 亚洲五月综合 | 欧美a级成人淫片免费看 | 在线观看日本高清mv视频 | 在线观看视频中文字幕 | 久久久久婷 | 国模一区二区三区四区 | 97电影手机 | 蜜臀久久99静品久久久久久 | 亚洲精品久| 精品国产aⅴ一区二区三区 在线直播av | 天堂va在线高清一区 | 久久久久久国产精品亚洲78 | 国产视频午夜 | 在线免费观看视频 | 视频成人永久免费视频 | 久久xx视频| 最新真实国产在线视频 | 国产在线观看91 | 亚洲欧洲日韩在线观看 | 91麻豆精品一区二区三区 | 日韩中文字幕a | 日韩精品一区二区在线观看 | 国产精品日韩在线观看 | 亚洲国产精品99久久久久久久久 | 亚洲欧洲日韩在线观看 | 91精品人成在线观看 | 国产精品国产三级国产aⅴ无密码 | 九九热免费在线视频 | 在线精品视频免费播放 | 韩国av不卡| 亚洲国产精品视频 | 精品久久久久久一区二区里番 | 久久激情视频免费观看 | 日韩视频中文字幕在线观看 | 亚洲欧美成人在线 | 国产精品理论在线观看 | 91在线影视| 激情视频91| 日韩精品一区二区三区中文字幕 | 亚洲国产精品资源 | 三级黄色免费片 | 国产毛片久久 | 婷婷激情小说网 | 成人免费在线视频观看 | 男女拍拍免费视频 | 中文字幕高清 | 国产色视频网站 | 激情五月婷婷综合 | 国产精品一区二区久久久久 | 中文字幕麻豆 | 97精品国产97久久久久久免费 | 在线观看视频中文字幕 | 在线导航av | 黄色a视频| 天天操比 | 九九久久成人 | 国产精品视频 | 国产精品精品国产婷婷这里av | 久久久麻豆精品一区二区 | 国产 视频 高清 免费 | 亚洲毛片视频 | 欧美一区二区在线免费看 | 韩日色视频 | 四虎成人网| 天天骚夜夜操 | 91完整版观看 | 一区二区精品在线观看 | 超碰97在线人人 | 久久五月激情 | 亚洲视屏一区 | 国产一级免费片 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 成人97人人超碰人人99 | 日日碰狠狠添天天爽超碰97久久 | 手机看片国产 | 国产精久久| 五月色婷 | 午夜精品一区二区三区在线观看 | 亚洲日韩中文字幕 | 午夜色影院 | 韩国av一区二区三区 | 在线免费视频a | 13日本xxxxxⅹxxx20 | 国产精品久久电影观看 | 婷婷色在线观看 | 91少妇精拍在线播放 | 国产护士hd高朝护士1 | 国产成人一区二区三区久久精品 | 国产成人a亚洲精品v | 久久国产免费视频 | 992tv在线观看 | 97超级碰| 日韩精品观看 | 亚洲精品中文字幕视频 | 中文字幕 成人 | 五月婷网 | 中文字幕在线观看日本 | 国产一区二区成人 | av解说在线| 手机av电影在线观看 | av中文字幕在线观看网站 | 国产精品二区在线观看 | 亚洲在线资源 | 天天操综 | 中文字幕丰满人伦在线 | 色人久久 | 欧美一级特黄aaaaaa大片在线观看 | jizz999| 免费成人av在线看 | 超碰在线1| 激情久久久| 黄色成人免费电影 | 黄色软件在线观看视频 | 亚洲电影久久久 | 在线观看亚洲精品 | 激情五月婷婷综合网 | 亚洲精品乱码久久久久久按摩 | 国产福利免费看 | 在线观看视频国产一区 | 日韩精品一区二区三区中文字幕 | 日韩色视频在线观看 | 草久在线播放 | 成人精品福利 | 亚洲精品美女久久 | 国产精品婷婷午夜在线观看 | 欧美淫aaa免费观看 日韩激情免费视频 | 黄网站色视频 | 9在线观看免费高清完整版在线观看明 | 国产一区国产二区在线观看 | 9i看片成人免费看片 | 五月天中文字幕mv在线 | 91社区国产高清 | 日本三级国产 | 97超碰国产精品 | 91精品国产自产在线观看 | 美女很黄免费网站 | 久久99国产精品二区护士 | 在线国产日本 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 夜夜视频欧洲 | 午夜影视av | 国产中文字幕在线看 | 国产婷婷色 | www.com在线观看 | 欧美日韩精品在线视频 | 一区二区三区国产精品 | 九九热在线播放 | 丁香六月久久综合狠狠色 | 成人午夜剧场在线观看 | 久久久久婷 | 天天久久夜夜 | 国产精品av电影 | 亚洲精选国产 | 在线影院av | 69夜色精品国产69乱 | 黄网站色视频免费观看 | 午夜精品一区二区三区在线观看 | 日韩丝袜在线观看 | 久久久久久国产精品免费 | 国产va在线观看免费 | 超碰久热| 主播av在线 | 六月丁香激情综合 | 不卡的av电影 | 在线观看久| aaa毛片视频 | 99久久99久久精品国产片 | 最新91在线视频 | 欧美精品做受xxx性少妇 | 在线视频区| 四虎伊人 | 黄色看片 | 成人 亚洲 欧美 | 久久免费a| 狠狠色网| 一区二区欧美日韩 | 在线日韩av| 亚洲精品在线视频网站 | 成 人 黄 色 片 在线播放 | 国产免费不卡av | 午夜国产福利在线 | 正在播放亚洲精品 | 操处女逼 | 国产成人亚洲在线电影 | 天天综合天天做 | 久久久久国产精品免费 | 国产精品免费久久久久 | 亚洲h在线播放在线观看h | 96av在线视频 | 午夜久久福利影院 | 91传媒激情理伦片 | 欧洲精品码一区二区三区免费看 | 欧美一级久久久 | 黄色在线视频网址 | 久青草电影 | 国产精品国产三级国产aⅴ入口 | 日韩视频一区二区在线观看 | 亚洲黄色免费在线 | 深爱综合网| 成人免费ⅴa | 精品女同一区二区三区在线观看 | 人人澡人| 粉嫩一二三区 | 亚洲成人免费 | 欧美日韩精品电影 | 国产一级小视频 | 玖玖精品视频 | 日产乱码一二三区别在线 | 欧美激情综合五月 | 中文字幕在线观看免费高清电影 | 国产免费观看久久黄 | 国产原创91 | 在线免费视频a | 久久久视频在线 | 婷婷丁香av | 中文字幕免费国产精品 | 日日干天天爽 | 韩国av一区 | 色综合久久五月天 | 精品久久一区二区三区 | 欧美成人黄色片 | 亚洲成人免费观看 | 丁香六月五月婷婷 | 激情综合网五月激情 | 人人插人人艹 | 欧美日韩一区二区三区不卡 | 伊人久久在线观看 | 久久久久电影网站 | 亚洲国产中文在线 | 色综合久久88色综合天天免费 | 最近能播放的中文字幕 | 青春草视频 | 欧美另类美少妇69xxxx | 久艹在线免费观看 | 91大神电影 | 蜜臀久久99精品久久久无需会员 | 国产在线久草 | 狠狠操狠狠插 | 色瓜| 国产剧情一区二区在线观看 | 成年人在线免费视频观看 | 国产精品资源网 | 国产黄色片免费观看 | 亚洲午夜精品久久久 | 国产在线久久久 | 国产黄色免费在线观看 | 午夜精品久久 | 91免费观看视频网站 | 久久久激情网 | 91精品久久久久久 | 国产精品99视频 | 欧美日韩首页 | 99视频精品全部免费 在线 | 天天干天天射天天操 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 成人性生活大片 | 日韩一级电影网站 | 在线看成人片 | 特级黄录像视频 | 欧美日韩免费一区二区 | 色综合激情久久 | 视频一区亚洲 | 国产免费一区二区三区最新6 | 99热只有精品在线观看 | 国产精品自拍av | 欧美天堂视频在线 | 日韩电影一区二区三区在线观看 | 国产一区不卡在线 | 黄色一级在线视频 | 欧美另类调教 | 欧美激情视频一区二区三区免费 | 日本乱视频 | 久草91视频 | 韩日三级av| 中文字幕在线免费观看 | av网址aaa | 国产精品扒开做爽爽的视频 | 国产大片黄色 | 国产欧美最新羞羞视频在线观看 | 久久久久久久久福利 | 456免费视频 | 国产成人a v电影 | 91毛片视频 | 黄色精品一区 | 色香蕉在线视频 | 国产精品系列在线播放 | 久久久久久片 | 日韩美女免费线视频 | 婷婷在线视频 | 亚洲精品麻豆视频 | 国内外激情视频 | 国产又黄又硬又爽 | aa一级片 | 亚洲在线色 | 色播五月激情五月 | 国产成年免费视频 | www色com| 日韩在线三级 | 亚洲男男gaygayxxxgv | av在线免费播放 |