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 分頁助手插件,為了更好的模擬線上真實環境。

至此,整個項目的目錄結構如下:

1580223958684

通過瀏覽器訪問對應的接口地址,獲得的數據如下。證明項目已經跑通。准備工作完成:

1580224000291

初步使用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的項目並成功獲取數據:

1580225028150

深入使用

前面我們已經可以初步的使用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 請求的過程中我發現了兩處配置問題

  1. 插入的數據亂碼,這個需要在數據庫連接url中加參數。設置編碼位 utf8
url: jdbc:mysql://192.168.25.128:3306/mysql?characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT

  1. 之前寫的 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請求的示例項目


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM