1、引文
之前做需求的時候杈女,有一次遇到一個場景:判斷某一天是工作日、休息日或節(jié)假日吊圾。從網(wǎng)上找了一個接口http://tool.bitefu.net/jiari/ 用法如下圖
如上所示达椰,我們僅在這個接口尾部輸入yyyyMMDD格式的日期參數(shù),就能知道當天是工作日(0)项乒、休息日(1)和節(jié)假日(2)了啰劲。
做法如下:
public static String httpClient(String dateString){
//創(chuàng)建客戶端
CloseableHttpClient httpClient = HttpClients.createDefault();
//拼接uri
String uri = "http://tool.bitefu.net/jiari/?d=%s";
String format = String.format(uri, dateString);
//創(chuàng)建請求
HttpGet httpGet = new HttpGet(format);
try {
//調(diào)用接口,返回結(jié)果
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response!=null){
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity,"UTF-8");
return result;
}else{
return "error";
}
} catch (IOException e) {
e.printStackTrace();
}
return "error";
}
可以發(fā)現(xiàn)當前代碼中其實只有極少的代碼與調(diào)用接口有關(guān)檀何,我們希望僅僅需要傳入uri和參數(shù)蝇裤,就能夠返回我們想要的結(jié)果廷支。在這里我們不得不捕獲或拋出檢查型異常IOException。如果我們在編寫一個方法栓辜,調(diào)用其他接口恋拍,又需要我們寫非常多的重復的代碼。這并不符合我的期望藕甩。
Spring 提供給我們一些模版施敢,給我們的很大的便利。舉個例子狭莱,我們在使用傳統(tǒng)的jdbc去操作數(shù)據(jù)庫的時候僵娃,我們需要加載驅(qū)動、建立連接腋妙、寫sql默怨、傳參、執(zhí)行和返回結(jié)果骤素,在完成之后我們還需要去關(guān)閉鏈接匙睹,不得不去捕獲拋出的檢查型異常。但是spring提供給我們的jdbcTempalte谆甜,在設(shè)置了dataSource之后垃僚,我們僅僅需要執(zhí)行類似這樣一句
jdbcTemplate.setDataSource(dataSource);
String sql = "select count(*) from user";
Long num = (long) jdbcTemplate.queryForObject(sql, Long.class);
即可返回user的數(shù)量,它已經(jīng)幫我們完成連接的建立规辱、關(guān)閉以及異常處理等等操作谆棺。
RestTemplate也是這樣為了提供給我們方便的而生的,它定義了36個與REST資源交互的方法罕袋,其中的大多數(shù)都對應于HTTP的方法改淑。但是,沒有足夠的篇幅涵蓋所有的36個方法浴讯。其實朵夏,這里面只有11個獨立的方法,其中有十個有三種重載形式榆纽,而第十一個則重載了六次仰猖,這樣一共形成了36個方法。
除了TRACE以外奈籽,RestTemplate涵蓋了所有的HTTP動作饥侵。除此之外,execute()和exchange()提供了較低層次的通用方法來使用任意的HTTP方法衣屏。
2躏升、Get
從上面的三個方法中進行分析:
第一個方法傳參是直接調(diào)用url,responseType代表了返回值的類型狼忱。
第二個方法提供了多個參數(shù)的植入膨疏,通常來說一睁,這些參數(shù)是根據(jù)url中填參部分,依次填入佃却。
第三個方法利用Map填參者吁,Map的key值與url缺少的參數(shù)名要保持一致。
上圖展示了三種方法的使用方式双霍,它們均可以給出我們想要的結(jié)果砚偶。
此外還有一個方法getForEntity( ),它的使用方式和getForObject( )大同小異洒闸,它們都執(zhí)行根據(jù)URL檢索資源的GET請求染坯。它們都將資源根據(jù)responseType參數(shù)匹配為一定的類型。唯一的區(qū)別在于getForObject()只返回所請求類型的對象丘逸,而getForEntity()方法會返回請求的對象以及響應相關(guān)的額外信息单鹿。如下所示,它還能返回http狀態(tài)碼以及的響應頭信息深纲。
為了實現(xiàn)更通用的HTTP頭信息訪問仲锄,HttpHeaders提供了get()方法和getFirst()方法。兩個方法都接受String參數(shù)來標識所需要的頭信息湃鹊。get()將會返回一個String值的列表儒喊,其中的每個值都是賦給該頭部信息的,而getFirst()方法只會返回第一個頭信息的值币呵。
3怀愧、POST
不管是URL類型還是String類型,第一個參數(shù)都是資源要POST到的URL余赢;
第二個參數(shù)是要發(fā)送的對象芯义;
第三個參數(shù)是預期返回的Java類型。
在將URL作為String類型的兩個版本中妻柒,第四個參數(shù)指定了URL變量(要么是可變參數(shù)列表扛拨,要么是一個Map,與上一節(jié)的使用方法一致)举塔。
postForLocation 绑警、postForObject 、postForEntity的區(qū)別:
類似于get類型央渣,postForObject 和postForEntity擁有的作用類似待秃,他們講第二個參數(shù)要發(fā)送的對象推送到服務器進行處理。而postForEntity的場景還是為了查看一些響應中的頭信息痹屹,比如說一些Location信息,我們可以使用ResponseEntity.getHeaders().getLocation()的方式獲得枉氮。如果要同時接收所發(fā)送的資源和響應頭志衍,postForEntity()方法是很便利的暖庄。但通常你并不需要將資源發(fā)送回來(畢竟,將其發(fā)送到服務器端是第一位的)楼肪。如果你需要的僅僅是Location頭信息的值培廓,那么使用RestTemplate的postForLocation()方法會更簡單。
4春叫、Delete
實際上肩钠,delete是RestTemlate中最簡單的方法,唯一需要我們提供的就是url和要刪除的對象的ID即可暂殖,在這里就不舉例了价匠。
5、Put
在RestFul接口規(guī)范中呛每,我們通常使用put來進行數(shù)據(jù)的更新修改踩窖。
RestTemplate提供了三個簡單的put()方法,第一個參數(shù)是指定的Url晨横,第二個參數(shù)是需要更新的對象洋腮,后面的參數(shù)是對utl的補全。
從getForObject()和getForEntity()方法中我們也看到了手形,使用基于String的其他put()方法能夠為我們減少創(chuàng)建URI的不便啥供。對象將被轉(zhuǎn)換成什么樣的內(nèi)容類型很大程度上取決于傳遞給put()的類型。如果給一個String值库糠,那么將會使用StringHttpMessageConverter:這個值直接被寫到請求體中伙狐,內(nèi)容類型設(shè)置為“text/plain”。如果給定一個MultiValueMap<String,String>曼玩,那么這個Map中的值將會被FormHttpMessageConverter以“application/x-www-form-urlencoded”的格式寫到請求體中鳞骤。
6、exchange
RestTempalte中定義很多重載的exchange()方法黍判,如下
String|URL :請求路徑
HttpMethod:Http的動作豫尽,如Get、delete等
requestEntity():在請求中發(fā)送資源顷帖,get可以為null
responseType(如果要獲取狀態(tài)碼和header可使用ResponseEntity<T>):返回數(shù)據(jù)的類型
Map/Object... :填充Url的參數(shù)
exchange()利用HttpMethod這個參數(shù)美旧,可以完成其他RestTemplate方法的工作,如上GET贬墩、POST榴嗅、DELETE、PUT等陶舞。exchange()優(yōu)于其他方法的點事它可以在發(fā)送給服務器的請求中加入頭信息嗽测。
MultiValueMap<String,String> headers = new LinkedMultiValueMap<>();
headers.add("User-Agent","Java/1.8.0_161");
...
HttpEntity<Object> requestEntity = new HttpEntity<>(headers);