RestTemplate接口調用神器常見用法匯總
1、RestTemplate 概述
發送 http 請求,估計很多人用過 httpclient 和 okhttp,確實挺好用的,而 Spring web 中的 RestTemplate 和這倆的功能類似,也是用來發送 http 請求的,不過用法上面比前面的 2 位要容易很多。
spring 框架提供的 RestTemplate 類可用於在應用中調用 rest 服務,它簡化瞭與 http 服務的通信方式,統一瞭 RESTful 的標準,封裝瞭 http 鏈接, 我們隻需要傳入 url 及返回值類型即可。相較於之前常用的 HttpClient,RestTemplate 是一種更優雅的調用 RESTful 服務的方式。
在 Spring 應用程序中訪問第三方 REST 服務與使用 Spring RestTemplate 類有關。RestTemplate 類的設計原則與許多其他 Spring 模板類(例如 JdbcTemplate、JmsTemplate)相同,為執行復雜任務提供瞭一種具有默認行為的簡化方法。
RestTemplate 默認依賴 JDK 提供 http 連接的能力(HttpURLConnection),如果有需要的話也可以通過 setRequestFactory 方法替換為例如 Apache HttpComponents、Netty 或 OkHttp 等其它 HTTP library。
考慮到 RestTemplate 類是為調用 REST 服務而設計的,因此它的主要方法與 REST 的基礎緊密相連就不足為奇瞭,後者是 HTTP 協議的方法:HEAD、GET、POST、PUT、DELETE 和 OPTIONS。例如,RestTemplate 類具有 headForHeaders()、getForObject()、postForObject()、put()和 delete()等方法。
下面給大傢上案例,案例是重點,通過案例,把我知道的用法都給盤出來。
2、案例代碼
2.1、git 地址
https://gitee.com/javacode2018/springmvc-series
2.2、關鍵代碼位置
文中的所有 controller 代碼,在RestTemplateTestController
類中。
所有@Test 用例的代碼,在RestTemplateTest
。
2.3、如何運行測試用例?
- 拉取項目
- 將 chat16-RestTemplate 模塊發佈到 tomcat9 中
- 運行 RestTemplateTest 中對應的用例即可
下面咱們來看 RestTemplate 常見的用法匯總。
3、發送 Get 請求
3.1、普通請求
接口代碼
@GetMapping("/test/get") @ResponseBody public BookDto get() { return new BookDto(1, "SpringMVC系列"); }
使用 RestTemplate 調用上面這個接口,通常有 2 種寫法,如下
@Test public void test1() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/get"; //getForObject方法,獲取響應體,將其轉換為第二個參數指定的類型 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中包含瞭響應結果中的所有信息,比如頭、狀態、body ResponseEntity<BookDto> responseEntity = restTemplate.getForEntity(url, BookDto.class); //狀態碼 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 中含有動態參數
接口代碼
@GetMapping("/test/get/{id}/{name}") @ResponseBody public BookDto get(@PathVariable("id") Integer id, @PathVariable("name") String name) { return new BookDto(id, name); }
使用 RestTemplate 調用上面這個接口,通常有 2 種寫法,如下
@Test public void test3() { RestTemplate restTemplate = new RestTemplate(); //url中有動態參數 String url = "http://localhost:8080/chat16/test/get/{id}/{name}"; Map<String, String> 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中有動態參數 String url = "http://localhost:8080/chat16/test/get/{id}/{name}"; Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("id", "1"); uriVariables.put("name", "SpringMVC系列"); //getForEntity方法 ResponseEntity<BookDto> 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<BookDto> getList() { return Arrays.asList( new BookDto(1, "Spring高手系列"), new BookDto(2, "SpringMVC系列") ); }
當接口的返回值為泛型的時候,這種情況比較特殊,使用 RestTemplate 調用上面這個接口,代碼如下,需要用到restTemplate.exchange
的方法,這個方法中有個參數是ParameterizedTypeReference
類型,通過這個參數類指定泛型類型
@Test public void test5() { RestTemplate restTemplate = new RestTemplate(); //返回值為泛型 String url = "http://localhost:8080/chat16/test/getList"; //若返回結果是泛型類型的,需要使用到exchange方法, //這個方法中有個參數是ParameterizedTypeReference類型,通過這個參數類指定泛型類型 ResponseEntity<List<BookDto>> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<BookDto>>() { }); List<BookDto> bookDtoList = responseEntity.getBody(); System.out.println(bookDtoList); }
輸出
[BookDto{id=1, name='Spring高手系列'}, BookDto{id=2, name='SpringMVC系列'}]
3.4、下載小文件
接口代碼如下,這個接口會下載服務器端的 1.txt 文件。
/** * 下載文件 * * @return */ @GetMapping("/test/downFile") @ResponseBody public HttpEntity<InputStreamResource> downFile() { //將文件流封裝為InputStreamResource對象 InputStream inputStream = this.getClass().getResourceAsStream("/1.txt"); InputStreamResource inputStreamResource = new InputStreamResource(inputStream); //設置header MultiValueMap<String, String> headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=1.txt"); HttpEntity<InputStreamResource> httpEntity = new HttpEntity<>(inputStreamResource); return httpEntity; }
使用 RestTemplate 調用這個接口,代碼如下,目前這個文件的內容比較少,可以直接得到一個數組。
@Test public void test6() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/downFile"; //文件比較小的情況,直接返回字節數組 ResponseEntity<byte[]> responseEntity = restTemplate.getForEntity(url, byte[].class); //獲取文件的內容 byte[] body = responseEntity.getBody(); String content = new String(body); System.out.println(content); }
註意:如果文件大的時候,這種方式就有問題瞭,會導致 oom,要用下面的方式瞭。
3.5、下載大文件
接口代碼,繼續使用上面下載 1.txt 的代碼
/** * 下載文件 * * @return */ @GetMapping("/test/downFile") @ResponseBody public HttpEntity<InputStreamResource> downFile() { //將文件流封裝為InputStreamResource對象 InputStream inputStream = this.getClass().getResourceAsStream("/1.txt"); InputStreamResource inputStreamResource = new InputStreamResource(inputStream); //設置header MultiValueMap<String, String> headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=1.txt"); HttpEntity<InputStreamResource> httpEntity = new HttpEntity<>(inputStreamResource); return httpEntity; }
此時使用 RestTemplate 調用這個接口,代碼如下
文件比較大的時候,比如好幾個 G,就不能返回字節數組瞭,會把內存撐爆,導致 OOM,需要使用 execute 方法瞭,這個方法中有個 ResponseExtractor 類型的參數,restTemplate 拿到結果之後,會回調{@link ResponseExtractor#extractData}這個方法,在這個方法中可以拿到響應流,然後進行處理,這個過程就是變讀邊處理,不會導致內存溢出
@Test public void test7() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/downFile"; /** * 文件比較大的時候,比如好幾個G,就不能返回字節數組瞭,會把內存撐爆,導致OOM * 需要這麼玩: * 需要使用execute方法瞭,這個方法中有個ResponseExtractor類型的參數, * restTemplate拿到結果之後,會回調{@link ResponseExtractor#extractData}這個方法, * 在這個方法中可以拿到響應流,然後進行處理,這個過程就是變讀邊處理,不會導致內存溢出 */ String result = restTemplate.execute(url, HttpMethod.GET, null, new ResponseExtractor<String>() { @Override public String extractData(ClientHttpResponse response) throws IOException { System.out.println("狀態:"+response.getStatusCode()); System.out.println("頭:"+response.getHeaders()); //獲取響應體流 InputStream body = response.getBody(); //處理響應體流 String content = IOUtils.toString(body, "UTF-8"); return content; } }, new HashMap<>()); System.out.println(result); }
3.6、傳遞頭
接口代碼
@GetMapping("/test/header") @ResponseBody public Map<String, List<String>> header(HttpServletRequest request) { Map<String, List<String>> header = new LinkedHashMap<>(); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); Enumeration<String> values = request.getHeaders(name); List<String> list = new ArrayList<>(); while (values.hasMoreElements()) { list.add(values.nextElement()); } header.put(name, list); } return header; }
使用 RestTemplate 調用接口,請求頭中傳遞數據,代碼如下,註意代碼①和②
,這兩處是關鍵,用到瞭HttpHeaders
和RequestEntity
- 請求頭放在 HttpHeaders 對象中
- RequestEntity:請求實體,請求的所有信息都可以放在 RequestEntity 中,比如 body 部分、頭、請求方式、url 等信息
@Test public void test8() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/header"; //①:請求頭放在HttpHeaders對象中 MultiValueMap<String, String> headers = new HttpHeaders(); headers.add("header-1", "V1"); headers.add("header-2", "Spring"); headers.add("header-2", "SpringBoot"); //②:RequestEntity:請求實體,請求的所有信息都可以放在RequestEntity中,比如body部分、頭、請求方式、url等信息 RequestEntity requestEntity = new RequestEntity( null, //body部分數據 headers, //頭 HttpMethod.GET,//請求方法 URI.create(url) //地址 ); ResponseEntity<Map<String, List<String>>> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<Map<String, List<String>>>() { }); Map<String, List<String>> 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 動態參數
接口
@GetMapping("/test/getAll/{path1}/{path2}") @ResponseBody public Map<String, Object> getAll(@PathVariable("path1") String path1, @PathVariable("path2") String path2, HttpServletRequest request) { Map<String, Object> result = new LinkedHashMap<>(); result.put("path1", path1); result.put("path2", path2); //頭 Map<String, List<String>> header = new LinkedHashMap<>(); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); Enumeration<String> values = request.getHeaders(name); List<String> list = new ArrayList<>(); while (values.hasMoreElements()) { list.add(values.nextElement()); } header.put(name, list); } result.put("header", header); return result; }
如下,使用 RestTemplate 調用接口,GET 方式、傳遞 header、path 中動態參數。
@Test public void test9() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/getAll/{path1}/{path2}"; //①:請求頭 MultiValueMap<String, String> headers = new HttpHeaders(); headers.add("header-1", "V1"); headers.add("header-2", "Spring"); headers.add("header-2", "SpringBoot"); //②:url中的2個參數 Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("path1", "v1"); uriVariables.put("path2", "v2"); //③:HttpEntity:HTTP實體,內部包含瞭請求頭和請求體 HttpEntity requestEntity = new HttpEntity( null,//body部分,get請求沒有body,所以為null headers //頭 ); //④:使用exchange發送請求 ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange( url, //url HttpMethod.GET, //請求方式 requestEntity, //請求實體(頭、body) new ParameterizedTypeReference<Map<String, Object>>() { },//返回的結果類型 uriVariables //url中的占位符對應的值 ); Map<String, Object> 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 中發送 |
multipart/form-data | 頁面中表單上傳文件的時候,用到的就是這種格式 |
application/json | 將發送的數據轉換為 json 格式,丟在 http 請求的 body 中發送,後端接口通常用@RequestBody 配合對象來接收。 |
下面看則種方式的案例。
4.2、普通表單請求
普通表單默認為 application/x-www-form-urlencoded 類型的請求。
接口代碼
@PostMapping("/test/form1") @ResponseBody public BookDto form1(BookDto bookDto) { return bookDto; }
使用 RestTemplate 調用接口
@Test public void test10() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form1"; //①:表單信息,需要放在MultiValueMap中,MultiValueMap相當於Map<String,List<String>> MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); //調用add方法填充表單數據(表單名稱:值) body.add("id","1"); body.add("name","SpringMVC系列"); //②:發送請求(url,請求體,返回值需要轉換的類型) 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相當於Map<String,List<String>> MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); //調用add方法放入表單元素(表單名稱:值) body.add("id","1"); body.add("name","SpringMVC系列"); //②:請求頭 HttpHeaders headers = new HttpHeaders(); //調用set方法放入請求頭 headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); //③:請求實體:包含瞭請求體和請求頭 HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, headers); //④:發送請求(url,請求實體,返回值需要轉換的類型) 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<String, String> form2(@RequestParam("file1") MultipartFile file1) { Map<String, String> fileMetadata = new LinkedHashMap<>(); fileMetadata.put("文件名", file1.getOriginalFilename()); fileMetadata.put("文件類型", file1.getContentType()); fileMetadata.put("文件大小(byte)", String.valueOf(file1.getSize())); return fileMetadata; }
使用 RestTemplate 調用接口,主要下面代碼②
上傳的文件需要包裝為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相當於Map<String,List<String>> MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); //調用add方法放入表單元素(表單名稱:值) //②:文件對應的類型,需要是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"); //④:請求實體 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:發送請求(請求實體,返回值需要轉換的類型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
4.4、通過流或字節數組的方式上傳文件
有時候,上傳的文件是通過流的方式或者字節數組的方式,那麼就需要用到 InputStreamResource、ByteArrayResource 這倆瞭。
**註意:**使用這倆的時候,需要重寫 2 個方法,否則會上傳失敗
getFilename:文件名稱
contentLength:長度
@Test public void test13() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form2"; //①:表單信息,需要放在MultiValueMap中,MultiValueMap相當於Map<String,List<String>> MultiValueMap<String, Object> 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"); //④:請求實體 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:發送請求(請求實體,返回值需要轉換的類型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
4.5、復雜表單:多個普通元素+多文件上傳
接口
/** * 復雜的表單:包含瞭普通元素、多文件 * * @param userDto * @return */ @PostMapping("/test/form3") @ResponseBody public Map<String, String> form3(UserDto userDto) { Map<String, String> 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:包含瞭多個元素(姓名、頭像、多張證件照),這種可以模擬復雜的表單
public class UserDto { //姓名 private String name; //頭像 private MultipartFile headImg; //多張證件照 private List<MultipartFile> idImgList; //get set 省略瞭... }
用 RestTemplate 調用這個接口,代碼如下
@Test public void test14() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form3"; //①:表單信息,需要放在MultiValueMap中,MultiValueMap相當於Map<String,List<String>> MultiValueMap<String, Object> 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"); //④:請求實體 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:發送請求(請求實體,返回值需要轉換的類型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
輸出
{name=路人, headImg=1.jpg, idImgList=[2.jpg, 3.jpg]}
4.6、發送 json 格式數據:傳遞 java 對象
接口
/** * body中json格式的數據,返回值非泛型 * * @param bookDto * @return */ @PostMapping("/test/form4") @ResponseBody public BookDto form4(@RequestBody BookDto bookDto) { return bookDto; }
RestTemplate 調用接口
@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、發送 json 格式數據:傳遞 java 對象,返回值為泛型
接口
/** * body中json格式的數據,返回值為泛型 * * @param bookDtoList * @return */ @PostMapping("/test/form5") @ResponseBody public List<BookDto> form5(@RequestBody List<BookDto> bookDtoList) { return bookDtoList; }
用 RestTemplate 調用這個接口,代碼如下
@Test public void test16() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form5"; //①:請求體,發送的時候會被轉換為json格式數據 List<BookDto> body = Arrays.asList( new BookDto(1, "SpringMVC系列"), new BookDto(2, "MySQL系列")); //②:頭 HttpHeaders headers = new HttpHeaders(); headers.add("header1", "v1"); headers.add("header2", "v2"); //③:請求實體 RequestEntity requestEntity = new RequestEntity(body, headers, HttpMethod.POST, URI.create(url)); //④:發送請求(請求實體,返回值需要轉換的類型) ResponseEntity<List<BookDto>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<List<BookDto>>() { }); //⑤:獲取結果 List<BookDto> result = responseEntity.getBody(); System.out.println(result); }
輸出
[BookDto{id=1, name='SpringMVC系列'}, BookDto{id=2, name='MySQL系列'}]
4.8、發送 json 字符串格式數據
上面 2 個 json 案例 body 都是 java 對象,RestTemplate 默認自動配上 Content-Type=application/json
但是如果 body 的值是 json 格式字符串的時候,調用的時候需要在頭中明確指定 Content-Type=application/json,寫法如下:
public void delete(String url, Object... uriVariables); public void delete(String url, Map<String, ?> uriVariables); public void delete(URI url);
輸出
[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<String, ?> uriVariables); public void delete(URI url);
5.2、PUT 請求
PUT 請求和 POST 請求類似,將類型改為 PUT 就可以瞭。
5.3、OPTIONS 請求
OPTIONS 請求用來探測接口支持哪些 http 方法
public Set<HttpMethod> optionsForAllow(String url, Object... uriVariables); public Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables); public Set<HttpMethod> optionsForAllow(URI url);
6、集成 HttpClient
RestTemplate 內部默認用的是 jdk 自帶的 HttpURLConnection 發送請求的,性能上面並不是太突出。
可以將其替換為 httpclient 或者 okhttp。
先來看下如何替換為 HttpClient。
引入 maven 配置
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version> </dependency>
創建 RestTemplate 時指定 HttpClient 配置,代碼如下
public HttpClient httpClient() { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); try { //設置信任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<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() // 註冊http和https請求 .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory).build(); //使用Httpclient連接池的方式配置(推薦),同時支持netty,okHttp以及其他http框架 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); // 最大連接數 poolingHttpClientConnectionManager.setMaxTotal(1000); // 同路由並發數 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); //配置連接池 httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); // 重試次數 httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(0, true)); //設置默認請求頭 List<Header> headers = new ArrayList<>(); httpClientBuilder.setDefaultHeaders(headers); return httpClientBuilder.build(); } catch (Exception e) { throw new RuntimeException(e); } } public ClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient()); // 連接超時(毫秒),這裡設置10秒 clientHttpRequestFactory.setConnectTimeout(10 * 1000); // 數據讀取超時時間(毫秒),這裡設置60秒 clientHttpRequestFactory.setReadTimeout(60 * 1000); // 從連接池獲取請求連接的超時時間(毫秒),不宜過長,必須設置,比如連接不夠用時,時間過長將是災難性的 clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000); return clientHttpRequestFactory; } public RestTemplate restTemplate(){ //創建RestTemplate的時候,指定ClientHttpRequestFactory return new RestTemplate(this.clientHttpRequestFactory()); } @Test public void test18() { RestTemplate restTemplate = this.restTemplate(); String url = "http://localhost:8080/chat16/test/get"; //getForObject方法,獲取響應體,將其轉換為第二個參數指定的類型 BookDto bookDto = restTemplate.getForObject(url, BookDto.class); System.out.println(bookDto); }
7、集成 okhttp
引入 maven 配置
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.3.1</version> </dependency>
創建 RestTemplate
new RestTemplate(new OkHttp3ClientHttpRequestFactory());
8、總結
RestTemplate 使用確實非常容易,建議大傢去看一下 RestTemplate 的源碼,debug 跟蹤一下過程,這樣用起來就非常順手瞭。
到此這篇關於RestTemplate接口調用神器常見用法匯總的文章就介紹到這瞭,更多相關RestTemplate接口調用內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- RestTemplate實現發送帶headers的GET請求
- 淺談HttpClient、okhttp和RestTemplate的區別
- 如何使用spring ResponseEntity處理http響應
- spring boot RestTemplate 發送get請求的踩坑及解決
- java分佈式基於RestTemplate的使用方法