<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      設計模式——從HttpServletRequestWrapper了解裝飾者模式

      從一個業務開始

      最近項目上緊急需要,為了應付一個不知道啥的安全檢測,我們要給系統追加防XSS注入的功能,這里有經驗的JavaWeb開發就會想到,用過濾器或者基于項目框架的攔截器來做,但是順著這個思路下去,我們會發現一個很尷尬的問題,如果我們在過濾器里把Request對象的參數拿處理校驗(即表明使用了Reuqest的參數),那么后續的過濾器或者Controller都將得到一個“失效”的Request對象,后面的邏輯全線垮掉……

      于是,愛好學習的你就去了某度,某度經過檢索,給了你一個頁面……,又經過重重查詢和閱讀,你終于有了解決方案:

      我們可以利用HttpServletRequestWrapper包裝HttpServletRequest,在Wrapper中實現參數的修改,然后用HttpServletRequestWrapper替換HttpServletRequest,這樣就實現了參數的修改設置。

      這時候,喜歡刨根問底的你,就想看看這個HttpServletRequestWrapper究竟是什么,于是好奇之旅開始。

      HttpServletRequestWrapper源碼

      說白了HttpServletRequestWrapper是HttpServletRequest裝飾類,什么是裝飾類,我們后面再說,這一節里,先來看看它的落地實現,也就是源碼。

      整體關系

      這里我就先說結論吧:

      • HttpServletRequestWrapper繼承了ServletRequestWrapper,實現了HttpServletRequest接口;
      • ServletRequestWrapper和HttpServletRequest都實現了ServletRequest接口;
      • ServletRequestWrapper是對ServletRequest的包裝;
      • HttpServletRequestWrapper是對HttpServletRequest的包裝;

      實際的繼承關系如下圖:

       

       

      ServletRequestWrapper的源碼:

      package javax.servlet;
      
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.util.Enumeration;
      import java.util.Locale;
      import java.util.Map;
      
      /**
       * ServletRequestWrapper提供了一個簡便實現類,在對ServletRequest有改動需求的時,可以重寫此類,之后Request的操作都會經過重寫的類.
       */
      public class ServletRequestWrapper implements ServletRequest {
          
          /**
           * ServletRequestWrapper持有ServletRequest的實例.
           */
          private ServletRequest request;
      
          /**
           * 構建ServletRequestWrapper,傳入ServletRequest的值.
           */
          public ServletRequestWrapper(ServletRequest request) {
              if (request == null) {
                  throw new IllegalArgumentException("Request cannot be null");
              }
              this.request = request;
          }
      
          /**
           * 獲取ServletRequest實例.
           */
          public ServletRequest getRequest() {
              return this.request;
          }
      
          /**
           * 設置ServletRequest實例.
           * @param request ServletRequest.
           */
          public void setRequest(ServletRequest request) {
              if (request == null) {
                  throw new IllegalArgumentException("Request cannot be null");
              }
              this.request = request;
          }
      
          /**
           * 獲取Servlet的屬性.
           */
          public Object getAttribute(String name) {
              return this.request.getAttribute(name);
          }
      
          /**
           * 獲取所有屬性枚舉格式.
           */
          public Enumeration getAttributeNames() {
              return this.request.getAttributeNames();
          }
      
          /**
           * 返回請求中輸入內容的字符編碼類型,如果沒有定義字符編碼類型就返回空值.
           * @return 字符編碼.
           */
          public String getCharacterEncoding() {
              return this.request.getCharacterEncoding();
          }
      
          /**
           * 設置輸入內容的字符編碼類型.
           * @param env 字符編碼類型.
           * @throws java.io.UnsupportedEncodingException .
           */
          public void setCharacterEncoding(String enc) throws java.io.UnsupportedEncodingException {
              this.request.setCharacterEncoding(enc);
          }
      
          /**
           * 請求內容的長度,如果長度未知就返回-1.
           * @return 請求內容長度.
           */
          public int getContentLength() {
              return this.request.getContentLength();
          }
      
          /**
           * 返回請求數據體的MIME類型CONTENT-TYPE,如果類型未知返回空值.
           * @return
           */
          public String getContentType() {
              return this.request.getContentType();
          }
      
          /**
           * 返回一個輸入流,使用該輸入流以二進制方式讀取請求正文的內容.
           * javax.servlet.ServletInputStream是一個抽象類,繼承自InputStream.
           * @return .
           * @throws IOException .
           */
          public ServletInputStream getInputStream() throws IOException {
              return this.request.getInputStream();
          }
      
          /**
           * 根據指定參數名獲取參數值.
           * @param name 參數名.
           * @return 參數值.
           */
          public String getParameter(String name) {
              return this.request.getParameter(name);
          }
      
          /**
           * 獲取參數的Map形式,包括所有參數.
           * @return 參數Map.
           */
          public Map getParameterMap() {
              return this.request.getParameterMap();
          }
      
          /**
           * 獲取所有參數名的枚舉.
           * @return 參數名枚舉.
           */
          public Enumeration getParameterNames() {
              return this.request.getParameterNames();
          }
      
          /**
           * 根據指定屬性名獲取參數值數組.
           * @param name 參數名.
           * @return 參數值數組.
           */
          public String[] getParameterValues(String name) {
              return this.request.getParameterValues(name);
          }
      
          /**
           * 返回請求使用的協議信息.格式為:協議/主版本號.次版本號.例如:http/1.0.
           * @return
           */
          public String getProtocol() {
              return this.request.getProtocol();
          }
      
          /**
           * 返回請求所使用的URL的模式.若http、https等.
           * @return 模式.
           */
          public String getScheme() {
              return this.request.getScheme();
          }
      
          /**
           * 返回請求發送到的服務器的主機名.
           * @return 主機名.
           */
          public String getServerName() {
              return this.request.getServerName();
          }
      
          /**
           * 返回請求發送到的服務器的端口號.
           * @return 端口號.
           */
          public int getServerPort() {
              return this.request.getServerPort();
          }
      
          /**
           * 返回BufferedReader對象,以字節數據方式讀取請求正文.
           * @return .
           * @throws IOException .
           */
          public BufferedReader getReader() throws IOException {
              return this.request.getReader();
          }
      
          /**
           * 返回發送請求的客戶端或最后一個代理服務器的IP地址.
           * @return IP地址.
           */
          public String getRemoteAddr() {
              return this.request.getRemoteAddr();
          }
      
          /**
           * 返回發送請求的客戶端或最后一個代理服務器的主機名.
           * @return 主機名.
           */
          public String getRemoteHost() {
              return this.request.getRemoteHost();
          }
      
          /**
           * 根據傳遞的屬性名和屬性值設置Request屬性.
           * @param name 屬性名.
           * @param o 屬性值.
           */
          public void setAttribute(String name, Object o) {
              this.request.setAttribute(name, o);
          }
      
          /**
           * 從Request中刪除指定的屬性名對應的值.一般使用此方法.
           * @param name 屬性名.
           */
          public void removeAttribute(String name) {
              this.request.removeAttribute(name);
          }
      
          /**
           * 根據客戶端傳遞的Accept-Language對應的區域設置.
           * 若客戶端未指定Accept-Language,則返回服務器默認語言環境.
           * @return
           */
          public Locale getLocale() {
              return this.request.getLocale();
          }
      
          /**
           * 返回Locale對象的枚舉,從首選區域開始按降序返回基于Accept-Language頭的客戶端可接受的區域.
           * 如果客戶機請求不提供Accept-Language頭,此方法返回包含一個Locale的枚舉,即是服務器默認語言環境對應的Locale.
           * @return
           */
          public Enumeration getLocales() {
              return this.request.getLocales();
          }
      
          /**
           * 指示是否使用安全通道(如HTTPS)發出此請求.
           */
          public boolean isSecure() {
              return this.request.isSecure();
          }
      
          /**
           * 返回RequestDispatcher對象,作為path所定位的資源的封裝.
           * RequestDispatcher用于服務器請求轉發.
           * @param path 相對路徑或絕對路徑.
           * @return RequestDispatcher.
           */
          public RequestDispatcher getRequestDispatcher(String path) {
              return this.request.getRequestDispatcher(path);
          }
      
          /**
           * @deprecated
           * Servlet API 2.1開始已不推薦使用此API.
           * 取得文件在服務器上的絕對路徑.
           * @param path 相對路徑.
           * @return 絕對路徑.
           */
          public String getRealPath(String path) {
              return this.request.getRealPath(path);
          }
      
          /**
           * 返回發送請求的客戶端或者最后一個代理服務器的IP源端口, 這個方法是在Servlet 2.4規范中新增的方法.
           * @return 端口號.
           */
          public int getRemotePort() {
              return this.request.getRemotePort();
          }
      
          /**
           * 返回接收到請求的IP接口的主機名,這個方法是在Servlet 2.4規范中新增的方法.
           * @return 主機名.
           */
          public String getLocalName() {
              return this.request.getLocalName();
          }
      
          /**
           * 返回接收到請求的網絡接口的IP地址,這個方法是在Servlet 2.4規范中新增的方法.
           * @return IP地址.
           */
          public String getLocalAddr() {
              return this.request.getLocalAddr();
          }
      
          /**
           * 返回接收到請求的網絡接口的IP端口號,這個方法是在Servlet 2.4規范中新增的方法.
           * @return 端口號.
           */
          public int getLocalPort() {
              return this.request.getLocalPort();
          }
      
      }

      HttpServletRequestWrapper的源碼:

      package javax.servlet.http;
      
      import javax.servlet.ServletRequestWrapper;
      import java.util.Enumeration;
      
      /**
       * HttpServletRequestWrapper提供了一個簡便實現不了,在對HttpServletRequest有改動需求的時,可以重寫此類,之后Request的操作都會經過重寫的類.
       */
      public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {
      
          /**
           * Constructs.
           */
          public HttpServletRequestWrapper(HttpServletRequest request) {
              super(request);
          }
          
          /**
           * 獲取HttpServletRequest.
           * @return HttpServletRequest.
           */
          private HttpServletRequest _getHttpServletRequest() {
              return (HttpServletRequest) super.getRequest();
          }
      
          /**
           * 返回認證類型.
           * 所有Servlet容器都支持basic、form、client_cert,digest不一定支持.
           * 若不支持,則返回null.
           */
          public String getAuthType() {
              return this._getHttpServletRequest().getAuthType();
          }
      
          /**
           * 獲取請求中帶有的Cookie信息.
           */
          public Cookie[] getCookies() {
              return this._getHttpServletRequest().getCookies();
          }
      
          /**
           * 以長整數形式返回一個特定的請求頭,該長整數代表一個Date對象. 
           * 該方法可以用在包含時間信息的header中,如:If-Modified-Since.
           * @param name 頭名稱.
           * @return 頭值.
           */
          public long getDateHeader(String name) {
              return this._getHttpServletRequest().getDateHeader(name);
          }
      
          /**
           * 根據指定的頭名稱獲取頭的值.
           * 若存在多個,則返回第一個.
           * @param name 頭名稱.
           * @return 頭值.
           */
          public String getHeader(String name) {
              return this._getHttpServletRequest().getHeader(name);
          }
      
          /**
           * 根據指定的頭名稱獲取頭值的枚舉.
           * 若沒有找到,則返回空的枚舉.
           * @param name 頭名稱.
           * @return 頭值.
           */
          public Enumeration getHeaders(String name) {
              return this._getHttpServletRequest().getHeaders(name);
          }
      
          /**
           * 獲取所有的頭的枚舉.
           * @return 頭的枚舉.
           */
          public Enumeration getHeaderNames() {
              return this._getHttpServletRequest().getHeaderNames();
          }
      
          /**
           * 根據指定頭名稱獲取int類型的值.若未找到則返回-1,如不是int類型,則會拋出NumberFormatException異常.
           * @param name 頭名稱.
           * @return 頭值.
           */
          public int getIntHeader(String name) {
              return this._getHttpServletRequest().getIntHeader(name);
          }
      
          /**
           * 獲取HTTP方法,如:GET、POST、PUT等.
           * @return 方法名.
           */
          public String getMethod() {
              return this._getHttpServletRequest().getMethod();
          }
      
          /**
           * 官網解釋:
           *  返回與客戶端發出此請求時發送的URL相關聯的任何額外路徑信息.
           *  額外的路徑信息跟隨servlet路徑,但位于查詢字符串之前,并以"/"字符開頭.
           * 例如:url-pattern配置為/demo/*,請求URL為http://localhost/Pro/demo/htm/index.html,則pathInfo為/htm/index.html.
           * @return
           */
          public String getPathInfo() {
              return this._getHttpServletRequest().getPathInfo();
          }
      
          /**
           * 返回servlet名稱之后、
           *      查詢字符串之前的任何額外路徑信息,并將其轉換為實際路徑. 
           *      與轉換的CGI變量PATH U的值相同
           * @return
           */
          public String getPathTranslated() {
              return this._getHttpServletRequest().getPathTranslated();
          }
      
          /**
           * 返回項目根路徑.
           * 例如:url-pattern配置為/demo/*,請求URL為http://localhost/Pro/demo/htm/index.html,則contextPath為/demo.
           * @return 項目根路徑.
           */
          public String getContextPath() {
              return this._getHttpServletRequest().getContextPath();
          }
      
          /**
           * 獲得請求中的查詢字符串,例如a=1&b=2這樣的格式.
           * @return 查詢字符串.
           */
          public String getQueryString() {
              return this._getHttpServletRequest().getQueryString();
          }
      
          /**
           * 如果用戶已經過驗證,則返回發出此請求的用戶的登錄信息,如果用戶未經過驗證,則返回 null.
           * 用戶名是否隨每個后續請求發送取決于瀏覽器和驗證類型,返回的值與 CGI變量REMOTE_USER的值相同.
           * @return 用戶信息.
           */
          public String getRemoteUser() {
              return this._getHttpServletRequest().getRemoteUser();
          }
      
          /**
           * 返回一個 boolean值,指示指定的邏輯"角色"中是否包含經過驗證的用戶.
           * 角色和角色成員關系可使用部署描述符定義.
           * 如果用戶沒有經過驗證,則該方法返回 false.
           * @param role 角色.
           * @return 已驗證用戶是否屬于某種角色.
           */
          public boolean isUserInRole(String role) {
              return this._getHttpServletRequest().isUserInRole(role);
          }
      
          /**
           * 返回包含當前已經過驗證的用戶的名稱的 java.security.Principal對象.
           * 如果用戶沒有經過驗證,則該方法返回 null.
           * @return java.security.Principal或null.
           */
          public java.security.Principal getUserPrincipal() {
              return this._getHttpServletRequest().getUserPrincipal();
          }
      
          /**
           * 獲取請求對應的sessionId.
           * @return sessionId.會話ID.
           */
          public String getRequestedSessionId() {
              return this._getHttpServletRequest().getRequestedSessionId();
          }
      
          /**
           * 請求URL的相對地址,包括服務器路徑,不包括查詢參數.
           * @return 請求URL的相對地址.
           */
          public String getRequestURI() {
              return this._getHttpServletRequest().getRequestURI();
          }
      
          /**
           * 請求的URL地址,包含協議、主機名、端口和服務器路徑,但是不包括查詢參數.
           * @return 請求URL地址.
           */
          public StringBuffer getRequestURL() {
              return this._getHttpServletRequest().getRequestURL();
          }
      
          /**
           * 官方解釋:
           *  返回此請求的URL中調用servlet的部分.
           *  此路徑以"/"字符開頭,包含servlet名稱或到servlet的路徑,但不包含任何額外的路徑信息或查詢字符串.
           *  與CGI變量SCRIPT_NAME的值相同.
           * 其實真是的意思就是,在配置webx.xml或編程式配置時,配置了url-pattern,請求的URL與url-pattern的有效部分重合部分就是servletPath,
           * 也可以理解為url-pattern的有效部分就是servletPath.
           * 例如:url-pattern配置為/demo/*,請求URL為http://localhost/Pro/demo/htm/index.html,則servletPath為/demo.
           * @return
           */
          public String getServletPath() {
              return this._getHttpServletRequest().getServletPath();
          }
      
          /**
           * 獲得請求對應的當前sesson.
           * 在沒有session的情況下:
           *  若create=true,則新創建一個session.
           *  若create=false,則不創建session,返回null.
           * @param create session失效的情況下,是否創建session.
           * @return HttpSession實例.
           */
          public HttpSession getSession(boolean create) {
              return this._getHttpServletRequest().getSession(create);
          }
      
          /**
           * 獲得請求對應的當前sesson.
           * 若沒有session,則創建一個session.
           * @return HttpSession實例.
           */
          public HttpSession getSession() {
              return this._getHttpServletRequest().getSession();
          }
      
          /**
           * 返回session是否有效.
           * @return session是否有效.
           */
          public boolean isRequestedSessionIdValid() {
              return this._getHttpServletRequest().isRequestedSessionIdValid();
          }
      
          /**
           * sessionId是否從Cookie中獲得.
           * @return 若是從Cookie中獲得,返回true,否則返回false.
           */
          public boolean isRequestedSessionIdFromCookie() {
              return this._getHttpServletRequest().isRequestedSessionIdFromCookie();
          }
      
          /**
           * sessionId是否從URL中獲得.
           * @return 若是從URL中獲得,返回true,否則返回false.
           */
          public boolean isRequestedSessionIdFromURL() {
              return this._getHttpServletRequest().isRequestedSessionIdFromURL();
          }
      
          /**
           * @deprecated
           * sessionId是否從URL中獲得.
           * @return 若是從URL中獲得,返回true,否則返回false.
           */
          public boolean isRequestedSessionIdFromUrl() {
              return this._getHttpServletRequest().isRequestedSessionIdFromUrl();
          }
      
      }

       

      其實查看源碼后會發現,ServletRequestWrapper和HttpServletRequestWrapper提供的API完全調用的ServletRequest和HttpServletRequest的API進行實現。在我們進行應用時,使用HttpServletRequestWrapper即可,它同時擁有ServletRequestWrapper和HttpServletRequestWrapper的功能。

      裝飾者模式

      我們來分析一下,HttpServletRequestWrapper的實現流程,首先,所有的源頭,都是ServletRequest這個接口,這個接口其實就是定義來請求功能的;然后HttpServletRequest實現了ServletRequest,它的對象就是我們在Filter常用的Request,ServletRequestWrapper也實現了ServletRequest這個接口,同時它內部又引用了ServletRequest作為成員變量,它和HttpServletRequest就有同樣了API,屬于同一層級,這時候,HttpServletRequestWrapper繼承了ServletRequestWrapper同時實現了HttpServletRequest,也就是集兩家之長,又能代替兩家,所以可以滿足我們一開始的場景需求(替換掉HttpServletRequest對象)。

      以上這段分析描述,也就是裝飾模式的實現思路,下面開始介紹一下何為裝飾模式。

      裝飾模式的定義與特點

      裝飾(Decorator)模式的定義:指在不改變現有對象結構的情況下,動態地給該對象增加一些職責(即增加其額外功能)的模式,它屬于對象結構型模式。
      裝飾(Decorator)模式的主要優點有:

        • 裝飾器是繼承的有力補充,比繼承靈活,在不改變原有對象的情況下,動態的給一個對象擴展功能,即插即用
        • 通過使用不用裝飾類及這些裝飾類的排列組合,可以實現不同效果
        • 裝飾器模式完全遵守開閉原則

      其主要缺點是:裝飾模式會增加許多子類,過度使用會增加程序得復雜性

      裝飾模式的結構與實現

      通常情況下,擴展一個類的功能會使用繼承方式來實現。但繼承具有靜態特征,耦合度高,并且隨著擴展功能的增多,子類會很膨脹。如果使用組合關系來創建一個包裝對象(即裝飾對象)來包裹真實對象,并在保持真實對象的類結構不變的前提下,為其提供額外的功能,這就是裝飾模式的目標。下面來分析其基本結構和實現方法。

      模式的結構

      裝飾模式主要包含以下角色。

        1. 抽象構件(Component)角色:定義一個抽象接口以規范準備接收附加責任的對象。
        2. 具體構件(ConcreteComponent)角色:實現抽象構件,通過裝飾角色為其添加一些職責。
        3. 抽象裝飾(Decorator)角色:繼承抽象構件,并包含具體構件的實例,可以通過其子類擴展具體構件的功能。
        4. 具體裝飾(ConcreteDecorator)角色:實現抽象裝飾的相關方法,并給具體構件對象添加附加的責任。

      模板的UML實現關系為:

      細品之后,是不是發現這個UML和HttpServletRequestWrapper那個很相似 !!!!!其實ServletRequest充當了這里抽象構件的角色,ServletRequestWrapper沖到了抽象裝飾的角色,而HttpServletRequest就是具體構件的位置。

      下面看一個簡單的裝飾者實現例子:

      package decorator;
      public class DecoratorPattern {
          public static void main(String[] args) {
              Component p = new ConcreteComponent();
              p.operation();
              System.out.println("---------------------------------");
              Component d = new ConcreteDecorator(p);
              d.operation();
          }
      }
      //抽象構件角色
      interface Component {
          public void operation();
      }
      //具體構件角色
      class ConcreteComponent implements Component {
          public ConcreteComponent() {
              System.out.println("創建具體構件角色");
          }
          public void operation() {
              System.out.println("調用具體構件角色的方法operation()");
          }
      }
      //抽象裝飾角色
      class Decorator implements Component {
          private Component component;
          public Decorator(Component component) {
              this.component = component;
          }
          public void operation() {
              component.operation();
          }
      }
      //具體裝飾角色
      class ConcreteDecorator extends Decorator {
          public ConcreteDecorator(Component component) {
              super(component);
          }
          public void operation() {
              super.operation();
              addedFunction();
          }
          public void addedFunction() {
              System.out.println("為具體構件角色增加額外的功能addedFunction()");
          }
      }

      裝飾模式的應用場景

      前面講解了關于裝飾模式的結構與特點,下面介紹其適用的應用場景,裝飾模式通常在以下幾種情況使用。

        • 當需要給一個現有類添加附加職責,而又不能采用生成子類的方法進行擴充時。例如,該類被隱藏或者該類是終極類或者采用繼承方式會產生大量的子類。
        • 當需要通過對現有的一組基本功能進行排列組合而產生非常多的功能時,采用繼承關系很難實現,而采用裝飾模式卻很好實現。
        • 當對象的功能要求可以動態地添加,也可以再動態地撤銷時。


      裝飾模式在Java中的最著名的應用莫過于 Java I/O 標準庫的設計了。例如,InputStream 的子類 FilterInputStream,OutputStream 的子類 FilterOutputStream,Reader 的子類 BufferedReader 以及 FilterReader,還有 Writer 的子類 BufferedWriter、FilterWriter 以及 PrintWriter 等,它們都是抽象裝飾類。

      下面代碼是為 FileReader 增加緩沖區而采用的裝飾類 BufferedReader 的例子:

      BufferedReader in = new BufferedReader(new FileReader("filename.txt"));
      String s = in.readLine();

      裝飾模式的擴展

      (1) 如果只有一個具體構件而沒有抽象構件時,可以讓抽象裝飾繼承具體構件,其結構圖如圖

      (2) 如果只有一個具體裝飾時,可以將抽象裝飾和具體裝飾合并,其結構圖如圖 


      該類型文章目錄:設計模式匯總


      posted @ 2020-12-31 10:35  糖拌西紅柿  閱讀(2580)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 久久婷婷成人综合色| 精品久久精品午夜精品久久| 性色在线视频精品| 欧美猛少妇色xxxxx猛叫| 成人综合婷婷国产精品久久蜜臀| 国产真实露脸乱子伦原著| 精品国产成人国产在线视| 国产亚洲国产精品二区| 日本大片免A费观看视频三区| 亚洲国产女性内射第一区| 人人爽亚洲aⅴ人人爽av人人片 | 久久久亚洲欧洲日产国码606| 国产av综合色高清自拍| 丰满岳乱妇一区二区三区| 不卡免费一区二区日韩av| 日韩中文字幕亚洲精品 | 久久青青草原亚洲AV无码麻豆| 妓女妓女一区二区三区在线观看 | 日韩午夜福利片段在线观看| 国产日韩精品中文字幕| 天堂资源国产老熟女在线| 女人与牲口性恔配视频免费| 国产精品青青在线观看爽香蕉| 兴国县| 日韩无专区精品中文字幕| 成人白浆一区二区三区在线观看 | 国产乱码精品一品二品| 久久96热在精品国产高清| 久热久精久品这里在线观看| 久久99九九精品久久久久蜜桃| 91精品蜜臀国产综合久久| 一区二区三区不卡国产| 韩国无码AV片午夜福利| 精品国产亚洲区久久露脸| 另类 专区 欧美 制服| 亚洲日本VA中文字幕在线| 一本一道av中文字幕无码| 国产麻豆精品一区一区三区| 中文字幕日韩一区二区不卡| 日本精品aⅴ一区二区三区| 美日韩精品一区三区二区|