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