RestTemplate---Spring提供的輕量Http Rest 風格API呼叫工具
前言
今天在學習Spring Cloud的過程中無意發現了 RestTemplate 這個Spring 提供的Http Rest風格介面之間呼叫的模板工具類,感覺比Apache提供的HttpClient更加輕量化,只需要在容器中初始化該物件之後就可以使用,因此決定探索一下。
準備工作
首先建立一個SpringBoot父工程,新增必要的依賴,建立Mysql表,加入一些測試資料:
這裡我建立了一個 emp 員工表,添加了兩條測試資料,SQL語句如下:
建立表
DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `id` bigint(20) NOT NULL COMMENT '主鍵', `name` varchar(32) NOT NULL COMMENT '姓名', `join_time` datetime DEFAULT NULL COMMENT '入職時間', `sex` tinyint(4) DEFAULT NULL COMMENT '性別 0 未知 1 男 2 女', `address` varchar(64) DEFAULT NULL COMMENT '地址', `education_background` varchar(64) DEFAULT NULL COMMENT '教育背景', `age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡', `remark` varchar(128) DEFAULT NULL COMMENT '備註', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*Data for the table `emp` */ insert into `emp`(`id`,`name`,`join_time`,`sex`,`address`,`education_background`,`age`,`remark`) values (1,'無憂','2020-01-28 21:17:07',1,'陝西省/西安市/雁塔區/某某街道','本科',23,'創始人'),(2,'忘我','2020-01-28 21:18:12',1,'陝西省/西安市/雁塔區/某某街道','本科',22,'合夥人');
逆向生成
接著逆向生成實體類,Mapper和XML檔案。這裡我參考了部落格:堅持到底的部落格 博主解釋的很詳細,我就不重複說明了。
Service和Controller
service和controller 書寫起來也比較簡單,只是一些基本的CRUD,這裡我額外的添加了pageHelper 分頁助手外掛,為了更好的模擬線上真實環境。
至此,整個專案的目錄結構如下:
通過瀏覽器訪問對應的介面地址,獲得的資料如下。證明專案已經跑通。準備工作完成:
初步使用RestTemplate
建立專案
新建一個SpringBoot專案,為了方便,我這裡只寫Controller
利用SpringIOC建立Bean
在啟動類中往容器中注入RestTemplate的Bean
@SpringBootApplication
public class BossApplication {
public static void main(String[] args) {
SpringApplication.run(BossApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
使用其Get Api
在新專案中的Controller中注入Bean,然後呼叫其對應的Api即可快速的通過Http的方式呼叫介面了
@RestController
@RequestMapping("boss")
public class BossController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("employ/{id}")
public ResponseEntity<Emp> employById(@PathVariable Long id){
ResponseEntity<Emp> emp = null;
emp = restTemplate.getForEntity("http://127.0.0.1:9001/emp/" + id, Emp.class);
return emp;
}
}
測試效果如下,可以看到利用9002埠的專案已經呼叫到9001的專案併成功獲取資料:
深入使用
前面我們已經可以初步的使用RestTemplate進行服務之間通過HttpRest請求進行呼叫了,接下來我們更深入的探索其他的API。Http Rest請求常用的請求方法有4種,分別是 POST、DELETE、PUT、GET。分別對應增刪改查4個動作。而在url中加上操作的資源名稱。並不出現動詞便是我理解的RestFul風格API。下面我對不同的請求方法分別詳細介紹其對應的呼叫方法。
GET
專案中查詢的介面一般有兩種:根據ID查詢詳情和根據引數查詢列表。根據ID查詢詳情我已經在前面展示了
這裡要說明的就是 getForEntity 和 getForObject 方法,他兩的引數是相同的,但返回值型別不同 getForEntity 返回的是 ResponseEntity
@Nullable
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, (Object[])uriVariables);
}
// 可以看到,getForEntity 只是對getForObject的結果進行強制型別轉換,並沒有什麼特別的操作
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
帶請求引數的GET
專案中一般都會有分頁條件查詢的介面,此時請求引數以key value 形式提交。我們只需要呼叫對應的過載方法即可
例如有如下介面。根據性別分頁查詢員工:
@RequestMapping("/list/{sex}/{pageNum}/{pageSize}")
public List<Emp> getByParam(@PathVariable Integer sex,
@PathVariable Integer pageNum,
@PathVariable Integer pageSize){
return empService.getListByPara(pageNum, pageSize, sex);
}
我們通過RestTemplate可以這樣查詢:
@RequestMapping("employList/{sex}")
public List employById1(@PathVariable Integer sex,
@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
// 直接返回物件
List emp = null;
Map<String, Object> paraMap = new HashMap<>();
paraMap.put("pageNum", pageNum);
paraMap.put("pageSize", pageSize);
paraMap.put("sex", sex);
// 通過map的形式,spring會將url對應的引數key替換成value
// emp = restTemplate.getForObject("http://127.0.0.1:9001/emp/list/{sex}/{pageNum}/{pageSize}", List.class, paraMap);
// 通過可變參的形式,spring會按順序替換url中的引數
emp = restTemplate.getForObject("http://127.0.0.1:9001/emp/list/{sex}/{pageNum}/{pageSize}", List.class, pageNum, pageSize, sex);
return emp;
}
以上是完全按照Rest風格的GET url,引數都是在url上以PathVariable 的形式出現的,但如果引數不在url上,就需要稍加修改了
非Rest風格GET請求
我們知道,GET請求的請求引數一般都在url上拼接。url後面以 ? 開始,key=value 的形式拼接多個請求引數。多個鍵值對之間用 & 符號連線。我琢磨了很久也只發現了字串拼接這種傳參方式,(慚愧,回去該好好讀讀 http 請求相關的書籍了)如果讀者發現了更好的方法請不吝賜教!實現程式碼如下:
@RequestMapping("employList1/{sex}")
public List employList1(@PathVariable Integer sex,
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
HttpServletRequest request) {
// 直接返回物件
List emp = null;
// 請求引數
Map<String, Object> map= new HashMap<>();
map.put("pageNum", pageNum);
map.put("pageSize", pageSize);
map.put("sex", sex);
// 在url中拼接引數,然後由spring從map中將值替換
emp = restTemplate.getForObject("http://127.0.0.1:9001/emp/list/{sex}" + "?pageNum={pageNum}&pageSize={pageSize}", List.class, map);
return emp;
}
POST
專案中,POST請求一般以JSON的形式傳送。基本的傳送方法很簡單。將物件打包好扔到方法的第二個引數就可以傳送了
@RequestMapping("new")
public int addEmploy(@RequestBody Emp emp) {
return restTemplate.postForObject("http://127.0.0.1:9001/emp/new", emp, Integer.class);
}
PS:在測試 POST 請求的過程中我發現了兩處配置問題
- 插入的資料亂碼,這個需要在資料庫連線url中加引數。設定編碼位 utf8
url: jdbc:mysql://192.168.25.128:3306/mysql?characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT
- 之前寫的 select * 查詢沒有開啟mysql下劃線到Java駝峰的自動轉換,導致入職日期,教育背景欄位沒有讀取成功
這個在 application.yml 中可以配置:
mybatis:
mapper-locations: classpath:cn/keats/mapper/*Mapper.xml
configuration:
map-underscore-to-camel-case: true
PUT DELETE
put 請求類似於 post,delete 請求類似於 get。這裡就不在贅述了
後記
RestTemplate的介紹就到這裡了,以上的方法基本涵蓋了專案目前所有的介面,使用RestTemplate給我的感受就是如果介面完全按照Rest風格書寫,使用其方法很簡單,基本上一行程式碼就呼叫成功了。如果不是完全按照Rest風格的介面就需要多花費一些時間來二次封裝介面了。推薦呼叫Rest風格API時候使用。
GITHUB專案地址
此部落格的所有程式碼都已經同步上傳至我的GITHUB倉庫中,想要練手的朋友不妨克隆下來使用
RestTemplate 使用介紹 RestTemplate傳送GET、POST請求的示例項