精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Spring5新寵PathPattern,AntPathMatcher:那我走?

開發 前端
PathPattern是Spring5新增的API,所在包:org.springframework.web.util.pattern.PathPattern,所屬模塊為spring-web。可見它專為Web設計的“工具”。

[[406999]]

前言

你好,我是YourBatman。

依稀記得3年前的在“玩”Spring WebFlux的時候,看到PathPattern在AbstractHandlerMapping中起到了重要作用:用于URL的匹配。當時就很好奇:這一直不都是AntPathMatcher的活嗎?

于是乎我就拿出了自己更為熟悉的Spring WebMvc對于類進行功能比對,發現PathPattern扮演的角色和AntPathMatcher一毛一樣,所以當時也就沒去深入研究啦。

正所謂念念不忘必有回響。時隔3年最近又回到搞WebFlux了,欠下的債總歸要還呀,有必要把PathPattern深入解讀,畢竟它是Spring5在路徑解析器方面的新寵,貫穿WebFlux上下。重點是號稱比AntPathMatcher擁有更好的使用體驗以及更快的匹配效率,咦,勾起了興趣了解一下~

正值周末,說干就干。

所屬專欄

  • 點撥-Spring技術棧

本文提綱

版本約定

  • JDK:8
  • Spring Framework:5.3.x

正文

PathPattern是Spring5新增的API,所在包:org.springframework.web.util.pattern.PathPattern,所屬模塊為spring-web。可見它專為Web設計的“工具”。

不同于AntPathMatcher是一個“上帝類”把所有活都干了,新的路徑匹配器圍繞著PathPattern擁有一套體系,在設計上更具模塊化、更加面向對象,從而擁有了更好的可讀性和可擴展性。

下面深入了解下該技術體系下的核心元素。主要有:

  • PathElement:路徑元素。一個URL模板根據/可以拆分成N多個路徑元素對象
  • PathContainer:URL的結構化表示。一個URL對應一個PathContainer對象實例
  • PathPattern:路徑解析的模式。路徑模式匹配器的最核心API
  • PathPatternParser:將一個String類型的模式解析為PathPattern實例,這是創建PathPattern實例的唯一方式

PathElement:路徑元素

顧名思義,它表示路徑節點。一個path會被解析成N多個PathElement節點。

