RestTemplate
是由Spring
框架提供的一個可用于應用中調用rest
服務的類它簡化了與http
服務的通信方式,統(tǒng)一了RESTFul
的標準,封裝了http
連接,我們只需要傳入url
及其返回值類型即可。相較于之前常用的HttpClient
,RestTemplate
是一種更為優(yōu)雅的調用RESTFul
服務的方式。Spring
應用程序中訪問第三方REST服務
與使用Spring RestTemplate
類有關。RestTemplate
類的設計原則與許多其他Spring
的模板類(例如JdbcTemplate
)相同,為執(zhí)行復雜任務提供了一種具有默認行為的簡化方法。RestTemplate
默認依賴JDK提供了http
連接的能力(HttpURLConnection
),如果有需要的話也可以通過setRequestFactory
方法替換為例如Apache HttpCompoent、Netty或OKHttp
等其他Http libaray
。RestTemplate
類是為了調用REST服務而設計的,因此它的主要方法與REST
的基礎緊密相連就不足為奇了,后者時HTTP
協(xié)議的方法:HEAD、GET、POST、PUT、DELETE、OPTIONS
例如,RestTemplate
類具有headForHeaders()、getForObject()、putForObject(),put()和delete()
等方法。RestTemplate
? 因為RestTemplate
是Spirng
框架提供的所以只要是一個Springboot
項目就不用考慮導包的問題,這些都是提供好的。
? 但是Spring
并沒有將其加入SpringBean
容器中,需要我們手動加入,因為我們首先創(chuàng)建一個Springboot
配置類,再在配置類中將我們的RestTemlate
注冊到Bean
容器中
? 使用Springboot
提供的RestTemplateBuilder
構造類來構造一個RestTemplate
,可以自定義一些連接參數(shù),如:連接超時時間,讀取超時時間,還有認證信息等
@Configuration
public class WebConfiguration {@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){return builder
//設置連接超時時間
.setConnectTimeout(Duration.ofSeconds(5000))
//設置讀取超時時間
.setReadTimeout(Duration.ofSeconds(5000))
//設置認證信息
.basicAuthentication("username","password")
//設置根路徑
.rootUri("https://api.test.com/")
//構建
.build();
}
}
添加自定義的攔截器? 自定義攔截器示例
@Slf4j
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {//打印請求明細
logRequestDetails(request,body);
ClientHttpResponse response = execution.execute(request, body);
//打印響應明細
logResponseDetails(response);
return response;
}
private void logRequestDetails(HttpRequest request, byte[] body){log.debug("Headers:{}",request.getHeaders());
log.debug("body:{}",new String(body, StandardCharsets.UTF_8));
log.debug("{}:{}",request.getMethod(),request.getMethodValue());
}
private void logResponseDetails(ClientHttpResponse response) throws IOException {log.debug("Status code : {}",response.getStatusCode());
log.debug("Status text : {}",response.getStatusText());
log.debug("Headers : {}",response.getHeaders());
log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(),StandardCharsets.UTF_8));
}
}
? 使用RestTemplateBuilder
構造類,添加自定義攔截器,構造帶有自定義攔截器的RestTemplate
實例
@Configuration
public class WebConfiguration {@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){return builder
.additionalInterceptors(new CustomClientHttpRequestInterceptor())
//構建
.build();
}
}
? 測試請求確實經(jīng)過了攔截器,注冊成功(注意請求和響應的流只會被讀取一次,這里我們讀取了response后返回的response就讀取不到剛剛讀過的內(nèi)容了)
?
? 使用RestTemplate
構造方法構造一個RestTemlate
,雖然不能像RestTemplate
構造類那樣更詳細、更多樣的配置參數(shù),但是RestTemplate
構造方法在一般情況是夠用的。
ClientHttpRequestFactory
的構造方法可以指定自己實現(xiàn)的ClientHttpRequestFactory
(客戶端http
請求工廠)其他的與無參構造相同。ClientHttpRequestFactory
List>
的構造方法可以指定自己是實現(xiàn)的HttpMessageConverter
(Http
消息轉換器)傳入其他與無參構造相同。@Configuration
public class WebConfiguration {@Bean
public RestTemplate restTemplate(){return new RestTemplate();
}
}
? 兩者方法都可使用,前者提供了多樣的自定義參數(shù)的選擇,可以將RestTemplate
配置的更為完善,后者則簡化了配置雖然配置多樣性不如前者,但是日常使用調用些API
還是足以使用
RestTemplate API
使用? 在使用RestTemplate
前先讓我們看看RestTemplate
有哪些API
? 相信大家看到這么多方法,一定很頭大,但是我們仔細看上述的方法,我們可以提取出主要的幾種方法是(這里只討論Http請求的):
GET
POST
PUT
DELETE
HEAD
OPTIONS
EXCHANGE
EXECUTE
? 這里我給大家安利一個一個網(wǎng)站,它提供免費的RESTFul api的樣例測試。httpbin A simple HTTP Request & Response Service.
? 通過上圖我們可以發(fā)現(xiàn)RestTemlate
發(fā)送GET
請求的方法有兩種
public
T getForObject(...) public
ResponseEntity getForEntity(...)
getForEntity()
? 后綴帶有Entity
的方法都代表返回一個ResponseEntity
,ResponseEntity
是Spring對HTTP
請求響應的封裝,包括了幾個重要的元素,如響應碼,contentType、contentLength
、響應消息體等
? 通過它繼承父類(HttpEntity
)的getHeader()
方法我們可以獲取contentType、contentLength
、響應消息體等。比如下面這個例子。
public void queryWeather() {ResponseEntity
? 該例子中getForEntity()
方法的第一個參數(shù)為我要調用服務的URL
,第二個參數(shù)則為響應內(nèi)容的類的類型(Java嘛 萬物皆對象)還可以添加第三個參數(shù),第三個參數(shù)為一個可變參數(shù) 代表著調用服務時的傳參。
第三個參數(shù)可以使用key-value的map來傳入?yún)?shù)
? get請求也可通過向在url上添加查詢參數(shù)來發(fā)送帶有請求的參數(shù)
getForObject()
? 相比于前者getForEntity()
該方法則是,更偏向于直接獲取響應內(nèi)容的,因為他直接返回響應實體的body
(響應內(nèi)容),。比如下面這個例子
public void queryWeather() {
Object body = restTemplate.getForObject("https://restapi.amap.com/v3/weather/weatherInfo?city=510100&key=e7a5fa943f706602033b6b329c49fbc6", Object.class);
System.out.println(body);
}
方法參數(shù)簽名與`getForEntity()`基本一致。
? 當你只需要返回的響應內(nèi)容時,使用getForObject()
是一個很好的選擇,但當你需要獲得更詳細的響應信息,如響應頭中的信息,你就只能選擇getForEntity()
了。
?POST
請求有如下三種方法
public URI postForLocation(...)
public
T postForObject(...) public
ResponseEntity postForEntity(...)
? 后兩種用法與GET
基本一致不做詳細介紹,這里著重介紹postForLocation()
postForEntity()
? 該方法有三個參數(shù),第一個為調用服務的地址(URL)
? 第二個參數(shù)表示上傳的參數(shù)(json格式提交)
? 第三個表示返回響應內(nèi)容的具體類型
? 第四個參數(shù)也用于指定參數(shù)(在URL中添加)
@Override
public void queryWeather() {User user = new User();
user.setName("魯大師");
ResponseEntity
postForObject()
? 使用方法與getForObject
類似只是多了一個傳入對象參數(shù)(傳入方式與postForEntity()
相同)
public void queryWeather() {User user = new User();
user.setName("魯大師");
ResponseEntity
postForLocation()
?postForLocation
傳參用法與前兩者一致,只不過返回從實體變成了一個URL
,因此它不需要指定返回響應內(nèi)容的類型。
public void queryWeather() {User user = new User();
user.setName("魯大師");
URI uri = restTemplate.postForLocation("https://httpbin.org/post", user);
System.out.println(uri);
}
這個只需要服務提供者返回一個 URI 即可,該URI
返回值體現(xiàn)的是:用于提交完成數(shù)據(jù)之后的頁面跳轉,或數(shù)據(jù)提交完成之后的下一步數(shù)據(jù)操作URI
。
? 這里我們著重說一下,如何自己封裝一個請求體。
? 我們需要用到如下幾個類
HttpHeaders
MultiValueMap
HttpEntity
HttpHeaders
? 故名思意,就是用來封裝Http請求的請求頭的,這里我們要設置他的ContentType
為**MediaType.APPLICATION_FORM_URLENCODED
**以使得我們提交的參數(shù)是以Form(表單)的形式提交。
//設置請求頭, x-www-form-urlencoded格式的數(shù)據(jù)
HttpHeaders httpHeaders = new HttpHeaders();
//這里指定參數(shù)以UTF-8編碼格式傳輸
MediaType mediaType = new MediaType(MediaType.APPLICATION_FORM_URLENCODED, UTF_8);
httpHeaders.setContentType(mediaType);
//提交參數(shù)設置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","魯大師");
MultiValueMap
? 該類是用來封裝請求參數(shù)的,是以key-value
的形式封裝但是以單個key對應多個value的格式傳輸(也就是是以單個key:[value...]
的格式傳輸?shù)?。
//提交參數(shù)設置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","魯大師");
? 如果像傳輸單個key
對應單個value
使用普通的Map
傳參即可
HttpEntity
? 該類是用來封裝請求的,主要作用就是將請求頭和請求體封裝在一起成為一個請求實體 T用來指定用來封裝參數(shù)的容器的類型。
//組裝請求體
HttpEntity>request = new HttpEntity<>(map, httpHeaders);
通過上述介紹后,我們就可以自己封裝一個以form形式提交參數(shù)的POST
請求了。
@Test
void contextLoads() {//請求地址
String url = "https://httpbin.org/post";
//設置請求頭, x-www-form-urlencoded格式的數(shù)據(jù)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//提交參數(shù)設置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","魯大師");
//組裝請求體
HttpEntity>request = new HttpEntity<>(map, httpHeaders);
//發(fā)送post請求并打印結果 以String類型接收響應結果JSON字符串
String s = restTemplate.postForObject(url, request, String.class);
System.out.println(s);
}
? 通過攔截器攔截了請求并對請求頭進行拆包,可以發(fā)現(xiàn)ContentType
已經(jīng)被修改成了x-www-form-urlencoded
格式了。
?PUT
請求的方法只有一類
void put()
PUT()
? 使用方法與postForEntity()
參數(shù)基本一致,只是put
方法沒有返回值(也就不必去設置響應內(nèi)容的類型了)。
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/put";
User user = new User();
user.setName("魯大師");
restTemplate.put(url,user);
}
? 與PUT
一樣,DELETE
方法只有一類
void delete()
delete()
?delete()
可以指定url
中的中的參數(shù),但是RestTemplate
的delete()
方法是不支持上傳requestBody
的。
void contextLoads() {//請求地址
String url = "http://httpbin.org/delete";
restTemplate.delete(url);
}
?HEADER
也只有一類方法
public HttpHeaders headForHeaders()
? 主要用來發(fā)送請求獲取響應頭部信息,但是像DELETE
、PUT
這類沒有響應的方法,是不能使用該方法的(因為沒有響應也就沒有響應頭了)。
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/get";
HttpHeaders httpHeaders = restTemplate.headForHeaders(url);
System.out.println(httpHeaders);
}
public Set
optionsForAllow()
? 該方法的主要用來判斷該服務地址,能夠使用那種方法去執(zhí)行
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/get";
SethttpMethods = restTemplate.optionsForAllow(url);
System.out.println(httpMethods);
}
ResponseEntity exchange()
? 該接口與其他接口不同
- 該方法允許用戶指定請求的方法(
get,post,put
等)- 可以在請求中增加body以及頭信息,其內(nèi)容通過參數(shù)
HttpEntity>requestEntity
描述exchange
支持’含參數(shù)的類型(即泛型)'作為返回類型,該特性通過ParameterizedTypeReferenceresponseType
描述
? 該方法支持五個參數(shù)
- 第一個是服務地址
- 第二個是請求方法
- 第三個是寫入的請求實體
- 第四個是響應內(nèi)容的類型
- 第五個是擴展模板的變量或包含
URI
模板變量的映射
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/post";
User user = new User();
user.setName("彭于晏");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntityuserHttpEntity = new HttpEntity<>(user, httpHeaders);
ResponseEntity
? 上述代碼模擬了一個簡單的POST
請求 可以理解為可以動態(tài)的指定請求方法和請求實體的一個方法。
響應實體
T execute()
? 該方法就是執(zhí)行請求的方法,我們可以發(fā)現(xiàn)上述的所有方法的最后執(zhí)行都是調用的該方法執(zhí)行,所以他在RestTemplate
中十分重要
? 該方法有五個參數(shù)
- 服務地址
- 請求的方法
- 準備請求的對象(
requestCallback
)- 從響應中提取返回值的對象
- 擴展模板的變量或包含
URI
模板變量的映射
execute()
@Override
@Nullable
publicT execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractorresponseExtractor, Object... uriVariables) throws RestClientException {URI expanded = getUriTemplateHandler().expand(url, uriVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
? 通過上述源碼我們可以發(fā)現(xiàn)execute()
方法只是將我們傳入的String
類型的URL
轉換為了URL
類型,最后執(zhí)行請求是由doExecute()
方法
doExecute()
? 這里需要了解兩個類:RequestCallback
和ResPonseExtractor
?RequestCallback
: 用于操作請求頭和body,在請求發(fā)出前執(zhí)行。不需要關心關閉請求或處理錯誤:這都將由RestTemplate處理。
? 該接口有兩個實現(xiàn)類:
?
?ResPonseExtractor
: 解析HTTP響應的數(shù)據(jù),而且不需要擔心異常和資源的關閉。
? 該接口在RestTemplate
中同樣有兩個實現(xiàn)類:
HeadersExtractor | 提取響應HttpHeaders 的響應提取器。直接提取響應體中的響應頭 | |
---|---|---|
ResponseEntityResponseExtractor | HttpEntity 的響應提取器。可以獲取響應實體里面包括響應頭,響應體等。具體請查看HttpEntity |
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/post";
User user = new User();
user.setName("彭于晏");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntityuserHttpEntity = new HttpEntity<>(user, httpHeaders);
ResponseEntity
URI
模板變量的映射我們來簡單看一下這個參數(shù),我們知道請求傳參可以通過url
拼接參數(shù)的方式傳參,拼接參數(shù)也分為兩種:
- 路徑中嵌入占位的格式(
http://httpbin.org/{1}/post
)也叫模板映射- 末尾添加
Key-value
格式(http://httpbin.org/post?name="彭于晏"
)即擴展模板的變量
key-value
的格式拼接在URL
后(通俗的說就是這樣設置的變量會跟著URL
路徑后面)?http://httpbin.org/post?name="彭于晏"
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/get";
HashMapmap = new HashMap<>();
map.put("name","彭于晏");
Object forObject = restTemplate.getForObject(url, Object.class, map);
System.out.println(forObject);
}
@Test
void contextLoads() {//請求地址
String url = "http://httpbin.org/{2}/get";
HashMapmap = new HashMap<>();
Object forObject = restTemplate.getForObject(url, Object.class, 99);
System.out.println(forObject);
}
spring cloud 做微服務時關于RestTemplate中的各種請求方法的使用總結_DWT_CCFK的博客-博客
RestTemplate 詳解 - 知乎 (zhihu.com)
RestTemplate使用教程 - 簡書 (jianshu.com)
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁名稱:RestTemplate-創(chuàng)新互聯(lián)
轉載來源:http://jinyejixie.com/article22/gegcc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供電子商務、自適應網(wǎng)站、定制開發(fā)、網(wǎng)站策劃、建站公司、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容