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

首頁 > 開發 > Java > 正文

詳解Spring cloud使用Ribbon進行Restful請求

2024-07-14 08:40:17
字體:
來源:轉載
供稿:網友

寫在前面

本文由markdown格式寫成,為本人第一次這么寫,排版可能會有點亂,還望各位海涵。
 主要寫的是使用Ribbon進行Restful請求,測試各個方法的使用,代碼冗余較高,比較適合初學者,介意輕噴謝謝。

前提

  1. 一個可用的Eureka注冊中心(文中以之前博客中雙節點注冊中心,不重要)
  2. 一個連接到這個注冊中心的服務提供者
  3. 一個ribbon的消費者

注意:文中使用@GetMapping、@PostMapping、@PutMapping、@DeleteMapping等注解需要升級 spring-boot-starter-parent版本到1.5.9.REALEASE以上(1.3.7.RELEASE版本沒有這些注解)

建議:每個微服務應用都有自己的spring-boot-maven-plugin和maven-compiler-plugin并指定jdk編譯版本為1.8 ,指定方式如下,pom.xml中添加

  <build>    <plugins>      <plugin>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-maven-plugin</artifactId>      </plugin>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-compiler-plugin</artifactId>        <configuration>          <source>1.8</source>          <target>1.8</target>        </configuration>      </plugin>    </plugins>  </build>

測試項目構建

Eureka注冊中心:參考注冊中心的搭建 
 服務提供者:參考注冊服務提供者
ribbon消費者:參考服務發現與消費

項目搭建完后,記得按照這幾個教程中提到的配置hosts文件

為了防止項目中的RequestMapping相同,這里就刪除所有的controller類(服務提供者和消費者),接下來我會將每個restful方法都封裝成一個類,方便大家查看

Get請求

getForEntity:此方法有三種重載形式,分別為:

  1. getForEntity(String url, Class<T> responseType)
  2. getForEntity(String url, Class<T> responseType, Object... uriVariables)
  3. getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
  4. getForEntity(URI url, Class<T> responseType)

注意:此方法返回的是一個包裝對象ResponseEntity<T>其中T為responseType傳入類型,想拿到返回類型需要使用這個包裝類對象的getBody()方法

getForObject:此方法也有三種重載形式,這點與getForEntity方法相同:

  1. getForObject(String url, Class<T> responseType)
  2. getForObject(String url, Class<T> responseType, Object... uriVariables)
  3. getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
  4. getForObject(URI url, Class<T> responseType)

注意:此方法返回的對象類型為responseType傳入類型

為了方便測試,這里分別在服務提供者和服務消費者中提供相同的User類,用于方便測試