核心屬性:

  1. // Since: 5.0 
  2. abstract class PathElement { 
  3.  
  4.  protected final int pos; 
  5.  protected final char separator; 
  6.  @Nullable 
  7.  protected PathElement next
  8.  @Nullable 
  9.  protected PathElement prev; 
  • pos:該節點在path里的起點位置
  • separator:該path使用的分隔符
  • next:后節點,可以為null(如最后一個節點)
  • prev:前節點,可以為null(如第一個節點)

所有的PathElement之間形成鏈狀結構,構成一個完整的URL模板。

Tips:我個人意見,并不需要太深入去了解PathElement內部的具體實現,在宏觀角度了解它的定義,然后認識下它的子類實現不同的節點類型即可

它有如下子類實現:

SeparatorPathElement

分離器元素。代表用于分離的元素(默認是/,也可以是.)

  1. @Test 
  2. public void test1() { 
  3.     PathPatternParser parser = new PathPatternParser(); 
  4.     PathPattern pathPattern = parser.parse("/api/v1"); 
  5.     System.out.println(pathPattern); 

斷點調試查看解析后的pathPattern變量擁有的元素情況:

可以看到這是標準的鏈式結構嘛,這種關系用圖畫出來就是這樣子:

其中綠色的/都是SeparatorPathElement類型,藍色都是LiteralPathElement字面量類型。將一個Pattern拆解成為了一個個的Element對象,后面就可以方便的面向對象編程,大大增加了可讀性、降低出錯的概率。

說明:由于這是第一個元素,所以才舉了個實際的代碼示例輔助理解。下面的就只需描述概念啦,舉一反三即可~

WildcardPathElement

通配符元素。如:/api/*/yourbatman

說明:在路徑中間它至少匹配1個字符(//不行,/ /可行),但在路徑末尾可以匹配0個字符

SingleCharWildcardedPathElement

單字符通配符元素。如:/api/your??tman

說明:一個?代表一個單字通配符,若需要適配多個用多個?即可

WildcardTheRestPathElement

通配剩余路徑元素。如:/api/yourbatman/**

說明:**只能放在path的末尾,這才是rest剩余的含義嘛

CaptureVariablePathElement

將一段路徑作為變量捕獲的路徑元素。如:/api/yourbatman/{age}

說明:{age}就代表此元素類型被封裝進來

CaptureTheRestPathElement

捕獲路徑其余部分的路徑元素。如:/api/yourbatman/{*restPath}

說明:若待匹配的路徑是/api/yourbatman/a/b/c,那么restPath=a/b/c

LiteralPathElement

字面量元素。不解釋~

RegexPathElement

正則表達式元素。如:api/*_*/*_{age}說明:*_*和*_{age}都會被解析為該元素類型,這種寫法是從AntPathMatcher里派生來過的(但不會依賴于AntPathMatcher)

總之:任何一個字符串的pattern最終都會被解析為若干段的PathElement,這些PathElement以鏈式結構連接起來用以表示該pattern,形成一個對象數據。不同于AntPathMatcher的純字符串操作,這里把每一段都使用對象來描述,結構化的表示使得可讀性更強、更具靈活性,甚至可以獲得更好的性能表現。

PathContainer:URL的結構化表示

和PathPattern類似,待匹配的path的每一段都會表示為一個元素并保存其元數據信息。也就是說:每一個待匹配的URL路徑都會被解析為一個PathContainer實例。

PathContainer雖然是個接口,但我們無需關心其實現,類同于Java 8的java.util.stream.Collector接口使用者無需關心其實現一樣。因為提供了靜態工具方法用于直接生成對應實例。體驗一把:

  1. @Test 
  2. public void test2() { 
  3.     PathContainer pathContainer = PathContainer.parsePath("/api/v1/address", PathContainer.Options.HTTP_PATH); 
  4.     System.out.println(pathContainer); 

debug模式運行,查看pathContainer對象詳情:

這和解析為PathPattern的結構何其相似(不過這里元素們是通過有序的集合組織起來的)。對比看來,拍腦袋應該能夠猜到何新版的匹配效率會更高了吧。

補充說明:

  • value和valueToMatch的區別:value是原值,valueToMatch是(處理過的,比如已解碼的)最終參與匹配的值
  • parameters代表路徑參數。若希望它有值只需使用;號分隔填值即可。如:/api;abc/v1,此參數一般都用不著

因為Http中是允許這樣攜帶參數的,但是目錄(.形式)就不能這么寫啦

PathPattern:路徑解析的模式

表示解析路徑的模式。包括用于快速匹配的路徑元素鏈,并累積用于快速比較模式的計算狀態。它是直接面向使用者進行匹配邏輯的最重要API,完成match操作。

PathPattern所在包是org.springframework.web.util.pattern.PathPattern,位于spring-web模塊,專為web(含webmvc和webflux)設計的全新一套路徑匹配API,具有更高的匹配效率。

認識下它的成員屬性:

  1. // Since: 5.0 
  2. public class PathPattern implements Comparable<PathPattern> { 
  3.  
  4.  // pattern的字符串形式 
  5.  private final String patternString; 
  6.  // 用于構建本實例的解析器 
  7.  private final PathPatternParser parser; 
  8.  // 分隔符使用/還是.,默認是/ 
  9.  private final PathContainer.Options pathOptions; 
  10.  // 如果pattern里結尾沒/而待匹配的有,仍然讓其匹配成功(true),默認是true 
  11.  private final boolean matchOptionalTrailingSeparator; 
  12.  // 是否對大小寫敏感,默認是true 
  13.  private final boolean caseSensitive; 
  14.  // 鏈式結構:表示URL的每一部分元素 
  15.  @Nullable 
  16.  private final PathElement head; 
  17.  
  18.  private int capturedVariableCount; 
  19.  private int normalizedLength; 
  20.  private boolean endsWithSeparatorWildcard = false
  21.  private int score; 
  22.  private boolean catchAll = false
  23.  

以上屬性是直接讀取,下面這些個是計算出來的,比較特殊就特別照顧下:

  • capturedVariableCount:在這個模式中捕獲的變量總數。也就是{xxx}或者正則捕獲的總數嘍
  • normalizedLength:通配符批到的變量長度的總和(關于長度的計算有個約定:如?是1,字面量就是字符串長度),這個變量對提升匹配速度有幫助
  • endsWithSeparatorWildcard:標記該模式是否以隔離符或者通配符*結尾
  • score:分數用于快速比較該模式。不同的模式組件被賦予不同的權重。分數越低越具體,如:捕獲到的變量分數值為1,通配符值是100
  • catchAll:該pattern是否以**或者{*xxx}結尾

score、catchAll等標記用于加速匹配的速度,具體體現在PathPattern.SPECIFICITY_COMPARATOR這個比較器上,這是PathPattern速度比AntPathMatcher快的根因之一

值得注意的是:所有屬性均不提供public的set方法,也就是說PathPattern實例一旦創建就是只讀(不可變)實例了。

快速創建缺省的實例

上面了解到,PathPattern的構造器不是public的,所以有且僅能通過PathPatternParser創建其實例。然而,為快速滿足絕大多數場景,Spring還提供了一種快速創建缺省的PathPattern實例的方式:

PathPatternParser提供一個全局共享的、只讀的實例用于快速創建缺省的PathPattern實例,類似于實例工廠的作用。畢竟絕大部分場景下用PathPattern的缺省屬性即可,因此有了它著實方便不少。

注意:雖然該PathPatternParser實例是全局共享只有1個,但是,創建出來的PathPattern可是不同實例哦(基本屬性都一樣而已)

代碼示例

PathPattern的匹配方式和AntPathMatcher基本保持一致:使用的基于Ant風格模式匹配。

但是發現沒,這里不再強調Ant字樣,也許Spring覺得Ant的概念確實已廉頗老矣?不符合它緊跟潮流的身份?

相比于AntPathMatcher,PathPattern主要有兩處地方不一樣:

說明:PathPattern只支持兩種分隔符(/和.),而AntPathMatcher可以隨意指定。雖然這也是不同點,但這一般無傷大雅所以就不單獨列出了

1. 新增{*pathVariable}語法支持

這是PathPattern新增的“語法”,表示匹配余下的path路徑部分并將其賦值給pathVariable變量。

  1. @Test 
  2. public void test1() { 
  3.     System.out.println("======={*pathVariable}語法======"); 
  4.     PathPattern pattern = PathPatternParser.defaultInstance.parse("/api/yourbatman/{*pathVariable}"); 
  5.  
  6.     // 提取匹配到的的變量值 
  7.     System.out.println("是否匹配:" + pattern.matches(PathContainer.parsePath("/api/yourbatman/a/b/c"))); 
  8.     PathPattern.PathMatchInfo pathMatchInfo = pattern.matchAndExtract(PathContainer.parsePath("/api/yourbatman/a/b/c")); 
  9.     System.out.println("匹配到的值情況:" + pathMatchInfo.getUriVariables()); 
  10.  
  11. ======={*pathVariable}語法====== 
  12. 是否匹配:true 
  13. 匹配到的值情況:{pathVariable=/a/b/c} 

在沒有PathPattern之前,雖然也可以通過/**來匹配成功,但卻無法得到匹配到的值,現在可以了!

和**的區別

我們知道/**和/{*pathVariable}都有匹配剩余所有path的“能力”,那它倆到底有什么區別呢?

  1. /**能匹配成功,但無法獲取到動態成功匹配元素的值
  2. /{*pathVariable}可認為是/**的加強版:可以獲取到這部分動態匹配成功的值

正所謂一代更比一代強嘛,如是而已。

和**的優先級關系

既然/**和/{*pathVariable}都有匹配剩余path的能力,那么它倆若放在一起,優先級關系是怎樣的呢?

妄自猜測沒有意義,跑個案例一看便知:由于PathPattern實現了比較器接口,因此本例利用SortedSet自動排序即可,排第一的證明優先級越高

  1. @Test 
  2. public void test2() { 
  3.     System.out.println("======={*pathVariable}和/**優先級======"); 
  4.     PathPattern pattern1 = PathPatternParser.defaultInstance.parse("/api/yourbatman/{*pathVariable}"); 
  5.     PathPattern pattern2 = PathPatternParser.defaultInstance.parse("/api/yourbatman/**"); 
  6.  
  7.     SortedSet<PathPattern> sortedSet = new TreeSet<>(); 
  8.     sortedSet.add(pattern1); 
  9.     sortedSet.add(pattern2); 
  10.  
  11.     System.out.println(sortedSet); 
  12.  
  13. ======={*pathVariable}和/**優先級====== 
  14. [/api/yourbatman/**, /api/yourbatman/{*pathVariable}] 

測試代碼的細節:故意將/{*pathVariable}先放進set里面而后放/**,但最后還是/**在前。

結論:當二者同時出現(出現沖突)時,/**優先匹配。

2. 禁用中間**語法支持

在上篇文章對AntPathMatcher的詳細分析文章中,我們知道是可以把/**放在整個URL中間用來匹配的,如:

  1. @Test 
  2. public void test4() { 
  3.     System.out.println("=======**:匹配任意層級的路徑/目錄======="); 
  4.     String pattern = "/api/**/yourbatman"
  5.  
  6.     match(1, MATCHER, pattern, "/api/yourbatman"); 
  7.     match(2, MATCHER, pattern, "/api//yourbatman"); 
  8.     match(3, MATCHER, pattern, "/api/a/b/c/yourbatman"); 
  9.  
  10. =======**:匹配任意層級的路徑/目錄======= 
  11. 1 match結果:/api/**/yourbatman 【成功】 /api/yourbatman 
  12. 2 match結果:/api/**/yourbatman 【成功】 /api//yourbatman 
  13. 3 match結果:/api/**/yourbatman 【成功】 /api/a/b/c/yourbatman 

與AntPathMatcher不同,**僅在模式末尾受支持。中間不被允許了,否則實例創建階段就會報錯:

  1. @Test 
  2. public void test3() { 
  3.     System.out.println("=======/**放在中間語法======"); 
  4.     PathPattern pattern = PathPatternParser.defaultInstance.parse("/api/**/yourbatman"); 
  5.  
  6.     pattern.matches(PathContainer.parsePath("/api/a/b/c/yourbatman")); 
  7.  
  8. =======/**放在中間語法====== 
  9. org.springframework.web.util.pattern.PatternParseException: No more pattern data allowed after {*...} or ** pattern element 
  10.  at org.springframework.web.util.pattern.InternalPathPatternParser.peekDoubleWildcard(InternalPathPatternParser.java:250) 
  11.  ... 

從報錯中還能看出端倪:不僅**,{*xxx}也是不能放在中間而只能是末尾的

PathPattern這么做的目的是:消除歧義。

那么問題來了,如果就是想匹配中間的任意層級路徑怎么做呢?答:首先這在web環境里有這樣需求的概率極小(PathPattern只適用于web環境),若這依舊是剛需,那就只能蛻化到借助AntPathMatcher來完成嘍。

PathPattern對比AntPathMatcher

二者目前都存在于Spring技術棧內,做著“相同”的事。雖說現在還鮮有同學了解到PathPattern,我認為淘汰掉AntPathMatcher只是時間問題(特指web環境哈),畢竟后浪總歸有上岸的一天。

但不可否認,二者將在較長時間內共處,那么它倆到底有何區別呢?了解一下

出現時間

AntPathMatcher是一個早在2003年(Spring的第一個版本)就已存在的路徑匹配器,而PathPattern是Spring 5新增的,旨在用于替換掉較為“古老”的AntPathMatcher。

功能差異

PathPattern去掉了Ant字樣,但保持了很好的向下兼容性:除了不支持將**寫在path中間之外,其它的匹配規則從行為上均保持和AntPathMatcher一致,并且還新增了強大的{*pathVariable}的支持。

因此在功能上姑且可認為二者是一致的,極特殊情況下的不兼容除外。

性能差異

Spring官方說PathPattern的性能優于AntPathMatcher,我抱著懷疑的態度做了測試,示例代碼和結果如下:

// 匹配的模板:使用一個稍微有點復雜的模板進行測試private static final String pattern = "/api/your?atman/{age}/**";

  1. // 匹配的模板:使用一個稍微有點復雜的模板進行測試 
  2. private static final String pattern = "/api/your?atman/{age}/**"
  1. // AntPathMatcher匹配代碼:使用單例的PathMatcher,符合實際使用情況 
  2. private static final PathMatcher MATCHER = new AntPathMatcher(); 
  3. public static void antPathMatcher(String reqPath) { 
  4.     MATCHER.match(reqPath); 
  1. // PathPattern代碼示例:這里的pattern由下面來定義 
  2. private static final PathPattern PATTERN = PathPatternParser.defaultInstance.parse(pattern); 
  3. public static void pathPattern(String reqPath) { 
  4.     PATTERN.matches(PathContainer.parsePath(reqPath)); 

匹配的測試代碼:

  1. @Test 
  2. public void test1() { 
  3.     Instant start = Instant.now(); 
  4.     for (int i = 0; i < 100000; i++) { 
  5.         String reqPath = "/api/yourBatman/" + i + "/" + i; 
  6.         antPathMatcher(reqPath); 
  7.         // pathPattern(reqPath); 
  8.     } 
  9.     System.out.println("耗時(ms):" + Duration.between(start, Instant.now()).toMillis()); 

不斷調整循環次數,且各執行三次,將結果繪制成如下表格:

測試機配置為:

循環100000次:

循環1000000次:

循環10000000次:

結論:PathPattern性能比AntPathMatcher優秀。理論上pattern越復雜,PathPattern的優勢越明顯。

最佳實踐

既然路徑匹配器有兩種方案,那必然有最佳實踐。Spring官方對此也是持有態度的:

Web環境

如果是Servlet應用(webmvc),官方推薦PathPattern(只是推薦,但默認的依舊是AntPathMatcher哈),相關代碼體現在PathPattern里:

  1. // Since: 07.04.2003 
  2. public abstract class AbstractHandlerMapping ... { 
  3.   
  4.  private UrlPathHelper urlPathHelper = new UrlPathHelper(); 
  5.  private PathMatcher pathMatcher = new AntPathMatcher(); 
  6.   
  7.  ... 
  8.   
  9.  @Nullable 
  10.  private PathPatternParser patternParser; 
  11.  // Since: 5.3 
  12.  public void setPatternParser(PathPatternParser patternParser) { 
  13.   this.patternParser = patternParser; 
  14.  } 

注意:setPatternParser()從5.3版本開始才被加入,也就說雖然PathPattern從Spring 5就有了,但直到5.3版本才被加入到webmvc里,且作為可選(默認依舊是AntPathMatcher)。換句話講:在Spring 5.3版本之前,仍舊只能用AntPathMatcher。

在WebMvc里啟用PathPattern

默認情況下,Spring MVC依舊是使用的AntPathMatcher進行路徑匹配的,那如何啟用效率更高的PathPattern呢?

通過上面源碼知道,就是要調用AbstractHandlerMapping的setPatternParser方法嘛,其實Spring為此是預留了擴展點的,只需這么做即可:

  1. /** 
  2.  * 在此處添加備注信息 
  3.  * 
  4.  * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a> 
  5.  * @site https://yourbatman.cn 
  6.  * @date 2021/6/20 18:33 
  7.  * @since 0.0.1 
  8.  */ 
  9. @Configuration(proxyBeanMethods = false
  10. public class WebMvcConfiguration implements WebMvcConfigurer { 
  11.  
  12.     @Override 
  13.     public void configurePathMatch(PathMatchConfigurer configurer) { 
  14.         configurer.setPatternParser(PathPatternParser.defaultInstance); 
  15.     } 

如果是Reactor應用(webflux),那PathPattern就是唯一解決方案。這體現在org.springframework.web.reactive.handler.AbstractHandlerMapping:

  1. // Since: 5.0 
  2. public abstract class AbstractHandlerMapping... { 
  3.  
  4.  private final PathPatternParser patternParser; 
  5.  ... 
  6.  public AbstractHandlerMapping() { 
  7.   this.patternParser = new PathPatternParser(); 
  8.  } 

webflux里早已不見AntPathMatcher的蹤影,因為webflux是從Spring 5.0開始的,因此沒有向下兼容的負擔,直接全面擁抱PathPattern了。

結論:PathPattern語法更適合于web應用程序,其使用更方便且執行更高效。

非Web環境

嗯,如果認真“聽課”了的同學就知道:非Web環境依舊有且僅有一種選擇,那便是AntPathMatcher,因為PathPattern是專為Web環境設計,不能用于非Web環境。所以像上面資源加載、包名掃描之類的,底層依舊是交給AntPathMatcher去完成。

說明:由于這類URL的解析絕大多數情況下匹配一次(執行一次)就行,所以微小的性能差異是無所謂的(對API來講收益較大)

可能有小伙伴會說:在Service層,甚至Dao層我也可以正常使用PathPattern對象呀,何解?這個問題就相當于:HttpServletRequest屬于web層專用組件,但你依舊可以將其傳到Service層,甚至Dao層供以使用,在編譯、運行時不會報錯。但你可深入思考下,這么做合適嗎?

舉個生活上的例子:馬桶可以裝在衛生間,也可以安裝在臥室的床旁邊,都能完成大小便功能,但你覺得這么做合適嗎?

Java這門語言對訪問權限的控制設計得還是很優秀的,很多隔離性的問題在編譯器就能搞定。但有很多規范性做法是無法做到強約束的,只能依靠工程師自身水平。這就是經驗,也是區別初級工程師和高級工程師的重要因素。

總結

技術的日新月異,體現在一個個像PathPattern這個更好的API上。

Spring 5早在2017-09就已發布,可能是由于它“設計得過于優秀”,即使大版本的發布也幾乎保持100%向下兼容,使得一般開發者感受不到它的升級。但是,這對框架二次開發者并不可能完全透明,因為二次開發經常會用到其Low-Level的API,比如今天的主角PathPattern就算其中之一,所以說我們要與時俱進呀o(╥﹏╥)o!

Spring 5雖然新增了(更好的)PathPattern,但它不能完全替代掉AntPathMatcher,因為前者專為web設計,所以在web領域是可完全替代掉AntPathMatcher的。但在非web領域內,AntPathMatcher依舊不可替代。

本文轉載自微信公眾號「 BAT的烏托邦」,可以通過以下二維碼關注。轉載本文請聯系 BAT的烏托邦公眾號。

 

責任編輯:姜華 來源: BAT的烏托邦
相關推薦

2021-06-30 13:30:05

GitHub工具AI

2022-07-07 14:18:43

SpringWeb應用設計

2021-08-06 15:56:48

編程語言PythonJava

2009-02-19 09:58:21

2023-07-11 08:12:49

OkHttp工具網絡

2021-03-07 16:41:06

URLSpring5

2022-07-28 10:39:50

OpenApiSwaggerSpringDoc

2021-06-21 08:35:52

AntPathMatcSpringAnt風格

2012-11-16 13:55:04

線下渠道連鎖賣場運營商網點

2013-01-22 13:02:41

HTML5canvasWeb

2013-01-24 10:26:04

HTML5HTML 5HTML5的未來

2010-11-02 14:48:48

職場

2014-12-02 09:05:20

2011-07-08 10:57:25

Lua

2023-10-23 15:38:12

Spring 5開發

2021-02-03 13:03:00

編程程序員語言

2012-09-24 11:17:11

2010-09-03 15:50:23

2013-03-20 10:18:10

SDN電信設備電信運營商

2013-04-02 09:23:25

開源虛擬化服務器虛擬化
點贊
收藏

51CTO技術棧公眾號

国产一线在线观看| 亚洲成人网上| 国产特黄大片aaaa毛片| 精品99久久| 欧美三级一区二区| 国产精品无码免费专区午夜| 日韩欧美电影在线观看| 美女高潮久久久| 欧美极品少妇xxxxⅹ喷水| 亚洲一区二区三区四区五区六区 | 久久精品国产亚洲| 午夜免费福利影院| 祥仔av免费一区二区三区四区| 亚洲国产人成综合网站| 亚洲狠狠婷婷综合久久久| 国产黄色片免费观看| 日本午夜一本久久久综合| 日韩视频在线免费观看| 日本黄色网址大全| 亚洲精品一二三**| 欧美日韩一卡二卡| 天天夜碰日日摸日日澡性色av| 淫片在线观看| 2020国产精品自拍| 国产精品国产亚洲精品看不卡15 | 色欲综合视频天天天| 日韩一二区视频| 黄色在线小视频| 亚洲这里只有精品| 中文字幕在线视频网站| 亚洲综合久久久久| 在线一区高清| 2017亚洲天堂1024| 91色九色蝌蚪| 国产精品一区二区免费| 国产日韩在线观看一区| 日韩高清电影一区| 欧美又大粗又爽又黄大片视频| 中文字幕在线有码| 97精品国产福利一区二区三区| 日韩精品极品视频| 男男一级淫片免费播放| 日韩精品一区二区三区中文字幕| 欧美三级中文字幕在线观看| 成人三级视频在线播放 | 欧美与欧洲交xxxx免费观看 | 国产日韩专区在线| 伊人久久久久久久久久久久| 免费看的黄色欧美网站| 国产69精品久久久久久| 国产精品theporn动漫| 亚洲精品中文字幕乱码| www国产精品视频| 天美传媒免费在线观看| 全球成人免费直播| 在线看日韩av| 午夜国产福利视频| 99re6这里只有精品| 中文字幕日韩高清| jizzjizzjizz国产| 亚洲乱码精品| 免费91麻豆精品国产自产在线观看| 欧美日韩午夜视频| 欧美不卡一区| 欧美精品久久久久久久免费观看| 国产黄色片视频| 日韩午夜av| 情事1991在线| 亚洲免费视频二区| 激情五月婷婷综合网| 51精品国产人成在线观看 | 手机免费观看av| 日韩大片在线观看| 久久久精品一区二区| 一级黄色录像视频| 亚洲麻豆视频| 日韩美女主播视频| 中文字幕资源网| 黄色日韩网站视频| 国产精品免费一区二区三区四区| 性高潮久久久久久久久久| 久久五月婷婷丁香社区| 亚洲v国产v在线观看| 黄在线免费观看| 亚洲国产精品久久艾草纯爱| 两根大肉大捧一进一出好爽视频| 香蕉久久免费电影| 3d动漫精品啪啪一区二区竹菊| 黑人无套内谢中国美女| 人人精品亚洲| 久久精品中文字幕电影| 国产精选第一页| 久久中文精品| 91pron在线| 青青草免费在线| 国产精品国产自产拍高清av | 在线观看的网站你懂的| 午夜精品影院在线观看| 蜜桃免费在线视频| 中文字幕一区日韩精品| 国产亚洲精品91在线| 中文字幕另类日韩欧美亚洲嫩草| 国产精品一级| 亚洲综合在线中文字幕| 麻豆app在线观看| 亚洲日本在线观看| 91看片就是不一样| 亚洲精品一区二区三区中文字幕 | 韩国在线一区| 国产精品电影久久久久电影网| 99久久久无码国产精品免费| 久久精品欧美一区二区三区不卡| 在线国产伦理一区| 亚洲女色av| 欧美xfplay| 欧美福利在线视频| 久久一区国产| 国产乱人伦精品一区二区| 亚洲成人三级| 色综合天天综合网国产成人综合天| 在线免费观看av网| 精品一级毛片| 91精品国产高清久久久久久久久 | 悠悠资源网亚洲青| 欧美成人bangbros| 日本高清一二三区| 免费在线视频一区| 日产精品高清视频免费| аⅴ资源天堂资源库在线| 欧美一区二区三区男人的天堂| 97在线观看免费视频| 中文在线一区| 精品蜜桃一区二区三区| 欧美大胆的人体xxxx| 日韩一区二区麻豆国产| 一本一本久久a久久| 免费欧美日韩国产三级电影| 欧美日韩大片一区二区三区 | 亚洲影院久久精品| 999在线精品视频| 人人狠狠综合久久亚洲婷| 国产成人97精品免费看片| 色视频在线观看免费| 欧美日韩国产综合视频在线观看中文 | 中日韩高清电影网| 欧美一区二区三区四区五区| 性少妇xx生活| 蜜桃久久久久久久| 一本一道久久久a久久久精品91 | 国产免费无码一区二区| 一区二区国产在线| 97超碰人人模人人爽人人看| a免费在线观看| 欧美一区二区二区| 日韩a级片在线观看| 国产99一区视频免费| 国产成人亚洲综合无码| 在线日韩成人| 国内成人精品一区| 四虎精品在线| 色噜噜狠狠成人网p站| 日韩免费成人av| 麻豆成人免费电影| 中国老女人av| ady日本映画久久精品一区二区| 欧美激情a在线| 女人18毛片一区二区三区| 激情亚洲一区二区三区四区| 久久久亚洲av波多野结衣| 青青国产91久久久久久| 综合国产精品久久久| 亚洲码欧美码一区二区三区| 久久久免费观看| 黄色在线视频观看网站| 欧美美女黄视频| 欧美成人一区二区三区高清| 波多野结衣视频一区| 欧美 激情 在线| 欧美电影免费| 国产精品久久7| 超薄肉色丝袜脚交一区二区| 爱福利视频一区| 手机在线不卡av| 色94色欧美sute亚洲线路二| 无码黑人精品一区二区| av在线不卡网| 天天操天天爽天天射| 欧美va天堂| 欧美日韩在线精品| 日韩一区二区三区在线看| 欧美亚洲激情在线| 黄色网址在线免费播放| 亚洲激情视频在线| 亚洲影院一区二区三区| 亚洲午夜免费电影| 黄色片网站免费| 国产成人综合亚洲91猫咪| 黄在线观看网站| 欧美一区二区三区另类| 日韩精品欧美在线| 成人影院中文字幕| 国产精品视频26uuu| 91老司机福利在线| 久久久久北条麻妃免费看| 网站黄在线观看| 91精品国产综合久久精品图片 | 视频一区二区三区不卡 | 国自产拍在线网站网址视频| 4438成人网| 久久久黄色大片| 亚洲综合色网站| 99久久99久久精品免费| 成人91在线观看| 精品亚洲视频在线| 日韩精品一级中文字幕精品视频免费观看 | 亚洲另类在线制服丝袜| 中文字幕 自拍| 成人免费毛片aaaaa**| 性欧美在线视频| 玖玖视频精品| 鲁一鲁一鲁一鲁一色| 亚洲乱码免费伦视频| 五月天国产一区| 群体交乱之放荡娇妻一区二区 | 妖精视频一区二区三区免费观看 | 爱福利视频一区二区| 一区二区三区在线| 先锋影音日韩| 精品国产一区二区三区久久久蜜臀| 成人综合色站| 国产精品视频一区二区三区综合| 国产精品久久中文| 亚洲国产福利| 欧美洲成人男女午夜视频| 美足av综合网| 欧美国产日本高清在线 | 久久av中文| 精品久久久三级| 激情小说亚洲图片| 国产一区二区不卡视频在线观看| 日本一区二区三区电影免费观看| 国产精品一区二区三区毛片淫片 | 亚洲国产一区二区精品专区| 国产亚洲精品久久久久久久| 欧美精品大片| 特级西西444| 在线一区电影| 国产又粗又硬又长| 亚洲视频电影在线| 国产又粗又爽又黄的视频| 婷婷综合社区| 亚洲一区二区三区在线观看视频| 日韩精品久久| av动漫免费观看| 性欧美欧美巨大69| 无码毛片aaa在线| 欧美日韩1080p| 国产精品一色哟哟| 1024成人| 亚欧无线一线二线三线区别| 久久精品官网| 五月天激情视频在线观看| 久久精品国产一区二区三区免费看| 黄色片在线免费| 麻豆精品在线看| 一级网站在线观看| 亚洲AV无码精品国产| 黑人巨大精品欧美一区| 亚洲国产综合av| www.色精品| 蜜桃传媒一区二区亚洲| 国产精品久久久久久久蜜臀| 欧美爱爱免费视频| 亚洲成av人片在www色猫咪| 日韩视频在线观看一区| 欧美艳星brazzers| 国产精品久久久久久久久久久久久久久久久久| 51精品久久久久久久蜜臀| 欧美 日韩 国产 在线| 亚洲人成电影在线| 欧美天天影院| 久久久久久亚洲精品中文字幕| 欧美裸体视频| 国产精品一区专区欧美日韩| 亚洲国产aⅴ精品一区二区| 久久国产精品久久精品国产| 精品免费av| 国产91视频一区| 久久在线91| 国产大学生av| 91麻豆.com| 欧美人禽zoz0强交| 色婷婷香蕉在线一区二区| 在线观看免费视频a| 亚洲精品久久久久久久久久久久久 | 网爆门在线观看| 亚洲亚洲人成综合网络| 亚洲午夜无码久久久久| 精品国偷自产国产一区| 超碰国产在线| 国内精品久久久久久中文字幕| 欧美美女被草| 久久综合毛片| 午夜精品999| 国产视频手机在线播放| 成人毛片老司机大片| 国产无遮挡在线观看| 舔着乳尖日韩一区| 999精品国产| 亚洲天堂精品在线| 久久成人激情视频| 欧美肥老太太性生活| 国产九九九九九| 国产一区欧美二区| 久久久久亚洲av无码a片| 午夜久久久久久久久| av网站免费大全| 在线一区二区日韩| 自由日本语热亚洲人| 国产成人精品免费视频大全最热 | 日韩污视频在线观看| 欧美一区二区久久| 永久免费av片在线观看全网站| 18一19gay欧美视频网站| 日韩欧美另类中文字幕| 一区不卡字幕| 日韩主播视频在线| 丰满少妇一区二区三区| 亚洲大片精品永久免费| 国产男女猛烈无遮挡| 最近2019年日本中文免费字幕 | 欧美~级网站不卡| 日本特黄a级片| 国产网站一区二区三区| 黄色片视频免费| 亚洲欧美一区二区精品久久久| 成人免费观看在线观看| 国产精品一级久久久| 欧美体内she精视频在线观看| 永久免费黄色片| 亚洲人成网站在线| 一级爱爱免费视频| 色av中文字幕一区| 国产麻豆一区| 亚洲精品高清国产一线久久| 日韩在线一二三区| 影音先锋制服丝袜| 在线观看网站黄不卡| 国产资源在线播放| 国产精品久久久999| 日本一本不卡| 奇米影视四色在线| 国产精品麻豆网站| 国产精品久久无码一三区| 久久国内精品一国内精品| www.久久热| 2018中文字幕第一页| 成人黄页在线观看| 啦啦啦免费高清视频在线观看| 亚洲精品国产拍免费91在线| 激情国产在线| 欧美人与物videos另类| 日本伊人精品一区二区三区观看方式 | 日本视频网站在线观看| 国产亚洲人成网站在线观看| 91福利精品在线观看| 一区二区三视频| 国产精品一二一区| 国产午夜精品无码| 亚洲精品中文字幕av| 久久免费资源| 国产又粗又猛又爽又黄的网站| 99久久亚洲一区二区三区青草| 波多野结衣视频免费观看| www.日韩av.com| 福利在线一区| 热久久精品免费视频| 日韩美女精品在线| 六月婷婷中文字幕| 国产精品久久久久av| 欧美精品色网| 日本xxx在线播放| 欧美老年两性高潮| h片精品在线观看| 日本一区免费在线观看| 精品在线亚洲视频| 99精品视频99| 日韩中文字幕在线精品| ccyy激情综合| 嫩草av久久伊人妇女超级a| 亚洲精品国产无天堂网2021| 天天摸天天碰天天爽天天弄| 国产欧美精品一区二区三区-老狼| 女人天堂亚洲aⅴ在线观看| 制服丝袜第二页| 91精品国产综合久久久久| 中文字幕不卡三区视频| 日本天堂免费a| 国产亚洲一区字幕| 亚洲精品字幕在线观看|