1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一文吃透接口調(diào)用神器RestTemplate

        共 25268字,需瀏覽 51分鐘

         ·

        2021-11-07 00:01

        文末可以領(lǐng)取所有系列高清 pdf。

        大家好,我是路人,這是 SpringMVC 系列第 21 篇。

        本文介紹 Spring web 中特別牛逼的一個類 RestTemplate。

        目錄

        • 1、RestTemplate 概述

        • 2、案例代碼

          • 2.1、git 地址

          • 2.2、關(guān)鍵代碼位置

          • 2.3、如何運(yùn)行測試用例?

        • 3、發(fā)送 Get 請求

          • 3.1、普通請求

          • 3.2、url 中含有動態(tài)參數(shù)

          • 3.3、接口返回值為泛型

          • 3.4、下載小文件

          • 3.5、下載大文件

          • 3.6、傳遞頭

          • 3.7、綜合案例:含頭、url 動態(tài)參數(shù)

        • 4、POST 請求

          • 4.1、post 請求常見的 3 種類型

          • 4.2、普通表單請求

          • 4.3、上傳本地文件

          • 4.4、通過流或字節(jié)數(shù)組的方式上傳文件

          • 4.5、復(fù)雜表單:多個普通元素+多文件上傳

          • 4.6、發(fā)送 json 格式數(shù)據(jù):傳遞 java 對象

          • 4.7、發(fā)送 json 格式數(shù)據(jù):傳遞 java 對象,返回值為泛型

          • 4.8、發(fā)送 json 字符串格式數(shù)據(jù)

        • 5、DELETE、PUT、OPTION 請求

          • 5.1、DELETE 請求

          • 5.2、PUT 請求

          • 5.3、OPTIONS 請求

        • 6、集成 HttpClient

        • 7、集成 okhttp

        • 8、總結(jié)

        • 9、SpringMVC 系列目錄

        • 10、更多好文章

        • 11、【路人甲 Java】所有系列高清 PDF

        1、RestTemplate 概述

        發(fā)送 http 請求,估計(jì)很多人用過 httpclient 和 okhttp,確實(shí)挺好用的,而 Spring web 中的 RestTemplate 和這倆的功能類似,也是用來發(fā)送 http 請求的,不過用法上面比前面的 2 位要容易很多。

        spring 框架提供的 RestTemplate 類可用于在應(yīng)用中調(diào)用 rest 服務(wù),它簡化了與 http 服務(wù)的通信方式,統(tǒng)一了 RESTful 的標(biāo)準(zhǔn),封裝了 http 鏈接, 我們只需要傳入 url 及返回值類型即可。相較于之前常用的 HttpClient,RestTemplate 是一種更優(yōu)雅的調(diào)用 RESTful 服務(wù)的方式。

        在 Spring 應(yīng)用程序中訪問第三方 REST 服務(wù)與使用 Spring RestTemplate 類有關(guān)。RestTemplate 類的設(shè)計(jì)原則與許多其他 Spring 模板類(例如 JdbcTemplate、JmsTemplate)相同,為執(zhí)行復(fù)雜任務(wù)提供了一種具有默認(rèn)行為的簡化方法。

        RestTemplate 默認(rèn)依賴 JDK 提供 http 連接的能力(HttpURLConnection),如果有需要的話也可以通過 setRequestFactory 方法替換為例如 Apache HttpComponents、Netty 或 OkHttp 等其它 HTTP library。

        考慮到 RestTemplate 類是為調(diào)用 REST 服務(wù)而設(shè)計(jì)的,因此它的主要方法與 REST 的基礎(chǔ)緊密相連就不足為奇了,后者是 HTTP 協(xié)議的方法:HEAD、GET、POST、PUT、DELETE 和 OPTIONS。例如,RestTemplate 類具有 headForHeaders()、getForObject()、postForObject()、put()和 delete()等方法。

        下面給大家上案例,案例是重點(diǎn),通過案例,把我知道的用法都給盤出來。

        2、案例代碼

        2.1、git 地址

        https://gitee.com/javacode2018/springmvc-series

        2.2、關(guān)鍵代碼位置

        文中的所有 controller 代碼,在RestTemplateTestController類中。

        所有@Test 用例的代碼,在RestTemplateTest。

        2.3、如何運(yùn)行測試用例?

        • 拉取項(xiàng)目
        • 將 chat16-RestTemplate 模塊發(fā)布到 tomcat9 中
        • 運(yùn)行 RestTemplateTest 中對應(yīng)的用例即可

        下面咱們來看 RestTemplate 常見的用法匯總。

        3、發(fā)送 Get 請求

        3.1、普通請求

        接口代碼

        @GetMapping("/test/get")
        @ResponseBody
        public?BookDto?get()?{
        ????return?new?BookDto(1,?"SpringMVC系列");
        }

        使用 RestTemplate 調(diào)用上面這個接口,通常有 2 種寫法,如下

        @Test
        public?void?test1()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/get";
        ????//getForObject方法,獲取響應(yīng)體,將其轉(zhuǎn)換為第二個參數(shù)指定的類型
        ????BookDto?bookDto?=?restTemplate.getForObject(url,?BookDto.class);
        ????System.out.println(bookDto);
        }

        @Test
        public?void?test2()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/get";
        ????//getForEntity方法,返回值為ResponseEntity類型
        ????//?ResponseEntity中包含了響應(yīng)結(jié)果中的所有信息,比如頭、狀態(tài)、body
        ????ResponseEntity?responseEntity?=?restTemplate.getForEntity(url,?BookDto.class);
        ????//狀態(tài)碼
        ????System.out.println(responseEntity.getStatusCode());
        ????//獲取頭
        ????System.out.println("頭:"?+?responseEntity.getHeaders());
        ????//獲取body
        ????BookDto?bookDto?=?responseEntity.getBody();
        ????System.out.println(bookDto);
        }

        test1 輸出

        BookDto{id=1,?name='SpringMVC系列'}

        test2 輸出

        200?OK
        頭:[Content-Type:"application/json;charset=UTF-8",?Transfer-Encoding:"chunked",?Date:"Sat,?02?Oct?2021?07:05:15?GMT",?Keep-Alive:"timeout=20",?Connection:"keep-alive"]
        BookDto{id=1,?name='SpringMVC系列'}

        3.2、url 中含有動態(tài)參數(shù)

        接口代碼

        @GetMapping("/test/get/{id}/{name}")
        @ResponseBody
        public?BookDto?get(@PathVariable("id")?Integer?id,?@PathVariable("name")?String?name)?{
        ????return?new?BookDto(id,?name);
        }

        使用 RestTemplate 調(diào)用上面這個接口,通常有 2 種寫法,如下

        @Test
        public?void?test3()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????//url中有動態(tài)參數(shù)
        ????String?url?=?"http://localhost:8080/chat16/test/get/{id}/{name}";
        ????Map?uriVariables?=?new?HashMap<>();
        ????uriVariables.put("id",?"1");
        ????uriVariables.put("name",?"SpringMVC系列");
        ????//使用getForObject或者getForEntity方法
        ????BookDto?bookDto?=?restTemplate.getForObject(url,?BookDto.class,?uriVariables);
        ????System.out.println(bookDto);
        }

        @Test
        public?void?test4()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????//url中有動態(tài)參數(shù)
        ????String?url?=?"http://localhost:8080/chat16/test/get/{id}/{name}";
        ????Map?uriVariables?=?new?HashMap<>();
        ????uriVariables.put("id",?"1");
        ????uriVariables.put("name",?"SpringMVC系列");
        ????//getForEntity方法
        ????ResponseEntity?responseEntity?=?restTemplate.getForEntity(url,?BookDto.class,?uriVariables);
        ????BookDto?bookDto?=?responseEntity.getBody();
        ????System.out.println(bookDto);
        }

        test3 輸出

        BookDto{id=1,?name='SpringMVC系列'}

        test4 輸出

        BookDto{id=1,?name='SpringMVC系列'}

        3.3、接口返回值為泛型

        接口代碼

        @GetMapping("/test/getList")
        @ResponseBody
        public?List?getList()?{
        ????return?Arrays.asList(
        ????????????new?BookDto(1,?"Spring高手系列"),
        ????????????new?BookDto(2,?"SpringMVC系列")
        ????);
        }

        當(dāng)接口的返回值為泛型的時候,這種情況比較特殊,使用 RestTemplate 調(diào)用上面這個接口,代碼如下,需要用到restTemplate.exchange的方法,這個方法中有個參數(shù)是ParameterizedTypeReference類型,通過這個參數(shù)類指定泛型類型

        @Test
        public?void?test5()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????//返回值為泛型
        ????String?url?=?"http://localhost:8080/chat16/test/getList";
        ????//若返回結(jié)果是泛型類型的,需要使用到exchange方法,
        ????//這個方法中有個參數(shù)是ParameterizedTypeReference類型,通過這個參數(shù)類指定泛型類型
        ????ResponseEntity>?responseEntity?=
        ????????????restTemplate.exchange(url,
        ????????????????????HttpMethod.GET,
        ????????????????????null,
        ????????????????????new?ParameterizedTypeReference>()?{
        ????????????????????});
        ????List?bookDtoList?=?responseEntity.getBody();
        ????System.out.println(bookDtoList);
        }

        輸出

        [BookDto{id=1,?name='Spring高手系列'},?BookDto{id=2,?name='SpringMVC系列'}]

        3.4、下載小文件

        接口代碼如下,這個接口會下載服務(wù)器端的 1.txt 文件。

        /**
        ?*?下載文件
        ?*
        ?*?@return
        ?*/

        @GetMapping("/test/downFile")
        @ResponseBody
        public?HttpEntity?downFile()?{
        ????//將文件流封裝為InputStreamResource對象
        ????InputStream?inputStream?=?this.getClass().getResourceAsStream("/1.txt");
        ????InputStreamResource?inputStreamResource?=?new?InputStreamResource(inputStream);
        ????//設(shè)置header
        ????MultiValueMap?headers?=?new?HttpHeaders();
        ????headers.add(HttpHeaders.CONTENT_DISPOSITION,?"attachment;filename=1.txt");
        ????HttpEntity?httpEntity?=?new?HttpEntity<>(inputStreamResource);
        ????return?httpEntity;
        }

        使用 RestTemplate 調(diào)用這個接口,代碼如下,目前這個文件的內(nèi)容比較少,可以直接得到一個數(shù)組。

        @Test
        public?void?test6()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/downFile";
        ????//文件比較小的情況,直接返回字節(jié)數(shù)組
        ????ResponseEntity<byte[]>?responseEntity?=?restTemplate.getForEntity(url,?byte[].class);
        ????//獲取文件的內(nèi)容
        ????byte[]?body?=?responseEntity.getBody();
        ????String?content?=?new?String(body);
        ????System.out.println(content);
        }

        注意:如果文件大的時候,這種方式就有問題了,會導(dǎo)致 oom,要用下面的方式了。

        3.5、下載大文件

        接口代碼,繼續(xù)使用上面下載 1.txt 的代碼

        /**
        ?*?下載文件
        ?*
        ?*?@return
        ?*/

        @GetMapping("/test/downFile")
        @ResponseBody
        public?HttpEntity?downFile()?{
        ????//將文件流封裝為InputStreamResource對象
        ????InputStream?inputStream?=?this.getClass().getResourceAsStream("/1.txt");
        ????InputStreamResource?inputStreamResource?=?new?InputStreamResource(inputStream);
        ????//設(shè)置header
        ????MultiValueMap?headers?=?new?HttpHeaders();
        ????headers.add(HttpHeaders.CONTENT_DISPOSITION,?"attachment;filename=1.txt");
        ????HttpEntity?httpEntity?=?new?HttpEntity<>(inputStreamResource);
        ????return?httpEntity;
        }

        此時使用 RestTemplate 調(diào)用這個接口,代碼如下

        文件比較大的時候,比如好幾個 G,就不能返回字節(jié)數(shù)組了,會把內(nèi)存撐爆,導(dǎo)致 OOM,需要使用 execute 方法了,這個方法中有個 ResponseExtractor 類型的參數(shù),restTemplate 拿到結(jié)果之后,會回調(diào){@link ResponseExtractor#extractData}這個方法,在這個方法中可以拿到響應(yīng)流,然后進(jìn)行處理,這個過程就是變讀邊處理,不會導(dǎo)致內(nèi)存溢出

        @Test
        public?void?test7()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/downFile";
        ????/**
        ?????*?文件比較大的時候,比如好幾個G,就不能返回字節(jié)數(shù)組了,會把內(nèi)存撐爆,導(dǎo)致OOM
        ?????*?需要這么玩:
        ?????*?需要使用execute方法了,這個方法中有個ResponseExtractor類型的參數(shù),
        ?????*?restTemplate拿到結(jié)果之后,會回調(diào){@link?ResponseExtractor#extractData}這個方法,
        ?????*?在這個方法中可以拿到響應(yīng)流,然后進(jìn)行處理,這個過程就是變讀邊處理,不會導(dǎo)致內(nèi)存溢出
        ?????*/

        ????String?result?=?restTemplate.execute(url,
        ????????????HttpMethod.GET,
        ????????????null,
        ????????????new?ResponseExtractor()?{
        ????????????????@Override
        ????????????????public?String?extractData(ClientHttpResponse?response)?throws?IOException?{
        ????????????????????System.out.println("狀態(tài):"+response.getStatusCode());
        ????????????????????System.out.println("頭:"+response.getHeaders());
        ????????????????????//獲取響應(yīng)體流
        ????????????????????InputStream?body?=?response.getBody();
        ????????????????????//處理響應(yīng)體流
        ????????????????????String?content?=?IOUtils.toString(body,?"UTF-8");
        ????????????????????return?content;
        ????????????????}
        ????????????},?new?HashMap<>());

        ????System.out.println(result);
        }

        3.6、傳遞頭

        接口代碼

        @GetMapping("/test/header")
        @ResponseBody
        public?Map>?header(HttpServletRequest?request)?{
        ????Map>?header?=?new?LinkedHashMap<>();
        ????Enumeration?headerNames?=?request.getHeaderNames();
        ????while?(headerNames.hasMoreElements())?{
        ????????String?name?=?headerNames.nextElement();
        ????????Enumeration?values?=?request.getHeaders(name);
        ????????List?list?=?new?ArrayList<>();
        ????????while?(values.hasMoreElements())?{
        ????????????list.add(values.nextElement());
        ????????}
        ????????header.put(name,?list);
        ????}
        ????return?header;
        }

        使用 RestTemplate 調(diào)用接口,請求頭中傳遞數(shù)據(jù),代碼如下,注意代碼①和②,這兩處是關(guān)鍵,用到了HttpHeadersRequestEntity

        • 請求頭放在 HttpHeaders 對象中
        • RequestEntity:請求實(shí)體,請求的所有信息都可以放在 RequestEntity 中,比如 body 部分、頭、請求方式、url 等信息
        @Test
        public?void?test8()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/header";
        ????//①:請求頭放在HttpHeaders對象中
        ????MultiValueMap?headers?=?new?HttpHeaders();
        ????headers.add("header-1",?"V1");
        ????headers.add("header-2",?"Spring");
        ????headers.add("header-2",?"SpringBoot");
        ????//②:RequestEntity:請求實(shí)體,請求的所有信息都可以放在RequestEntity中,比如body部分、頭、請求方式、url等信息
        ????RequestEntity?requestEntity?=?new?RequestEntity(
        ????????????null,?//body部分?jǐn)?shù)據(jù)
        ????????????headers,?//頭
        ????????????HttpMethod.GET,//請求方法
        ????????????URI.create(url)?//地址
        ????);
        ????ResponseEntity>>?responseEntity?=?restTemplate.exchange(requestEntity,
        ????????????new?ParameterizedTypeReference>>()?{
        ????????????});
        ????Map>?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        輸出

        {accept=[application/json,?application/*+json],?header-1=[V1],?header-2=[Spring,?SpringBoot],?user-agent=[Java/1.8.0_121],?host=[localhost:8080],?connection=[keep-alive]}

        3.7、綜合案例:含頭、url 動態(tài)參數(shù)

        接口

        @GetMapping("/test/getAll/{path1}/{path2}")
        @ResponseBody
        public?Map?getAll(@PathVariable("path1")?String?path1,
        ??????????????????????????????????@PathVariable("path2")?String?path2,
        ??????????????????????????????????HttpServletRequest?request)?
        {
        ????Map?result?=?new?LinkedHashMap<>();
        ????result.put("path1",?path1);
        ????result.put("path2",?path2);
        ????//頭
        ????Map>?header?=?new?LinkedHashMap<>();
        ????Enumeration?headerNames?=?request.getHeaderNames();
        ????while?(headerNames.hasMoreElements())?{
        ????????String?name?=?headerNames.nextElement();
        ????????Enumeration?values?=?request.getHeaders(name);
        ????????List?list?=?new?ArrayList<>();
        ????????while?(values.hasMoreElements())?{
        ????????????list.add(values.nextElement());
        ????????}
        ????????header.put(name,?list);
        ????}
        ????result.put("header",?header);
        ????return?result;
        }

        如下,使用 RestTemplate 調(diào)用接口,GET 方式、傳遞 header、path 中動態(tài)參數(shù)。

        @Test
        public?void?test9()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/getAll/{path1}/{path2}";
        ????//①:請求頭
        ????MultiValueMap?headers?=?new?HttpHeaders();
        ????headers.add("header-1",?"V1");
        ????headers.add("header-2",?"Spring");
        ????headers.add("header-2",?"SpringBoot");
        ????//②:url中的2個參數(shù)
        ????Map?uriVariables?=?new?HashMap<>();
        ????uriVariables.put("path1",?"v1");
        ????uriVariables.put("path2",?"v2");
        ????//③:HttpEntity:HTTP實(shí)體,內(nèi)部包含了請求頭和請求體
        ????HttpEntity?requestEntity?=?new?HttpEntity(
        ????????null,//body部分,get請求沒有body,所以為null
        ????????headers?//頭
        ????);
        ????//④:使用exchange發(fā)送請求
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????url,?//url
        ????????HttpMethod.GET,?//請求方式
        ????????requestEntity,?//請求實(shí)體(頭、body)
        ????????new?ParameterizedTypeReference>()?{
        ????????},//返回的結(jié)果類型
        ????????uriVariables?//url中的占位符對應(yīng)的值
        ????);
        ????Map?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        輸出

        {path1=v1,?path2=v2,?header={accept=[application/json,?application/*+json],?header-1=[V1],?header-2=[Spring,?SpringBoot],?user-agent=[Java/1.8.0_121],?host=[localhost:8080],?connection=[keep-alive]}}

        4、POST 請求

        4.1、post 請求常見的 3 種類型

        http 請求頭中的 Content-Type 用來指定請求的類型,常見的有 3 種

        Content-Type說明
        application/x-www-form-urlencoded頁面中普通的 form 表單提交時就是這種類型,表單中的元素會按照名稱和值拼接好,然后之間用&連接,格式如:p1=v1&p2=v2&p3=v3
        然后通過 urlencoded 編碼之后丟在 body 中發(fā)送
        multipart/form-data頁面中表單上傳文件的時候,用到的就是這種格式
        application/json將發(fā)送的數(shù)據(jù)轉(zhuǎn)換為 json 格式,丟在 http 請求的 body 中發(fā)送,后端接口通常用@RequestBody 配合對象來接收。

        下面看則種方式的案例。

        4.2、普通表單請求

        普通表單默認(rèn)為 application/x-www-form-urlencoded 類型的請求。

        接口代碼

        @PostMapping("/test/form1")
        @ResponseBody
        public?BookDto?form1(BookDto?bookDto)?{
        ????return?bookDto;
        }

        使用 RestTemplate 調(diào)用接口

        @Test
        public?void?test10()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form1";
        ????//①:表單信息,需要放在MultiValueMap中,MultiValueMap相當(dāng)于Map>
        ????MultiValueMap?body?=?new?LinkedMultiValueMap<>();
        ????//調(diào)用add方法填充表單數(shù)據(jù)(表單名稱:值)
        ????body.add("id","1");
        ????body.add("name","SpringMVC系列");
        ????//②:發(fā)送請求(url,請求體,返回值需要轉(zhuǎn)換的類型)
        ????BookDto?result?=?restTemplate.postForObject(url,?body,?BookDto.class);
        ????System.out.println(result);
        }

        如果想攜帶頭信息,代碼如下

        @Test
        public?void?test11()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form1";
        ????//①:表單信息,需要放在MultiValueMap中,MultiValueMap相當(dāng)于Map>
        ????MultiValueMap?body?=?new?LinkedMultiValueMap<>();
        ????//調(diào)用add方法放入表單元素(表單名稱:值)
        ????body.add("id","1");
        ????body.add("name","SpringMVC系列");
        ????//②:請求頭
        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????//調(diào)用set方法放入請求頭
        ????headers.set(HttpHeaders.CONTENT_TYPE,?MediaType.APPLICATION_FORM_URLENCODED_VALUE);
        ????//③:請求實(shí)體:包含了請求體和請求頭
        ????HttpEntity>?httpEntity?=?new?HttpEntity<>(body,?headers);
        ????//④:發(fā)送請求(url,請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????BookDto?result?=?restTemplate.postForObject(url,?httpEntity,?BookDto.class);
        ????System.out.println(result);
        }

        4.3、上傳本地文件

        上傳文件 Content-Type 為 multipart/form-data 類型。

        接口如下,上傳上傳單個文件,返回值為一個 Map 類型,是泛型類型

        @PostMapping(value?=?"/test/form2")
        @ResponseBody
        public?Map?form2(@RequestParam("file1")?MultipartFile?file1)?{
        ????Map?fileMetadata?=?new?LinkedHashMap<>();
        ????fileMetadata.put("文件名",?file1.getOriginalFilename());
        ????fileMetadata.put("文件類型",?file1.getContentType());
        ????fileMetadata.put("文件大小(byte)",?String.valueOf(file1.getSize()));
        ????return?fileMetadata;
        }

        使用 RestTemplate 調(diào)用接口,主要下面代碼上傳的文件需要包裝為org.springframework.core.io.Resource,常用的有 3 中[FileSystemResource、InputStreamResource、ByteArrayResource],這里案例中我們用到的是 FileSystemResource 來上傳本地文件,另外 2 種(InputStreamResource、ByteArrayResource)用法就比較特殊了,見下個案例。

        @Test
        public?void?test12()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form2";
        ????//①:表單信息,需要放在MultiValueMap中,MultiValueMap相當(dāng)于Map>
        ????MultiValueMap?body?=?new?LinkedMultiValueMap<>();
        ????//調(diào)用add方法放入表單元素(表單名稱:值)
        ????//②:文件對應(yīng)的類型,需要是org.springframework.core.io.Resource類型的,常見的有[FileSystemResource、InputStreamResource、ByteArrayResource]
        ????body.add("file1",?new?FileSystemResource(".\\src\\main\\java\\com\\javacode2018\\springmvc\\chat16\\dto\\UserDto.java"));
        ????//③:頭
        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????headers.add("header1",?"v1");
        ????headers.add("header2",?"v2");
        ????//④:請求實(shí)體
        ????RequestEntity>?requestEntity?=?new?RequestEntity<>(body,?headers,?HttpMethod.POST,?URI.create(url));
        ????//⑤:發(fā)送請求(請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????requestEntity,
        ????????new?ParameterizedTypeReference>()?{
        ????????});
        ????Map?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        4.4、通過流或字節(jié)數(shù)組的方式上傳文件

        有時候,上傳的文件是通過流的方式或者字節(jié)數(shù)組的方式,那么就需要用到 InputStreamResource、ByteArrayResource 這倆了。

        **注意:**使用這倆的時候,需要重寫 2 個方法,否則會上傳失敗

        • getFilename:文件名稱
        • contentLength:長度
        @Test
        public?void?test13()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form2";
        ????//①:表單信息,需要放在MultiValueMap中,MultiValueMap相當(dāng)于Map>
        ????MultiValueMap?body?=?new?LinkedMultiValueMap<>();
        ????/**
        ?????*?②:通過流的方式上傳文件,流的方式需要用到InputStreamResource類,需要重寫2個方法
        ?????* getFilename:文件名稱
        ?????* contentLength:長度
        ?????*/

        ????InputStream?inputStream?=?RestTemplateTest.class.getResourceAsStream("/1.txt");
        ????InputStreamResource?inputStreamResource?=?new?InputStreamResource(inputStream)?{
        ????????@Override
        ????????public?String?getFilename()?{
        ????????????return?"1.txt";
        ????????}

        ????????@Override
        ????????public?long?contentLength()?throws?IOException?{
        ????????????return?inputStream.available();
        ????????}
        ????};
        ????body.add("file1",?inputStreamResource);
        ????//③:頭
        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????headers.add("header1",?"v1");
        ????headers.add("header2",?"v2");
        ????//④:請求實(shí)體
        ????RequestEntity>?requestEntity?=?new?RequestEntity<>(body,?headers,?HttpMethod.POST,?URI.create(url));
        ????//⑤:發(fā)送請求(請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????????requestEntity,
        ????????????new?ParameterizedTypeReference>()?{
        ????????????});
        ????Map?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        4.5、復(fù)雜表單:多個普通元素+多文件上傳

        接口

        /**
        ?*?復(fù)雜的表單:包含了普通元素、多文件
        ?*
        ?*?@param?userDto
        ?*?@return
        ?*/

        @PostMapping("/test/form3")
        @ResponseBody
        public?Map?form3(UserDto?userDto)?{
        ????Map?result?=?new?LinkedHashMap<>();
        ????result.put("name",?userDto.getName());
        ????result.put("headImg",?userDto.getHeadImg().getOriginalFilename());
        ????result.put("idImgList",?Arrays.toString(userDto.getIdImgList().stream().
        ????????????????????????????????????????????map(MultipartFile::getOriginalFilename).toArray()));
        ????return?result;
        }

        UserDto:包含了多個元素(姓名、頭像、多張證件照),這種可以模擬復(fù)雜的表單

        public?class?UserDto?{
        ????//姓名
        ????private?String?name;
        ????//頭像
        ????private?MultipartFile?headImg;
        ????//多張證件照
        ????private?List?idImgList;

        ????//get?set?省略了...
        }

        用 RestTemplate 調(diào)用這個接口,代碼如下

        @Test
        public?void?test14()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form3";
        ????//①:表單信息,需要放在MultiValueMap中,MultiValueMap相當(dāng)于Map>
        ????MultiValueMap?body?=?new?LinkedMultiValueMap<>();
        ????body.add("name",?"路人");
        ????body.add("headImg",?new?FileSystemResource(".\\src\\main\\resources\\1.jpg"));
        ????//來2張證件照,元素名稱一樣
        ????body.add("idImgList",?new?FileSystemResource(".\\src\\main\\resources\\2.jpg"));
        ????body.add("idImgList",?new?FileSystemResource(".\\src\\main\\resources\\3.jpg"));
        ????//③:頭
        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????headers.add("header1",?"v1");
        ????headers.add("header2",?"v2");
        ????//④:請求實(shí)體
        ????RequestEntity>?requestEntity?=?new?RequestEntity<>(body,?headers,?HttpMethod.POST,?URI.create(url));
        ????//⑤:發(fā)送請求(請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????????requestEntity,
        ????????????new?ParameterizedTypeReference>()?{
        ????????????});
        ????Map?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        輸出

        {name=路人,?headImg=1.jpg,?idImgList=[2.jpg,?3.jpg]}

        4.6、發(fā)送 json 格式數(shù)據(jù):傳遞 java 對象

        接口

        /**
        ?*?body中json格式的數(shù)據(jù),返回值非泛型
        ?*
        ?*?@param?bookDto
        ?*?@return
        ?*/

        @PostMapping("/test/form4")
        @ResponseBody
        public?BookDto?form4(@RequestBody?BookDto?bookDto)?{
        ????return?bookDto;
        }

        RestTemplate 調(diào)用接口

        @Test
        public?void?test15()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form4";
        ????BookDto?body?=?new?BookDto(1,?"SpringMVC系列");
        ????BookDto?result?=?restTemplate.postForObject(url,?body,?BookDto.class);
        ????System.out.println(result);
        }

        輸出

        BookDto{id=1,?name='SpringMVC系列'}

        4.7、發(fā)送 json 格式數(shù)據(jù):傳遞 java 對象,返回值為泛型

        接口

        /**
        ?*?body中json格式的數(shù)據(jù),返回值為泛型
        ?*
        ?*?@param?bookDtoList
        ?*?@return
        ?*/

        @PostMapping("/test/form5")
        @ResponseBody
        public?List?form5(@RequestBody?List?bookDtoList)?{
        ????return?bookDtoList;
        }

        用 RestTemplate 調(diào)用這個接口,代碼如下

        @Test
        public?void?test16()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form5";
        ????//①:請求體,發(fā)送的時候會被轉(zhuǎn)換為json格式數(shù)據(jù)
        ????List?body?=?Arrays.asList(
        ????????????new?BookDto(1,?"SpringMVC系列"),
        ????????????new?BookDto(2,?"MySQL系列"));
        ????//②:頭
        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????headers.add("header1",?"v1");
        ????headers.add("header2",?"v2");
        ????//③:請求實(shí)體
        ????RequestEntity?requestEntity?=?new?RequestEntity(body,?headers,?HttpMethod.POST,?URI.create(url));
        ????//④:發(fā)送請求(請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????????requestEntity,
        ????????????new?ParameterizedTypeReference>()?{
        ????????????});
        ????//⑤:獲取結(jié)果
        ????List?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        輸出

        [BookDto{id=1,?name='SpringMVC系列'},?BookDto{id=2,?name='MySQL系列'}]

        4.8、發(fā)送 json 字符串格式數(shù)據(jù)

        上面 2 個 json 案例 body 都是 java 對象,RestTemplate 默認(rèn)自動配上 Content-Type=application/json

        但是如果 body 的值是 json 格式字符串的時候,調(diào)用的時候需要在頭中明確指定 Content-Type=application/json,寫法如下:

        @Test
        public?void?test17()?{
        ????RestTemplate?restTemplate?=?new?RestTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/form5";
        ????//①:請求體為一個json格式的字符串
        ????String?body?=?"[{\"id\":1,\"name\":\"SpringMVC系列\(zhòng)"},{\"id\":2,\"name\":\"MySQL系列\(zhòng)"}]";
        ????/**
        ?????*?②:若請求體為json字符串的時候,需要在頭中設(shè)置Content-Type=application/json;
        ?????*?若body是普通的java類的時候,無需指定這個,RestTemplate默認(rèn)自動配上Content-Type=application/json
        ?????*/

        ????HttpHeaders?headers?=?new?HttpHeaders();
        ????headers.setContentType(MediaType.APPLICATION_JSON);
        ????//③:請求實(shí)體(body,頭、請求方式,uri)
        ????RequestEntity?requestEntity?=?new?RequestEntity(body,?headers,?HttpMethod.POST,?URI.create(url));
        ????//④:發(fā)送請求(請求實(shí)體,返回值需要轉(zhuǎn)換的類型)
        ????ResponseEntity>?responseEntity?=?restTemplate.exchange(
        ????????????requestEntity,
        ????????????new?ParameterizedTypeReference>()?{
        ????????????});
        ????//⑤:獲取結(jié)果
        ????List?result?=?responseEntity.getBody();
        ????System.out.println(result);
        }

        輸出

        [BookDto{id=1,?name='SpringMVC系列'},?BookDto{id=2,?name='MySQL系列'}]

        5、DELETE、PUT、OPTION 請求

        5.1、DELETE 請求

        public?void?delete(String?url,?Object...?uriVariables);
        public?void?delete(String?url,?Map?uriVariables);
        public?void?delete(URI?url);

        5.2、PUT 請求

        PUT 請求和 POST 請求類似,將類型改為 PUT 就可以了。

        5.3、OPTIONS 請求

        OPTIONS 請求用來探測接口支持哪些 http 方法

        public?Set?optionsForAllow(String?url,?Object...?uriVariables);
        public?Set?optionsForAllow(String?url,?Map?uriVariables);
        public?Set?optionsForAllow(URI?url);

        6、集成 HttpClient

        RestTemplate 內(nèi)部默認(rèn)用的是 jdk 自帶的 HttpURLConnection 發(fā)送請求的,性能上面并不是太突出。

        可以將其替換為 httpclient 或者 okhttp。

        先來看下如何替換為 HttpClient。

        引入 maven 配置

        <dependency>
        ????<groupId>org.apache.httpcomponentsgroupId>
        ????<artifactId>httpclientartifactId>
        ????<version>4.5.7version>
        dependency>

        創(chuàng)建 RestTemplate 時指定 HttpClient 配置,代碼如下

        public?HttpClient?httpClient()?{
        ????HttpClientBuilder?httpClientBuilder?=?HttpClientBuilder.create();
        ????try?{
        ????????//設(shè)置信任ssl訪問
        ????????SSLContext?sslContext?=?new?SSLContextBuilder().loadTrustMaterial(null,?(arg0,?arg1)?->?true).build();
        ????????httpClientBuilder.setSSLContext(sslContext);
        ????????HostnameVerifier?hostnameVerifier?=?NoopHostnameVerifier.INSTANCE;
        ????????SSLConnectionSocketFactory?sslConnectionSocketFactory?=?new?SSLConnectionSocketFactory(sslContext,?hostnameVerifier);
        ????????Registry?socketFactoryRegistry?=?RegistryBuilder.create()
        ????????????????//?注冊http和https請求
        ????????????????.register("http",?PlainConnectionSocketFactory.getSocketFactory())
        ????????????????.register("https",?sslConnectionSocketFactory).build();

        ????????//使用Httpclient連接池的方式配置(推薦),同時支持netty,okHttp以及其他http框架
        ????????PoolingHttpClientConnectionManager?poolingHttpClientConnectionManager?=?new?PoolingHttpClientConnectionManager(socketFactoryRegistry);
        ????????//?最大連接數(shù)
        ????????poolingHttpClientConnectionManager.setMaxTotal(1000);
        ????????//?同路由并發(fā)數(shù)
        ????????poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
        ????????//配置連接池
        ????????httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
        ????????//?重試次數(shù)
        ????????httpClientBuilder.setRetryHandler(new?DefaultHttpRequestRetryHandler(0,?true));
        ????????//設(shè)置默認(rèn)請求頭
        ????????List
        ?headers?=?new?ArrayList<>();
        ????????httpClientBuilder.setDefaultHeaders(headers);
        ????????return?httpClientBuilder.build();
        ????}?catch?(Exception?e)?{
        ????????throw?new?RuntimeException(e);
        ????}
        }

        public?ClientHttpRequestFactory?clientHttpRequestFactory()?{
        ????HttpComponentsClientHttpRequestFactory?clientHttpRequestFactory?=?new?HttpComponentsClientHttpRequestFactory(httpClient());
        ????//?連接超時(毫秒),這里設(shè)置10秒
        ????clientHttpRequestFactory.setConnectTimeout(10?*?1000);
        ????//?數(shù)據(jù)讀取超時時間(毫秒),這里設(shè)置60秒
        ????clientHttpRequestFactory.setReadTimeout(60?*?1000);
        ????//?從連接池獲取請求連接的超時時間(毫秒),不宜過長,必須設(shè)置,比如連接不夠用時,時間過長將是災(zāi)難性的
        ????clientHttpRequestFactory.setConnectionRequestTimeout(10?*?1000);
        ????return?clientHttpRequestFactory;
        }

        public?RestTemplate?restTemplate(){
        ????//創(chuàng)建RestTemplate的時候,指定ClientHttpRequestFactory
        ????return?new?RestTemplate(this.clientHttpRequestFactory());
        }

        @Test
        public?void?test18()?{
        ????RestTemplate?restTemplate?=?this.restTemplate();
        ????String?url?=?"http://localhost:8080/chat16/test/get";
        ????//getForObject方法,獲取響應(yīng)體,將其轉(zhuǎn)換為第二個參數(shù)指定的類型
        ????BookDto?bookDto?=?restTemplate.getForObject(url,?BookDto.class);
        ????System.out.println(bookDto);
        }

        7、集成 okhttp

        引入 maven 配置

        <dependency>
        ????<groupId>com.squareup.okhttp3groupId>
        ????<artifactId>okhttpartifactId>
        ????<version>4.3.1version>
        dependency>

        創(chuàng)建 RestTemplate

        new?RestTemplate(new?OkHttp3ClientHttpRequestFactory());

        8、總結(jié)

        RestTemplate 使用確實(shí)非常容易,建議大家去看一下 RestTemplate 的源碼,debug 跟蹤一下過程,這樣用起來就非常順手了。

        尚硅谷 Java 學(xué)科全套教程(總 207.77GB)

        9、SpringMVC 系列目錄

        1. SpringMVC 系列第 1 篇:helloword
        2. SpringMVC 系列第 2 篇:@Controller、@RequestMapping
        3. SpringMVC 系列第 3 篇:異常高效的一款接口測試?yán)?/a>
        4. SpringMVC 系列第 4 篇:controller 常見的接收參數(shù)的方式
        5. SpringMVC 系列第 5 篇:@RequestBody 大解密,說點(diǎn)你不知道的
        6. SpringMVC 系列第 6 篇:上傳文件的 4 種方式,你都會么?
        7. SpringMVC 系列第 7 篇:SpringMVC 返回視圖常見的 5 種方式,你會幾種?
        8. SpringMVC 系列第 8 篇:返回 json & 通用返回值設(shè)計(jì)
        9. SpringMVC 系列第 9 篇:SpringMVC 返回 null 是什么意思?
        10. SpringMVC 系列第 10 篇:異步處理
        11. SpringMVC 系列第 11 篇:集成靜態(tài)資源
        12. SpringMVC 系列第 12 篇:攔截器
        13. SpringMVC 系列第 13 篇:統(tǒng)一異常處理
        14. SpringMVC 系列第 14 篇:實(shí)戰(zhàn)篇:通用返回值 & 異常處理設(shè)計(jì)
        15. SpringMVC 系列第 15 篇:全注解的方式 ?&? 原理解析
        16. SpringMVC 系列第 16 篇:通過源碼解析 SpringMVC 處理請求的流程
        17. SpringMVC 系列第 17 篇:源碼解析 SpringMVC 容器的啟動過程
        18. SpringMVC 系列第 18 篇:強(qiáng)大的 RequestBodyAdvice 解密
        19. SpringMVC 系列第 19 篇:強(qiáng)大的 ResponseBodyAdvice 解密
        20. SpringMVC 系列第 20 篇:RestFull 詳解

        10、更多好文章

        1. Spring 高手系列(共 56 篇)
        2. Java 高并發(fā)系列(共 34 篇)
        3. MySql 高手系列(共 27 篇)
        4. Maven 高手系列(共 10 篇)
        5. Mybatis 系列(共 12 篇)
        6. 聊聊 db 和緩存一致性常見的實(shí)現(xiàn)方式
        7. 接口冪等性這么重要,它是什么?怎么實(shí)現(xiàn)?
        8. 泛型,有點(diǎn)難度,會讓很多人懵逼,那是因?yàn)槟銢]有看這篇文章!

        11、【路人甲 Java】所有系列高清 PDF

        領(lǐng)取方式,掃碼發(fā)送:yyds

        瀏覽 101
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            污污污www精品国产网站| 2025中文在线观看最好看的电影| 五月丁香啪啪| 国产欧美在线不卡| 大地8免费高清视频观看大全| 亚洲欧洲无码在线| 亚洲黄色无码视频| 五月丁香婷婷成人| 亚洲va欧美ⅴa在线| 免看一级a一片| 97人人爽人人爽人人爽| 在线观看亚| 亚洲男同Gay一区二区| 国产做爰XXXⅩ久久久骚妇| 青青免费在线视频| 成人A片免费观看| 久久这里精品| 国产毛片一区二区| 中文字幕在线有码| 青青草无码视频| 国产精品内射| 91人妻无码一区二区久久| 国产午夜精品视频| 国产成人自拍视频在线| 亚洲免费黄色片| 国产五月天婷婷| 91黄色视频网站| 在线精品福利| 无码高潮| 中文字幕av久久爽一区| 日韩成人片无码| 北条麻妃无码视频在线| 亚洲午夜无码久久久| 99精品免费在线观看| 国产老熟女久久久| a天堂8在线资源| 黄色成人在线免费观看| 国产三级在线播放| 精品AV无码一区二区三区| 91精品国际| 国产区在线视频| 亚洲日韩欧美成人| 99热这里有精品| 亚洲精品中文字幕无码| 特级黄色毛片| 精品欧美激情精品一区| 国精品无码一区二区三区在线秋菊| 久久四区| 中文字幕福利视频| 特级西西444www高清| 操比视频| 竹菊影视一区二区三区| 污视频网站免费观看| 2021国产视频| 在线免费观看黄| 亚洲一区二区在线| 欧美性爱内射| 黄色a级毛片| 成人欧美精品区二区三| 国产精品网站在线观看| 日韩黄色网| 久久成人在线视频| 亚洲国产av一区| 狼色视频| 大香蕉伊人AV| 午夜国产| 精品女同一区二区三区四区外站在线| 精品码A片18| 青春草免费视频| 黄色三级在线观看| 日韩AV一区二区在线观看| 免费一级AAAAA片在线播放| 亚洲怡春院| 河南少妇搡BBBB搡BBBB| 国产xxxx| 性爱av在线观看| 欧美成人大片| 人人妻人人爽人人澡人人精品| 肏逼网| 日韩美女在线视频| 91成人在线播放| 91精品综合| 成人h网站在线观看| 午夜第一页| 最近中文字幕mv第三季歌词| 亚洲不卡| 91影音先锋| 四虎影院在线| 91蝌蚪丨人妻丨丝袜| 精品一区二区三区av| 婷婷欧美日韩| 91亚洲成人| 俺也去电影| 我爱大香蕉| 亚洲激情综合网| 女同一区二区三区| 在线无码免费视频| 国产一区不卡| 欧美一区二区三区成人| 天天日天天撸| 欧美日本黄色| 中文字幕精品一区久久久久 | 91成人免费电影片| 亚洲成人AV电影| 亚洲无码免费观看视频| www.黄色av| 久草精品视频| 黄工厂精品视频在线播| 色色色色综合| 男女激情网站| 色中色AV| 91狠狠| 亚洲天堂在线观看视频网站| 无码骚逼| 一本道无码在线观看| 家庭乱伦影视| 婷婷综合五月| 九九草在线视频| 成人小说视频| 久久免费精品| 成人午夜天堂| 日韩视频免费| 久久99高清| 激情五月天色| 久久综合加勒比| 九九99热| 人人操人人爱人人拍| 四虎成人电影| 亚洲午夜福利电影| 91视频免费在线看| 亚洲午夜福利在线| 天堂无码视频在线播放| 18禁一区| 三级高清无码视频| 九色PORNY蝌蚪视频| 午夜精品久久久久久久久无码99热| 中国老女人性爱视频| 精品日韩| www.97色| 久久人妻无码中文字幕系列| 江苏妇搡BBB搡BBBB| 操杨幂| 精品日韩中文字幕| 在线中文字幕视频| 欧美激情精品| 天堂资源| 欧美特大黄| 私人玩物』黑絲OL尤物| 国产尤物视频| 中文字幕在线播放AV| 国产日本在线| 国产精品操逼网站| 超碰在线看| 韩日综合在线| 狠狠操在线视频| 大蕉网| 免费在线观看黄色| 91视频第一页| 老骚老B老太太A片| 欧美日韩大片| 精品国产自| 久久久久无码| 走光无码一区二区三区| 免费看操逼视频| 吹潮喷水高潮HD| 2025最新国产精品每日更新| 操屄网| 99精品一区二区三区| 麻豆mdapp03.tⅴ| 蜜桃久久精品成人无码AV| 久草视频网站| 特级西西WWW无码| 嫩BBB嫩BBB嫩BBBn嫩| 成人免费看A片| 屁屁影院国产第一页| 人成视频在线| 国产操逼网址| 亚洲色图欧美| 日韩欧美国产精品| 伊人激情五月| 伊人在线视频| 一级国产欧美成人A片| 激情五月丁香花| 无码免费在线视频| 嫩草久久99www亚洲红桃| 成人免费内射视频| 国精产品久拍自产在线网站| 97在线免费| 香蕉综合网| 日韩免费视频观看| 五月天婷婷在线观看视频| 六月婷婷综合| 免费视频无码| 日逼老女人| 精品内射| 婷婷五月天小说| 99久久网站| 驲韩在线视频免费观看| 777免费视频| 亚洲成人在线免费| 乱伦91| 91无码成人| 精品人人操| 黄片一区| 二区三区在线| 天天操夜夜爱| 夜夜bb| 亚洲综合网站| 欧美一級黃色A片免費看| 四虎福利| 熟妇高潮一区二区高潮| 成人在线免费观看视频| 四川BBBBBB搡BBBBB| 动漫人物插画动漫人物的视频软件 | 91AV| 亚洲欧美成人网站| 亚洲无码久久网| 国产三级片在线观看| 麻豆视频一区二区| 黄色片网站免费观看| 91精品国产乱码久久| 正在播放李彩斐被洋老外| 奇米av| 亲子伦视频一区二区三区| a天堂在线| 黄片在线视频| 国产在线无码视频| 大鸡巴免费视频| 黑人一区二区三区四区| 成人免费无码A片免费| 精品视频在线播放| 日产毛片| 伊人久久国产| 日日搔av一区二区三区| 国产有码在线观看| 91麻豆国产福利精品| 一区二区精品| 91麻豆国产| 丁香五月天在线视频| 黑人大肉棒| 国产—级a毛—a毛免费视频| 青草大香蕉| 亚洲AV无码国产精品| 国产精品观看| 日韩在线视频91| 精品乱子伦| 国产区在线视频| 久久理论电影| 狠狠躁夜夜躁人人爽人妻| 爱干视频| 人人妻人人澡人人爽人人DVD| 丰满人妻无码| 免费国产A片| 超碰免费人人| 国产特黄视频| 国产精品久久久久久久久A| 国产精品视频| 国产久久久久久| 免费一级做a爱片毛片A片小说| 特级艺体西西444WWw| 日韩一级片网站| 草逼综合网| 国产熟妇搡BBBB搡BBBB搡| 国产香蕉视频免费| 怡春院中文字幕| 欧美,日韩,日| 超碰亚洲| 超碰日韩| 国产福利网| A片在线视频| 韩日精品视频| 一曲二曲三曲在线观看中文字| 搡女人视频国产一级午夜片| 怡红院成人av| 久热激情| 69视频在线播放| 人人人人人人操| 日本中文字幕在线观看视频| 日本有码中文字幕| 性性性性性XXXXX| 国产91免费视频| 日韩免费在线观看| 亚洲vs无码蜜桃少妇| A级片黄色片| 人妻无码HEYZO少妇精品| 青青操成人| 91亚洲精品久久久久蜜桃| 亚洲免费视频在线观看| 人人摸人人摸| 国产日本欧美韩国久久久久| 苗条一区小视频| 黄片网站在线观看| 肏逼网| 成人a级网站| 成人AV电影在线观看| 日本的黄色视频| 亚洲精品乱码久久久久久按摩观 | 黄片高清免费观看| www.五月天婷婷| 久久人人网| 调教人妻视频| 91精品少妇| 日韩porn| 日本道在线视频| 天天插天天狠| 欧美日韩人妻| 三级国产AV| 国产AV三级| 日韩无码三级| 日韩AV小说| 国产一级二级三级| 婷婷色图| 美日韩在线观看| 久久久亚洲AV| 91人妻一区二区三区| 国产成人精品一区二区三区四区| 伊大香蕉在线| 中文无码一区二区三区四区| 中文字幕av免费观看| 狠狠色色| 欧美日本国产| 麻豆精品久久久久久久99蜜桃| 青青草原网| www.四虎成人网站| 国产欧美精品在线观看| 亚洲成人电影天堂| 中文字幕人妻丝袜二区电影| 一级日逼视频| 无码成人午夜在线影院| 国产精品一区二区毛片A片婊下载| 黄色视频网站免费在线观看| 欧美色综合| 国产精品成人国产乱| 97超碰网| 国产色色网| 国产秘精品一区二区三区免费| 爱爱爱免费视频| 婷婷日韩一区二区三区| 精品一区国产探花| 亚洲中文视频在线| 99黄色电影| 亚洲国产久久| 国产婷婷色一区二区三区| 江苏妇搡BBBB搡BBBB| 欧美丝袜脚交xxxxBH| 成人三级片视频| 影音先锋av成人电影| 开心五月激情婷婷| 九色PORNY国产成人| 成人网在线视频| 久久久18禁一区二区三区精品| 影音先锋AV天堂| 天天操夜夜爱| 手机看片1204| 伊人网在线观看| 久草视频免费在线播放| 成人午夜天堂| 日韩VA| 国内操逼视频| 亚洲婷婷五月| 亚洲国产精品久久久久婷婷老年| 黄色小说在线看| 自拍一区在线观看| 人妻在线免费视频| AV网站免费看| 手机看片福利| 伊人久久久影视大全| 久久成人无码| 丰满少妇在线观看网站| 大香蕉av一区二区三区在线观看| 国产在线接入| 日韩成人精品在线| 久久免费精品视频| 欧美无遮挡| 久久肏屄| 中文字幕在线观看AV| 久久人妻免费视频| 丁香婷婷五月基地| 九色国产在线| 日韩一级A片| 欧美韩日一区二区| 91久久国产综合久久91精品网站| 另类一区| 人成视频免费观看| 黄色电影网站在线观看| 久99热| 亚洲在线视频网站| 国产欧美在线看| 男女啪啪免费网站| 日本黄A级A片国产免费| 九九人妻| 操b在线观看| 日韩欧美一级| 日本爱爱片| 91成人导航| 亚洲欧洲无码在线| 青青免费在线视频| 日韩动态图| 人人妻人人玩澡人人爽| 免费成人黄色| 亚洲www啪成人一区二区麻豆| 午夜成人国产| 国产秘精品一区二区三区免费| 91嫩草欧美久久久九九九| www.91在线视频| 婷婷国产AV| 欧美成人视频。| 爆操网站| 日韩视频免费在线观看| 黄色视频在线观看大全| 国产精品免费观看视频| 久草黄色电影在线观看| 婷婷毛片| 亚洲欧美成人在线| 一级a一级a免费观看免免黄‘/| 美女自慰网站在线观看| 婷婷激情五月天丁香| 丁香五月激情啪啪啪| 欧美成人精品一区二区| 三级毛片视频| 韩国无码免费| 亚洲日韩AV在线| 午夜丁香婷婷| 91国产爽黄在线| 91麻豆国产在线| 亚洲av免费在线| 亚洲视频中文字母| 亚洲AV成人无码AV小说| 五月丁香啪啪啪| 久久9视频| 日韩黄色三级片| 欧美黄色一级网站| 久久国产劲爆∧v内射| A片免费的| 69看片| 亚洲wwwwww| 久久99人妻无码精品一区| 亚洲综合p| 内射视频在线免费观看| 国产一级a片| 欧美在线视频网| 野花av| 中文字幕av久久爽爽| 91视频网站在线观看| a片在线免费播放| 伊人大香蕉久久| 波多野结衣视频无码| 欧美三P囗交做爰XXXⅩ| 亚洲成人影音先锋| 搡BBBB搡BBB搡我瞎了| 天天日天天日天天操| 日韩黄色一级视频| 久综合网| 神马午夜51| 成人无码91| 成人视频网站在线观看| 大香蕉网伊人在线| AV天堂影视在线观看| 99er在线视频| 91无码视频在线观看| 老妇槡BBBB槡BBBB槡| 婷婷成人五月天| 可以在线观看的av| 国产精品2025| 国产性生活| 免费三级片网址| 山东熟妇搡BBBB搡BBBB| 国产在线观看91| 欧美五月在线网址| 最新中文字幕免费MV第一季歌词 | 国产人人爱| 人人摸人人看| 亚洲美女免费视频| 大香蕉伊人免费| h片在线观看免费| 先锋资源久久| 不雅一级| 91人妻人人澡人人爽人人精| 中文字幕无码精品三级在线欧美| 国产在线资源| 操操片| 女神思瑞精品一区二区三区| 日韩黄色视频网站| 无码三级午夜久久人妻| 久久久999精品日韩一区二区| 欧美国产一区二区| 性欧美成人播放77777| 亚洲无码视频在线看| 免费人成视频在线播放| 日韩在线免费视频| 人成视频在线免费观看| 欧美老妇另类BBwBBw| 黄网站免费观看| 老妇槡BBBB槡BBBB槡| 2022天天干| 99视频在线免费观看| 亚人精品中文字幕在线观看| 青青日逼| 日韩人妻精品无码| 高清无码做爱视频| 婷婷五月综合激情| 柠檬福利第一导航| 欧美三级电影在线观看| 免费人成视频在线播放| 少妇精品无码一区二区免费视频| 国产免费自拍视频| 激情视频综合网| 色婷婷激情五月天| 伊人网视频在线| 亚洲无码AV片| 国产美女被爽到高潮免费A片软件| 精品国产av| 99精品丰满人妻无码| 黄色视频免费网站| 在线观看国产欧美| 人妻熟女字幕一区二区| 色999日韩| 91婷婷射| 成人国产精品在线观看| 无码人妻一区二区三区| 色情片在线观看| 玖玖爱这里只有精品| 熟女人妻一区二区三区| 香蕉视频91| 亚洲无线视频| 免费看的操逼视频| 色老板在线精品免费观看| 日韩精品人妻一区二区| 国产美女全裸网站| 超碰在线天天| 亚洲一本色道中文无码| 69视频在线观看| 欧美a在线观看| aaa片| aav在线| 国产91综合一区在线观看| 18XXX亚洲HD护士JD| 伊人久久爱| 毛茸茸BBBBBB毛茸茸| 中国熟睡妇BBwBBw| 国产人妻一区二区三区欧美毛片| 日韩视频一区二区三区| 免费看黄A级毛片成人片| 国产精品无码免费| 亚洲天堂电影网| 国产美女啪啪| 伊人网视频在线观看| 啪啪国产| 亚州无码一区| 免费成人视频| 国语偷拍| 91女色| 豆花无码视频一区二区| 国产一级一片免费播放放a| 欧美精品一二三区| 京东一热本色道久久爱| 理论片无码| 自拍三区| 欧美va亚洲va| 俺去了俺来也| 日韩一级一片内射视频4K| 91日韩欧美| 成人av免费在线观看| 91ThePorn国产在线观看| 欧美大香蕉伊人| 天天色色天天| 人妻综合第一页| 亚洲天堂视频网| 免费无码A片在线观看全| 蜜桃91精品秘入口| 日本人妻中文字幕| 久久99免费视频| 免费一级无码成人片| 中文字幕Av在线| 黄网免费观看| 不卡的一区二区| 亚洲中文无码电影| 国产无码AV成在线| 日批网站在线| 操逼激情视频| 美女网站永久免费观看| 热久久久久久| 亚洲日韩AV电影| 特级西西444www高清大胆免费看| 大香蕉伊人丁香五月| C逼| 亚洲色在线视频| 91av视频| 99电影网手机在线观看| 蜜臀久久99精品久久久巴士| 色综合99| 免费国产视频| 亚洲欧美中文字幕| 看毛片网站| 婷婷五月丁香五月| 免费看操逼| 男人天堂影院| 国产精品视频播放| 大香蕉av在线| 成人A毛片| 91欧美黑人| 懂色av一区蜜桃| 日韩欧美视频一区国产欧美在线 | 做爱网| yw·163.爆乳尤物com| 亚洲欧美另类在线| 波多野结衣AV在线播放| 黄色小电影网站| 亚洲无码久久精品| 久久精品视频9| 亚l洲视频在线观看| 超碰操| 深夜福利18| 玖玖成人电影| 福利导航网| 中韩无码| 美女毛片视频| 青草社区在线观看| 欧美日本色| 手机在线一区| 91精品国产综合久久久久久久 | 强伦轩一区二区三区四区播放方式| 亚洲色视频| 男人天堂99| 黄色一级在线| 无码欧美精品一区二区| jlzz18| 99久久国产精| av中文字幕无码| 丁香五月天AV| 欧美性猛交XXXX乱大交3| 日本黄色电影网址| 久操视频一区二区三区| 人妻少妇被猛烈进入中文字幕 | 免费黄色在线| AV狠狠干| 91插插网| 精品999999| 亚洲乱伦电影| 92丨九色丨偷拍老熟女| 爱视频福利| 法国《少女日记》电影| 日本一级片中文字幕| 亚洲日本三级| 久热在线精品视频| 国产操逼无码| 99久久婷婷国产综合精品青牛牛 | 国内免费毛片| 成人在线无码视频| 日韩av小电影| 国精产品一二四区黑人| 婷婷伊人綜合中文字幕| 欧美日韩中文字幕无码| 久久无码成人| 国产精品嫩草久久久久yw193 | 日本一级片免费看| 中国免费XXXX18| 高清日韩无码视频| 大香蕉久久久久| 欧洲激情网| 91操美女视频| 人妻熟女在线视频| 亚洲人成人无码一区二区三区| 最新日韩无码| 九九热精品在线| 国产中文人人国际| 成人性爱视频在线| ww无码| 午夜三级福利| 99热精品在线观看| 日韩无修正| 成年人黄色视频网站| 国产精品香蕉| 久精品视频| 松岛枫在线视频| 国产秘精品区二区三区日本| 一本久久精品一区二区| 中文字幕在线不卡| 秋霞一区二区三区无码| 91视频电影| 亚洲黄色电影网| 麻豆国产一区二区三区四区| A片在线视频| 大鸡巴午夜爽视频电影| 特级西西444www大胆高清图片 | 天堂麻豆天美| 麻豆91蜜桃传媒在线观看| 亚洲中文字幕人妻| 一区二区三区无码在线观看| 小佟丽娅大战91哥| 大香蕉伊人综合在线| 国产乱妇乱子伦视频免费观看让女人| 日韩三级毛片| 91三级片在线播放| 开心老牛熟| 久久精品一区二区三区四区| 九月丁香| 天天天天天天天天操| 91精品久久香蕉国产线看观看| 九七色色电影| 亚洲一卡二卡三卡四卡免| 91在线无码精品秘蜜桃入口| 激情性爱婷婷色五月| 久久a视频| 狠狠操狠狠撸| 亚洲美女喷水视频| 丁香六月色| 免费视频91蜜桃| 漂亮人妻吃鸡啪啪哥哥真的好| 日一区二区| 波多野在线视频| 在线观看三级网址| 日韩成人三级片| 国产精品秘麻豆果冻传媒潘甜甜丶| 黄色成人视频网站| 人人妻人人澡人人爽人人爽| 欧美激情综合色综合啪啪五月| 一道本不卡视频| 9l农村站街老熟女| 人人看人人干| 免费电影日本黄色| 日本91视频| 免费啪啪视频| 欧美亚洲成人视频| 精品二区| 国产亚洲视频免费观看| 亚洲电影av| 自拍第一页| 一级特黄色| 国产成人超碰| 国产成人无码Av片在线公司 | a一级黄片| 久久久久9999| 99精品视频国产| 夜夜骑夜夜操| 91高清无码视频| 三级黄色视频| 无码人妻一区二区三一区免费n狂飙 | 久久无码一区| aⅴ免费观看| 欧美综合在线观看| 亚洲黄色视频在线免费观看| 激情国产av| 日韩无码一卡| 日韩成人高清无码| 亚洲二区无码| 精品999| 成人精品亚洲人成在线| 色九| 亚洲免费视频在线看| 国产女人18毛片精品18水| 星空AV| 美女综合网| 2018天天日天天操| 免费看黃色AAAAAA片| 日本中文字幕在线免费观看| 黄色小视频免费看| 国产欧美综合一区二区| 黄片高清| 精品国产区一区二| 美日韩毛片| 高清视频无码| 久久精品网| 人人爽久久涩噜噜噜网站| 日韩精品一区二区三区四在线播放 | 久久久久国产一区二区三区四区 | 高清不卡一区二区| 天天拍夜夜操| 蜜臀AV网| 激情麻豆论坛| 99久久99九九九99九他书对| 超碰毛片| www.超碰在线| aaa在线观看| 中文字幕++中文字幕明步| 亚洲成人无码在线播放| 五月天乱伦网| 成人三级无码| 成年人视频免费| H片在线观看| 黄色操屄视频| 国产精品伦子伦免费视频| 久热精品视频在线观看| 欧美日韩色情| 日本一节片在线播放| 日韩免费观看视频| 天堂在线v| 亚洲成人一区| 又大又黄又爽| 99精品9| 日韩视频在线免费观看| 亚洲AV成人片色在线观看高潮| 韩剧《邻居的妻子》电视剧| 自拍视频在线观看| 久久久久99| 91精品久久久久久久| 亚洲精品中文字幕成人片| 啊哈嗯| 蜜桃传媒一区二区亚洲AV| 福利无码| 白丝在线观看| 成人精品三级AV在线看| A片大香蕉| 欧美操逼大全| 电影91久久久| 黄色免费看视频| 四川性BBB搡BBB爽爽爽小说| 日本人妻中文字幕| 无码潮喷| 中文字幕精品久久久久人妻红杏Ⅰ| 女人的天堂av| 国产精品久久久999| 苍井空精毛片精品久久久| 99热国产精品| 久久不卡视频| 色综合久久88色综合| 日本色色网站免费| 日韩无码AV电影| 密臀久久| 中文字幕国产在线观看| 阿宾MD0165麻豆沈娜娜| 日韩啪啪视频| 亚洲秘av无码一区二区| 国产凹凸视频在线观看| 青娱乐AV| 日韩免费无码视频| 无码动漫av| 日韩操逼av| 无码中文字幕| 抽插网| 福利视频一区二区| 日韩中文无码电影| 色妞视频精品一区| 第四色大香蕉| 操逼视频免费网站| 国产精品久久久久无码AV| 日韩精品你懂的| 特级黄色片| 欧美婷婷五月天| 日韩AV一区二区三区四区| 亚洲午夜久久久| 老鸭窝av免费入口在线观看| 日本乱伦视频| 欧美国产日本| 2019国产精品| 青青草91在线| 欧美性爱动态| 大鸡巴午夜爽视频电影| 国产91白丝在一线播放| 日韩有码在线观看| 91综合久久| 午夜试看120秒体验区的特点| AV无码不卡| 日韩操逼视频| 中文字幕偷拍| 91香蕉麻豆| 亚州高清无码视频| 91人人精品| 激情五月天激情网| 超碰毛片| 亚洲va在线∨a天堂va欧美va | 成人精品一区二区三区无码视频| www.黄色大片| 亚洲AAAAAA| 国产黄色视频网站| 猫咪AV成人永久网站| 日韩无| 国产TS在线| 日韩一级片网站| 91人人妻人人| 国产美女做爱| 在线观看免费欧美操逼视频| 欧美日韩免费| 先锋影音av资源网| 色婷婷AV国产精品| aaa久久| 狠狠干b| av在线资源播放| 国产中文字幕av| aV一区二区三区| 无码中文字| 在线播放毛片| 俩小伙3p老熟女露脸| 特黄AAAAAAAA片视频| 影音先锋成人资源AV在线观看| 欧美黄片在线| 免费无码视频在线观看| 国产在线拍揄自揄拍无码福利| 欧美成人网站在线| 亚洲欧洲精品在线| 欧美日韩国产在线播放| 久久污| 可以免费观看的av| 日韩黄色免费电影| 少妇bbb搡bbbb搡bbbb| 精品9999| 国产丝袜人妖TS系列| 91精彩视频在线观看| 黄片高清视频| 色婷婷18正码国产|