package com.cnblogs.hellxz;/** * 用于測試的pojo */public class User {  private String name;  private String sex;  private String phone;  public User(){}  public User(String name, String sex, String phone) {    this.name = name;    this.sex = sex;    this.phone = phone;  }  public String toString(){    return "user:{"        +"name: " + name + ", "        +"sex: " + sex + ", "        +"phone: " + phone        +" }";  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public String getSex() {    return sex;  }  public void setSex(String sex) {    this.sex = sex;  }  public String getPhone() {    return phone;  }  public void setPhone(String phone) {    this.phone = phone;  }}

下邊我們在服務提供者處創建一個GetRequestController

package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.*;/** * @Author : Hellxz * @Description: 服務提供者 * @Date : 2018/4/18 11:36 */@RestControllerpublic class GetRequestController {  @Autowired  private DiscoveryClient client; //注入發現客戶端  private final Logger logger = Logger.getLogger(GetRequestController.class);  /**   * go straight test   */  @GetMapping(value = "/hello")  public String hello(){    //獲取服務實例,作用為之后console顯示效果    ServiceInstance serviceInstance = client.getLocalServiceInstance();    logger.info("/hello host:"+serviceInstance.getHost()+" service_id:" +serviceInstance.getServiceId());    return "hello";  }  /**   * parameter test   */  @GetMapping(value = "/greet/{dd}")  public String greet(@PathVariable String dd){    ServiceInstance serviceInstance = client.getLocalServiceInstance();    logger.info("/hello host:"+serviceInstance.getHost()+" service_id:" +serviceInstance.getServiceId());    return "hello "+dd;  }  /**   * 返回測試對象   */  @GetMapping("/user")  public User getUser(){    ServiceInstance serviceInstance = client.getLocalServiceInstance();    logger.info("/user "+serviceInstance.getHost()+" port:"+serviceInstance.getPort()+" serviceInstanceid:"+serviceInstance.getServiceId());    return new User("hellxz","male", "123456789");  }  /**   * 根據名稱返回對象,這里模擬查數據庫操作   */  @GetMapping("/user/{name}")  public User getUserSelect(@PathVariable String name){    ServiceInstance serviceInstance = client.getLocalServiceInstance();    logger.info("/user "+serviceInstance.getHost()+" port:"+serviceInstance.getPort()+" serviceInstanceid:"+serviceInstance.getServiceId());    if(name.isEmpty()){      return new User();    }else if(name.equals("hellxz")){      return new User("hellxz","male", "123456789");    }else{      return new User("隨機用戶","male", "987654321");    }  }}

接下來我們在服務消費者項目中創建GetRequestController

package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;import java.util.HashMap;import java.util.Map;/** * @Author : Hellxz * @Description: ribbon消費者應用Controller,get請求 * @Date : 2018/4/16 15:54 */@RestControllerpublic class GetRequestController {  private Logger logger = Logger.getLogger(GetRequestController.class);  @Autowired  //注入restTemplate  private RestTemplate restTemplate;  /**   * ResponseEntity<T> getForEntity(String url, Class<T> responseType)   * T getBody() 以下此方法相同   */  @GetMapping(value="/entity/noparam")  public String noParamGetForEntity(){    //這里注釋掉,因為之前想當然使用了直鏈訪問服務提供者的接口,這樣是不會返回結果的,而且會報錯    //return restTemplate.getForEntity("http://localhost:8080/hello",String.class).getBody();    //使用restTemplate調用微服務接口    return restTemplate.getForEntity("http://hello-service/hello", String.class).getBody();  }  /**   * ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)   */  @GetMapping("/entity/type")  public User getForEntityIdentifyByType(){    //不傳參返回指定類型結果    ResponseEntity<User> entity = restTemplate.getForEntity("http://hello-service/user", User.class);    User body = entity.getBody();    logger.info("user:"+body);    return body;    //以上可簡寫為//    return restTemplate.getForEntity("http://hello-service/user", User.class).getBody();  }  /**   * ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)   * 使用占位符對參數進行替換,內部使用String.format方法實現   */  @GetMapping(value="/entity")  //如果接收的參數是使用參數沒有使用?有則使用@PathVariable,否則用@RequestParam  public String getForEntityByQuestionMarkParam(@RequestParam("name") String name){    //主要測試getEntity方法,這里測試直接傳參    return restTemplate.getForEntity("http://hello-service/greet/{1}", String.class, name).getBody();  }  /**   * getForEntity方法內部會提取map中,以占位符為key的值作為參數回填入url中   * ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)   */  @GetMapping(value="/entity/map/{name}")  //如果接收的參數是使用參數沒有使用?有則使用@PathVariable,否則用@RequestParam  public String getForEntityByMap(@PathVariable("name") String name){    //主要測試getEntity方法,這里測試map傳參    Map<String, String> reqMap = new HashMap();    reqMap.put("name",name);    return restTemplate.getForEntity("http://hello-service/greet/{name}", String.class,reqMap).getBody();  }  /**   * ResponseEntity<T> getForObject(URI url, Class<T> responseType)   */  @GetMapping("/entity/uri")  public String getForEntityByURI(){    //使用uri進行傳參并訪問    UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/greet/{name}").build().expand("laozhang").encode();    URI uri = uriComponents.toUri();    return restTemplate.getForEntity(uri, String.class).getBody();  }  /**   * T getForObject(String url, Class<T> responseType)   */  @GetMapping("/object")  public User getForObjectWithNoParam(){    //相比getForEntity方法,獲取對象可以省去調用getBody    return restTemplate.getForObject("http://hello-service/user", User.class);  }  /**   * T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)   */  @GetMapping("/object/map")  public User getForObjectByMap(){    //使用map傳參    Map<String, String> paramMap = new HashMap<>();    paramMap.put("name","hellxz");    return restTemplate.getForObject("http://hello-service/user", User.class, paramMap);  }  /**   * T getForObject(String url, Class<T> responseType, Object... uriVariables)   */  @GetMapping("/object/param/{name}")  public User getForObjectByParam(@PathVariable String name){    return restTemplate.getForObject("http://hello-service/user/{name}",User.class, name);  }  /**   * T getForObject(URI url, Class<T> responseType)   */  @GetMapping("/object/uri/{name}")  public User getForObjectByURI(@PathVariable String name){    UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/user/{name}")                                        .build().expand(name).encode();    URI uri = uriComponents.toUri();    return restTemplate.getForObject(uri,User.class);  }}

先啟動注冊中心,然后通過訪問消費者對外提供的接口進行測試,這些都是本人實際操作過的了,這里就不寫測試了

Post請求

post請求和get請求都有*ForEntity和*ForObject方法,其中參數列表有些不同,除了這兩個方法外,還有一個postForLocation方法,其中postForLocation以post請求提交資源,并返回新資源的URI

postForEntity:此方法有三種重載形式,分別為:

  1. postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
  2. postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
  3. postForEntity(URI url, Object request, Class<T> responseType)

注意:此方法返回的是一個包裝對象ResponseEntity<T>其中T為responseType傳入類型,想拿到返回類型需要使用這個包裝類對象的getBody()方法

postForObject:此方法也有三種重載形式,這點與postForEntity方法相同:

  1. postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
  2. postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
  3. postForObject(URI url, Object request, Class<T> responseType)

注意:此方法返回的對象類型為responseType傳入類型

postForLocation:此方法中同樣有三種重載形式,分別為:

  1. postForLocation(String url, Object request, Object... uriVariables)
  2. postForLocation(String url, Object request, Map<String, ?> uriVariables)
  3. postForLocation(URI url, Object request)

注意:此方法返回的是新資源的URI,相比getForEntity、getForObject、postForEntity、postForObject方法不同的是這個方法中無需指定返回類型,因為返回類型就是URI,通過Object... uriVariables、Map<String, ?> uriVariables進行傳參依舊需要占位符,參看postForEntity部分代碼

按照之前的方式,我們分別在提供服務者和消費者的項目中分別創建PostRequestController

如下服務者PostRequestController代碼如下:

package com.shunneng.springcloudhelloworld;import org.apache.log4j.Logger;import org.springframework.web.bind.annotation.*;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;/** * @Author : Hellxz * @Description: * @Date : 2018/4/18 10:21 */@RestControllerpublic class PostRequestController {  private Logger logger = Logger.getLogger(PostRequestController.class);  /**   * 接收一個對象再返回回去,postForEntity/postForObject方法通用   */  @PostMapping("/user")  public User returnUserByPost(@RequestBody User user){    logger.info("/use接口 "+user);    if(user == null) return new User("這是一個空對象","","");    return user;  }  /**   * 測試PostForEntity方法的參數,可以直接看輸出判斷結果了   */  @PostMapping("/user/{str}")  public User returnUserByPost(@PathVariable String str, @RequestBody User user){    logger.info("/user/someparam 接口傳參 name:"+str +" "+user);    if(user == null) return new User("這是一個空對象","","");    return user;  }  /**   * 為postForLocation方法返回URI   */  @PostMapping("/location")  public URI returnURI(@RequestBody User user){    //這里模擬一個url,真實資源位置不一定是這里    UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/location")                                                .build().expand(user).encode();    URI toUri = uriComponents.toUri();    //這里不知道是什么問題,明明生成uri了,返回之后好像并沒有被獲取到    logger.info("/location uri:"+toUri);    return toUri;  }}

消費端PostRequestController代碼:

package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;/** * @Author : Hellxz * @Description: Ribbon消費者post請求controller * @Date : 2018/4/18 9:47 */@RestControllerpublic class PostRequestController {  private Logger logger = Logger.getLogger(PostRequestController.class);  @Autowired  private RestTemplate restTemplate;  /**   * ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType)   * 其中參數url不多說,Object request如果是不是一個HttpEntity對象,會自動轉換為HttpEntity對象,視作完整的body來處理;   * 如果是HttpEntity對象,那么會被直接當做body處理并且包含header內容。   * 以下對于重寫的方法就不多說了,使用方法大體同getForEntity,如果僅是簡單post對象,那么使用不帶Object...variables或Map variables的方法即可。   * postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)   * postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)   *   * 這里詳細說下我遇到的坑:   * 1、其他幾個重載方法的最后邊的Object...variables和Map variables都是對之前的url進行操作的,   *   也就是說,在post請求的url中使用占位符進行傳參,而如果在url中沒有使用占位符,那么這些最后傳的參數是無效的!   * 2、方法中Object request這個對象如果和服務提供者的接收參數類型相同,那么服務提供者僅需使用@RequestBody接收參數即可。   * 3、如果二者都使用了,這就比較有趣了,需要一邊通過@PathVariable注解接收uri中的參數,一邊還需要@RequestBody接收對象或RequestParam按字段接收參數!   * 4、如果報錯了,請仔細看看我上邊寫的三條,并注意服務提供者的參數接收注解的使用等。   */  @PostMapping("/entity")  public User postForEntity(){    User user = new User("hellxz1","1","678912345");    ResponseEntity<User> entity = restTemplate.postForEntity("http://hello-service/user/{str}", user, User.class, "測試參數");    User body = entity.getBody(); //所有restTemplate.*ForEntity方法都是包裝類,body為返回類型對象    return body;  }  /**   * 使用URI傳參,測試結果會顯示在服務提供者的終端中   * ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType)   */  @PostMapping("/entity/uri")  public User postForEntityByURI(){    User user = new User("老張","1","678912345");    //這里只是將url轉成URI,并沒有添加參數    UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/user")                                        .build().encode();    URI toUri = uriComponents.toUri();    //使用user傳參    User object = restTemplate.postForObject(toUri, user, User.class);    return object;  }  /**   * 這里測試postForObject方法,需要注意的參數如上述方法的描述,區別只是不需要getBody了,這里就不再累述了   * postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)   * postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)   */  @PostMapping("/object")  public User postForObject(){    User user = new User("hellxz2","1","123654987");    //這里url傳1是為了調用服務者項目中的一個接口    User responseBody = restTemplate.postForObject("http://hello-service/user/1", user, User.class);    return responseBody;  }  /**   * post請求還有一種:postForLocation,這里也同樣有三種重載,除了無需指定返回類型外,用法相同,返回類型均為URI,也就不累述了   * postForLocation(String url, Object request, Object... uriVariables)   * postForLocation(String url, Object request, Map<String, ?> uriVariables)   * postForLocation(URI url, Object request)   */  @PostMapping("/location")  public URI postForLocation(){    User user = new User("hellxz3","1","987654321");    URI uri = restTemplate.postForLocation("http://hello-service/location", user);    //不知道為什么返回來是空,這個方法僅供參考吧,如果知道是什么情況,我會回來改的    logger.info("/location uri:"+uri);    return uri;  }}

Put請求&&Delete請求

put請求相對于get和post請求方法來的更為簡單,其中無需指定put請求的返回類型,當然也沒有返回值,也是三種重載,和之前寫的基本一致,這里就不想多說了,delete請求和put請求都是沒有返回值的,這里再特地重復寫也沒什么意思,這里先分別列出這兩個請求的方法,代碼寫在一個類中了

put請求方法如下:

  1. put(String url, Object request, Object... uriVariables)
  2. put(String url, Object request, Map<String, ?> uriVariables)
  3. put(URI url, Object request)

delete請求方法如下:

  1. delete(String url, Object... uriVariables)
  2. delete(String url, Map<String, ?> uriVariables)
  3. delete(URI url)

在提供服務者項目中添加PutAndDeleteRequestController,代碼如下

package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.web.bind.annotation.*;/** * @Author : Hellxz * @Description: 服務提供者 put&delete請求controller * @Date : 2018/4/19 14:11 */@RestControllerpublic class PutAndDeleteRequestController {  private Logger logger = Logger.getLogger(PutAndDeleteRequestController.class);  @PutMapping("/put")  public void put(@RequestBody User user){    logger.info("/put "+user);  }  @DeleteMapping("/delete/{id}")  public void delete(@PathVariable Long id){    logger.info("/delete id:"+id);  }}

在提供服務者項目中添加PutAndDeleteRequestController,代碼如下

package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;/** * @Author : Hellxz * @Description: put請求、delete請求,重載的參數與上述demo基本相同,不予列出 * @Date : 2018/4/19 13:43 */@RestControllerpublic class PutRequestController {  private Logger logger = Logger.getLogger(PostRequestController.class);  @Autowired  private RestTemplate restTemplate;  /**   * put請求示例,一般put請求多用作修改   */  @PutMapping("/put")  public void put(@RequestBody User user){    restTemplate.put("http://hello-service/put",user);  }  /**   * delete請求示例   */  @DeleteMapping("/del/{id}")  public void delete(@PathVariable Long id){    restTemplate.delete("http://hello-service/delete/{1}", id);  }}

結語

這篇博文使用markdown寫成,第一次寫不知道如何將代碼塊中加入序號以及折疊代碼功能,這可能不是一篇好文章,但是寫這篇博文寫了快兩天,有什么好的建議歡迎評論交流,

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品99久久久久中文字幕| 欧美大片在线影院| 久久精品国产亚洲一区二区| 亚洲一区999| 国产精品网站大全| 51色欧美片视频在线观看| 国产精品香蕉国产| 青草热久免费精品视频| 欧美激情精品在线| 亚洲国模精品私拍| 亚洲视频在线观看网站| 亚洲精品国精品久久99热| 91wwwcom在线观看| 亚洲免费一在线| 九九热在线精品视频| 精品视频中文字幕| 久久成人国产精品| 欧美激情一二三| 欧美日韩高清区| 久久精品亚洲国产| 日韩在线高清视频| 亚洲精美色品网站| 成人黄色在线免费| 日韩在线资源网| 91成人免费观看网站| 日本精品va在线观看| 国产一区二区三区直播精品电影| 亚洲午夜久久久久久久| 久久综合久久美利坚合众国| 欧美激情乱人伦一区| 91在线免费视频| 精品久久中文字幕| 久久成人18免费网站| 亚洲国产精品成人va在线观看| 亚洲天堂影视av| 北条麻妃一区二区三区中文字幕| 国产精品久久久久久久久久久久久久| 久久91亚洲精品中文字幕奶水| 亚洲午夜国产成人av电影男同| 中文字幕亚洲欧美日韩高清| 都市激情亚洲色图| 日韩三级成人av网| 久久久久久91| 九九热这里只有精品6| 91影视免费在线观看| 青青草原一区二区| 日韩av手机在线看| 欧美一级在线亚洲天堂| 久久免费少妇高潮久久精品99| 欧美一区二区三区精品电影| 国产精品视频xxxx| 91免费人成网站在线观看18| 日韩美女免费观看| 久久精品久久久久久国产 免费| 国产精品久久久久久久av电影| 欧美大肥婆大肥bbbbb| 中文字幕精品视频| 久热精品视频在线| 国产精品一区二区在线| 91成品人片a无限观看| 日韩大陆毛片av| 日韩一二三在线视频播| 亚洲精品之草原avav久久| 亚洲欧美国产日韩中文字幕| 欧美黑人xxxⅹ高潮交| 尤物九九久久国产精品的特点| 欧美在线激情网| 亚洲直播在线一区| 久久免费国产精品1| 亚洲国产精久久久久久久| 日韩欧美国产黄色| 亚洲欧美日本另类| 精品久久久久久中文字幕一区奶水| 伊人久久大香线蕉av一区二区| 日韩激情视频在线播放| 亚洲香蕉伊综合在人在线视看| 狠狠综合久久av一区二区小说| 国产精品旅馆在线| 欧美日韩国产中字| 精品一区二区亚洲| 91在线观看免费网站| 亚洲免费精彩视频| 中文字幕亚洲在线| 精品成人乱色一区二区| 欧美高清在线视频观看不卡| 亚洲欧洲第一视频| 久久亚洲精品网站| 91手机视频在线观看| 亚洲精品自拍第一页| 久久久久一本一区二区青青蜜月| 亚洲va码欧洲m码| 一区二区中文字幕| 日韩精品极品在线观看播放免费视频| 国产精品一区二区三区免费视频| 亚洲午夜激情免费视频| 欧美在线视频一区二区| 国产精品男女猛烈高潮激情| 91亚洲国产成人精品性色| 欧美日韩高清区| 国产视频在线一区二区| 91国语精品自产拍在线观看性色| 色爱av美腿丝袜综合粉嫩av| 国产一区二区三区在线观看视频| 亚洲黄色www网站| 日韩av一卡二卡| 久久99精品国产99久久6尤物| 亚洲精品成人久久电影| 亚洲精品中文字| 欧美视频在线视频| 国产欧美日韩高清| 亚洲品质视频自拍网| 55夜色66夜色国产精品视频| 第一福利永久视频精品| 国产精品99久久久久久人| 亚洲激情视频在线观看| 久久久精品免费视频| 亚洲国产天堂网精品网站| 亚洲欧美日韩另类| 亚洲欧洲自拍偷拍| 国模精品视频一区二区| 欧美日韩一区二区三区在线免费观看| 国产z一区二区三区| 国产视频久久久久久久| 91网站在线看| 夜夜嗨av一区二区三区四区| 日韩国产精品一区| 久久久久久久久久国产精品| 久热精品视频在线观看一区| 日本伊人精品一区二区三区介绍| 91在线|亚洲| 伊人av综合网| 欧美国产日韩免费| 中文字幕av一区| 亚洲精品成人久久| 久久成人人人人精品欧| 亚洲精品99久久久久中文字幕| 中文字幕亚洲欧美在线| 91久久在线播放| 欧美亚洲国产成人精品| 亚洲国产欧美日韩精品| 伊人久久男人天堂| 成人在线播放av| 美女国内精品自产拍在线播放| 久久噜噜噜精品国产亚洲综合| 成人国产精品日本在线| 俺也去精品视频在线观看| 亚洲人成网站免费播放| 亚洲精品国产综合久久| 亚洲色图综合久久| 亚洲人成伊人成综合网久久久| 亚洲区免费影片| 国产精品7m视频| 国产精品吴梦梦| 久久久之久亚州精品露出| 亚洲视频在线免费观看| 欧美激情精品久久久| 精品无人国产偷自产在线| 亚洲第一中文字幕在线观看| 日韩精品亚洲精品| 日韩精品在线私人| 91沈先生在线观看| 日韩第一页在线| 亚洲国产精品美女| 亚洲精品成人久久电影|