摘要:也是提交新資源,提交成功之后,返回新資源的,的參數和前面兩種的參數基本一致,只不過該方法的返回值為,這個只需要服務提供者返回一個即可,該表示新資源的位置。用于操作請求頭和,在請求發出前執行。
背景
這段時間自己做的項目中需要調用服務提供者的服務(接口),具體就是:我這邊需要將頁面所輸入的 Groovy 腳本代碼傳給別人提供的服務接口,然后那邊返回腳本編譯的結果給我,我需要將編譯結果展示在頁面,用的就是 RestTemplate 了,那 RestTemplate 是什么呢?簡單說就是:簡化了發起 HTTP 請求以及處理響應的過程,并且支持 REST 。下文就稍微總結下。
先講講如何使用吧,我項目是 SpringBoot 項目,可以在啟動類中加入:
@Bean public RestTemplate restTemplate() { return new RestTemplate(); }
然后在 Controller 層中引入:
@Autowired private RestTemplate restTemplate;
接下來就可以在 Controller 中各個方法中使用 restTemplate 了,但是 restTemplate 里面有什么方法呢?
RestTemplate 內部方法從圖中 RestTemplate 可以看到有很多方法,我們可以提取出主要的幾種方法是:
GET
POST
PUT
DELETE
HEAD
OPTIONS
EXCHANGE
EXECUTE
圖片中依然可以知道 RestTemplate 類中的方法主要是來自接口 RestOperations,下面我們具體看看這些方法里面的具體實現與該如何使用。
Get 方法在 RestTemplate 中,發送一個 GET 請求,我們可以通過如下兩種方式:
getForEntity
getForEntity 方法的返回值是一個ResponseEntity
@RequestMapping("/gethello") public String getHello() { ResponseEntityresponseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class); String body = responseEntity.getBody(); HttpStatus statusCode = responseEntity.getStatusCode(); int statusCodeValue = responseEntity.getStatusCodeValue(); HttpHeaders headers = responseEntity.getHeaders(); StringBuffer result = new StringBuffer(); result.append("responseEntity.getBody():").append(body).append("
") .append("responseEntity.getStatusCode():").append(statusCode).append("
") .append("responseEntity.getStatusCodeValue():").append(statusCodeValue).append("
") .append("responseEntity.getHeaders():").append(headers).append("
"); return result.toString(); }
關于這段代碼,說如下幾點:
getForEntity 的第一個參數為我要調用的服務的地址,這里我調用了服務提供者提供的 /hello 接口,注意這里是通過服務名調用而不是服務地址,如果寫成服務地址就沒法實現客戶端負載均衡了。(備注:我項目中需要通過 ConsulClient 去獲取服務名,然后在去獲取服務的 IP 和 Port,并把它拼接起來組合成我的服務地址,所以就沒法實現客戶端的負載均衡了,如果要是實現負載均衡,可以在 SpringBoot 啟動類的中加入注解 @LoadBalanced, 如下:
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
)
getForEntity 第二個參數 String.class 表示我希望返回的 body 類型是 String
拿到返回結果之后,將返回結果遍歷打印出來
有時候我在調用服務提供者提供的接口時,可能需要傳遞參數,有兩種不同的方式:
@RequestMapping("/sayhello") public String sayHello() { ResponseEntityresponseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={1}", String.class, "張三"); return responseEntity.getBody(); } @RequestMapping("/sayhello2") public String sayHello2() { Map map = new HashMap<>(); map.put("name", "李四"); ResponseEntity responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={name}", String.class, map); return responseEntity.getBody(); }
可以用一個數字做占位符,最后是一個可變長度的參數,來一 一替換前面的占位符
也可以前面使用 name={name} 這種形式,最后一個參數是一個 map,map 的 key 即為前邊占位符的名字,map的 value 為參數值
第一個調用地址也可以是一個URI而不是字符串,這個時候我們構建一個URI即可,參數神馬的都包含在URI中了,如下:
@RequestMapping("/sayhello3") public String sayHello3() { UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/sayhello?name={name}").build().expand("王五").encode(); URI uri = uriComponents.toUri(); ResponseEntityresponseEntity = restTemplate.getForEntity(uri, String.class); return responseEntity.getBody(); }
通過Spring中提供的UriComponents來構建Uri即可。
當然,服務提供者不僅可以返回String,也可以返回一個自定義類型的對象,比如我的服務提供者中有如下方法:
@RequestMapping(value = "/getbook1", method = RequestMethod.GET) public Book book1() { return new Book("三國演義", 90, "羅貫中", "花城出版社"); }
對于該方法我可以在服務消費者中通過如下方式來調用:
@RequestMapping("/book1") public Book book1() { ResponseEntityresponseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/getbook1", Book.class); return responseEntity.getBody(); }
運行結果如下:
getForObject
?
getForObject 函數實際上是對 getForEntity 函數的進一步封裝,如果你只關注返回的消息體的內容,對其他信息都不關注,此時可以使用 getForObject,舉一個簡單的例子,如下:
@RequestMapping("/book2") public Book book2() { Book book = restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class); return book; }POST 方法
在 RestTemplate 中,POST 請求可以通過如下三個方法來發起:
postForEntity
該方法和get請求中的getForEntity方法類似,如下例子:
@RequestMapping("/book3") public Book book3() { Book book = new Book(); book.setName("紅樓夢"); ResponseEntityresponseEntity = restTemplate.postForEntity("http://HELLO-SERVICE/getbook2", book, Book.class); return responseEntity.getBody(); }
方法的第一參數表示要調用的服務的地址
方法的第二個參數表示上傳的參數
方法的第三個參數表示返回的消息體的數據類型
我這里創建了一個Book對象,這個Book對象只有name屬性有值,將之傳遞到服務提供者那里去,服務提供者代碼如下:
@RequestMapping(value = "/getbook2", method = RequestMethod.POST) public Book book2(@RequestBody Book book) { System.out.println(book.getName()); book.setPrice(33); book.setAuthor("曹雪芹"); book.setPublisher("人民文學出版社"); return book; }
服務提供者接收到服務消費者傳來的參數book,給其他屬性設置上值再返回,調用結果如下:
postForObject
如果你只關注,返回的消息體,可以直接使用postForObject。用法和getForObject一致。
postForLocation
postForLocation 也是提交新資源,提交成功之后,返回新資源的 URI,postForLocation 的參數和前面兩種的參數基本一致,只不過該方法的返回值為 URI ,這個只需要服務提供者返回一個 URI 即可,該 URI 表示新資源的位置。
PUT 方法在 RestTemplate 中,PUT 請求可以通過 put 方法調用,put 方法的參數和前面介紹的 postForEntity 方法的參數基本一致,只是 put 方法沒有返回值而已。舉一個簡單的例子,如下:
@RequestMapping("/put") public void put() { Book book = new Book(); book.setName("紅樓夢"); restTemplate.put("http://HELLO-SERVICE/getbook3/{1}", book, 99); }
book對象是我要提交的參數,最后的99用來替換前面的占位符{1}
DELETE 方法delete 請求我們可以通過 delete 方法調用來實現,如下例子:
@RequestMapping("/delete") public void delete() { restTemplate.delete("http://HELLO-SERVICE/getbook4/{1}", 100); }HEADER 方法
返回資源的所有 HTTP headers。
OPTIONS問可以執行哪些方法。
EXCHANGE與其它接口的不同:
允許調用者指定HTTP請求的方法(GET,POST,PUT等)
可以在請求中增加body以及頭信息,其內容通過參數 HttpEntity>requestEntity 描述
exchange支持‘含參數的類型’(即泛型類)作為返回類型,該特性通過 ParameterizedTypeReference
細心的你,不知道有沒有發現上面所有的方法內部返回值都調用了同一個方法 —— execute 方法。
下面我們來看看:
可以看到,Excute方法只是將 String 格式的 URI 轉成了 java.net.URI,之后調用了doExecute方法。整個調用過程關鍵起作用的是 doExecute 方法
doExecute 方法這里需要了解兩個類: RequestCallback 和 ResponseExtractor
RestTemplate 類中可以看到他們兩的實現類。
RequestCallback :用于操作請求頭和body,在請求發出前執行。
該接口有兩個實現類:
AcceptHeaderRequestCallback | 只處理請求頭,用于getXXX()方法。 |
---|---|
HttpEntityRequestCallback | 繼承于AcceptHeaderRequestCallback可以處理請求頭和body,用于putXXX()、postXXX()和exchange()方法。 |
ResponseExtractor:解析HTTP響應的數據,而且不需要擔心異常和資源的關閉
上面圖紙這個實現類 ResponseEntityResponseExtractor 的作用是:使用 HttpMessageConverterExtractor 提取 body(委托模式),然后將 body 和響應頭、狀態封裝成 ResponseEntity 對象。
最后轉載請注明地址:http://www.54tianzhisheng.cn/...
參考資料1、https://www.cnblogs.com/caole...
2、https://segmentfault.com/a/11...
如果想和我進一步交流請關注:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70764.html
摘要:一個客戶端請求從發出到被響應經歷了哪些組件哪些微服務請求總時長每個組件所花時長等信息我們有必要了解和收集,以幫助我們定位性能瓶頸進行性能調優,因此監控整個微服務架構的調用鏈十分有必要,本文將闡述如何使用搭建微服務調用鏈追蹤中心。 showImg(https://segmentfault.com/img/remote/1460000014553707); 概述 一個完整的微服務系統包含...
摘要:時間年月日星期日說明本文部分內容均來自慕課網。用戶可以在服務器端調用云存儲云檢索從而構建自己的存儲和檢索服務,甚至可以制作自己的數據管理臺。 時間:2017年08月13日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://github.com/zccodere/s... 第一章:云圖產品介紹 1-1 云圖產品介紹...
摘要:時間年月日星期日說明本文部分內容均來自慕課網。用戶可以在服務器端調用云存儲云檢索從而構建自己的存儲和檢索服務,甚至可以制作自己的數據管理臺。 時間:2017年08月13日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://github.com/zccodere/s... 第一章:云圖產品介紹 1-1 云圖產品介紹...
摘要:客戶端負載均衡需要客戶端自己維護自己要訪問的服務實例清單,這些服務清單來源于注冊中心在使用進行服務治理時。使用從負載均衡器中挑選出的服務實例來執行請求內容。 客戶端負載均衡Spring Cloud Ribbon ?Spring Cloud Ribbon是一個基于HTTP和TCP的客戶端負載均衡工具,基于Netflix Ribbon實現。 目錄 客戶端負載均衡(本文重點) 源碼分析(本...
摘要:準備服務端我是用的是一個普通的第一種方式直接使用,寫死第一種方式直接使用,寫死第二種方式第二種方式利用通過應用名獲取,然后再使用第二種方式利用通過應用名獲取,然后再使用第三種方式第三種方式利用,可再里使用應用名字第三種方式利用,可再里使用應 準備 服務端我是用的是一個普通的API @RestController public class ServerController { ...
閱讀 3094·2021-08-03 14:05
閱讀 2140·2019-08-29 15:35
閱讀 678·2019-08-29 13:30
閱讀 3169·2019-08-29 13:20
閱讀 2531·2019-08-23 18:15
閱讀 1797·2019-08-23 14:57
閱讀 2213·2019-08-23 13:57
閱讀 1310·2019-08-23 12:10