### 13.2.3 REST Client
上一章講到如何在SpringBoot中提供RESTfull服務,本章將介紹系統之間,如何發起REST請求。
SpringBoot提供了RestTemplate來輔助發起一個REST請求,默認通過JDK自帶的HttpURLConnection來作為底層HTTP消息的發送,使用JackSon 來序列化服務器響應的JSON數據
#### 13.2.3.1 RestTemplate
RestTemplate是核心類,提供了所有訪問Rest服務的接口,盡管實際上可以使用HTTP Client類或者java.net.URL 來完成,但RestTemplate提供了Restful風格的的API。
RestTemplate有6個主要得方法對應于Restful的6個主要得Http Method。
| HTTP Method | Java API |
| ----------- | ----------------------------- |
| DELETE | delete |
| GET | getForObject,getForEntity |
| HEAD | headForHeaders |
| OPTIONS | optionsForAllow |
| POST | postForObject,postForLocation |
| PUT | put |
| 其他 | exchange(通用) |
SpringBoot 提供了RestTemplateBuilder來創建一個RestTemplat。應用可以通過如下代碼來創建一個RestTemplate實例
~~~java
@Autowired
RestTemplateBuilder restTemplateBuilder;
public void foo(){
RestTemplate client = restTemplateBuilder.build();
}
~~~
下面列舉一下使用RestTemplate來查詢訂單和創建訂單
~~~java
/*一個測試類*/
@Controller
@RequestMapping("/test")
public class RestClientTestCrontroller {
@Value(value = "${api.order}")
String base ;
@Autowired
RestTemplateBuilder restTemplateBuilder;
@GetMapping("/get/{orderId}")
public @ResponseBody Order testGetOrder(@PathVariable String orderId) throws Exception{
RestTemplate client = restTemplateBuilder.build();
String uri = base+"/order/{orderId}";
//核心代碼
Order order = client.getForObject(uri, Order.class,orderId);
return order;
}
}
~~~
base是在配置文件application.properties中配置的訂單API地址
~~~properties
api.order=http://127.0.0.1:8080/api/v1
~~~
代碼首先構造RestTemplate,然后調用getForObject,此方法接受三個參數,第一個是URI 模板,第二個參數是期望返回的對象,后面是URI模板對應的參數列表。參數列表既可以是數組,也可以是個Map,如上有可以寫成
~~~java
Map map = new HashMap();
map.put("orderId",orderId);
Order order = client.getForObject(uri, Order.class,map);
~~~
如果還想獲取響應的HTTP頭相關信息,可以調用client.getForEntity,此方法返回ResponseEntity,包含了頭信息
~~~java
ResponseEntity<Order> responseEntity = client.getForEntity(uri, Order.class, orderId);
Order order = responseEntity.getBody();
HttpHeaders headers = responseEntity.getHeaders();
~~~
添加訂單可以使用postForObject方法,此方法接受三個參數,第一個是URI,第二個是Post參數,可以是HttpEntity,或者是某個POJO對象,POJO對象在這種情況下回自動轉成HTTPEntity,第三個參數是期望返回的類型,這個例子期望返回類型是String
~~~java
@GetMapping("/addorder")
public @ResponseBody String testAddOrder() throws Exception{
RestTemplate client = restTemplateBuilder.build();
String uri = base+"/order";
Order order = new Order();
order.setName("test");
String ret = client.postForObject(uri, order, String.class);
//{success:true,message:"添加成功"}
return ret;
}
~~~
或者使用HttpEntity
~~~java
HttpEntity<Order> body = new HttpEntity<Order>(order);
String ret = client.postForObject(uri, body, String.class);
~~~
使用HttpEnity的好處是可以提供額外的HTTP頭信息。
如果期望返回的類型是一個列表,如List<Order>,不能簡單調用xxxForObject,因為存在泛型的類型擦除,RestTemplate在反序列化的時候并不知道實際反序列化的類型,因此可以使用ParameterizedTypeReference來包含泛型類型,代碼如下
```java
RestTemplate client = restTemplateBuilder.build();
//根據條件查詢一組訂單
String uri = base+"/orders?offset={offset}";
Integer offset = 1;
//無參數
HttpEntity body = null;
ParameterizedTypeReference<List<Order>> typeRef = new ParameterizedTypeReference<List<Order>>() {};
ResponseEntity<List<Order>> rs = client.exchange(uri, HttpMethod.GET, body, typeRef, offset);
List<Order> order = rs.getBody();
```
注意到typeRef實際定義是用{}結束,這里實際上創建了一個ParameterizedTypeReference子類,依據在類定義中的泛型信息是保留的原則,typeRef保留了期望返回的泛型List<Order>
exchange 是一個基礎的Rest調用接口,除了需要指明HTTP Method外,調用跟其他方法都類似。
> 除了使用ParameterizedTypeReference來保留泛型信息外,也可以通過getForObject方法先映射成String,然后通過ObjectMapper來轉為指定類型,可以參考第三章Jackson來了解。
#### 13.2.3.2 定制 RestTemplate
創建一個配置類實現RestTemplateCustomizer接口的customize方法,此方法會
~~~java
@Configuration
public class RestConf implements RestTemplateCustomizer {
public void customize(RestTemplate restTemplate) {
SimpleClientHttpRequestFactory jdkHttp = (SimpleClientHttpRequestFactory)restTemplate.getRequestFactory();
jdkHttp.setConnectTimeout(1000);
}
}
~~~
如上代碼,customize方法會定制RestTemplate,上面的代碼設置鏈接超時時間為1000毫秒。Spring Boot因為默認使用了JDK的URLConnection作為底層的HTTP工具,如果想使用了OkHttp。需要添加如下依賴
~~~xml
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.0.1</version>
</dependency>
~~~
那上面的代碼應該是
~~~java
public void customize(RestTemplate restTemplate) {
OkHttp3ClientHttpRequestFactory okHttp = (OkHttp3ClientHttpRequestFactory)restTemplate.getRequestFactory();
okHttp.setReadTimeout(5000);
okHttp.setWriteTimeout(3000);
}
~~~
- 再版說明
- 13 REST
- 13.1 REST
- 13.1.1 REST 風格的架構
- 13.1.2 使用api作為上下文
- 13.1.3 增加一個版本標示
- 13.1.4 標識資源
- 13.1.5 確定HTTP METHOD
- 13.1.6 確定HTTP Status
- 13.1.7 REST VS WebService
- 13.2 SpringBoot Rest集成
- 13.2.1 集成REST
- 13.2.2 @RestController
- 13.2.3 REST Client
- 13.3 Swager UI
- 13.3.2 集成Swager UI
- 13.3.3 OpenAPI 規范
- 13.3.4 接口描述
- 13.3.5 查詢參數描述
- 13.3.6 URI中的參數
- 13.3.7 HTTP 頭參數
- 13.3.8 表單參數
- 13.3.9 整個請求體作為參數
- 14 MongoDB
- 14.1 安裝MongoDB
- 14.2 使用shell
- 14.2 .1 指定數據庫
- 14.2.2 插入文檔
- 14.2.3 查詢文檔
- 14.2.4 更新操作
- 14.2.5 刪除操作
- 14.3 Spring Boot集成
- 14.4 增刪改查
- 14.4.1 增加API
- 14.4.2 根據主鍵查詢API
- 14.4.3 查詢API
- 14.4.4 修改API
- 14.4.5 刪除API
- 14.4.6 使用MongoDatabase
- 14.4.7 打印日志
- 14.5 使用Spring Data
- 15 Redis
- 15.1 安裝Redis
- 15.2 使用redis-cli
- 15.2 .1 安全設置
- 15.2.2 基本操作
- 15.2.3 Keys
- 15.2.3 Redis List
- 15.2.4 Redis Hash
- 15.2.5 Set
- 15.2.6 Pub&Sub
- 15.3 Spring Boot 集成
- 15.4 使用StringRedisTemplate
- 15.4.1 opsFor
- 15.4.2 綁定key的操作
- 15.4.3 RedisConnection
- 15.4.4 Pub&Sub
- 15.4.5 Pipeline
- 15.5 序列化策略
- 15.5.1 默認序列化策略
- 15.5.2 自定義序列化策略
- 16 Elastic Search
- 16.1 Elastic Search 介紹
- 16.1.1Elastic 安裝
- 16.2.1 創建Index
- 16.2.2 添加文檔
- 16.2.3 根據主鍵查詢
- 16.2.4 根據主鍵更新
- 16.2.5 根據主鍵刪除
- 16.2.6 搜索文檔
- 16.2.7 聯合多個索引搜索
- 16.2.8 Mapping
- 16.2.9 路由
- 16.3 使用RestTemplate 訪問ES
- 16.3.1 創建Book
- 16.3.2 使用RestTemplate 獲取搜索結果
- 16.4 Spring Data Elastic
- 16.4.1 安裝Spring Data
- 16.4.2 編寫entity
- 15.4.3 編寫Dao
- 16.4.4 編寫Controller
- 17 Cache
- 17.1 關于Cache
- 17.1.1 Cache 組件和概念
- 17.1.2 Cache的單機應用
- 17.1.3 使用專有的Cache服務器
- 17.1.4 使用一二級緩存服務器
- 17.2 Spring Boot Cache
- 17.2.1 集成Spring cache
- 17.3 注釋驅動緩存
- 17.3.1 @Cacheable
- 17.3.2 KEY生成器
- 17.3.2 @CachePut
- 17.3.3 @CacheEvict
- 17.3.4 @Caching
- 17.3.5 @CacheConfig
- 17.4 使用Redis Cache
- 17.4.1集成Redis 緩存
- 17.4.2 禁止緩存
- 17.4.3 定制緩存
- 17.4. 5 Redis緩存原理
- 17.5 實現Redis 倆級緩存
- 17.5.1 實現 TwoLevelCacheManager
- 17.5.2 創建RedisAndLocalCache
- 17.5.3 緩存同步說明
- 17.5.4 將代碼組合在一起
- 18 Spring Session
- 18.1 水平擴展實現
- 18.2 nginx 安裝和配置
- 18.2.1 安裝nginx
- 18.2.2 配置nginx
- 18.3 Spring Session
- 18.3.1 Spring Session介紹
- 18.3.2 使用Redis
- 18.3.3 Nginx+Redis
- 19 SpringBoot 和 Zookeeper
- 19.1 Zookeeper
- 19.1.1 zookeeper 數據結構
- 19.1.2 Zookeeper 安裝
- 19.1.3 zookeeper 基本命令
- 19.1.4 領導選取演示
- 19.1.5 分布式鎖演示
- 19.1.6 服務注冊演示
- 19.2 Spring boot 集成zookeeper
- 19.2.1 集成 Curator
- 19.2.2 Curator api
- 19.3 分布式鎖實現
- 19.4 服務注冊
- 19.4.1 服務注冊
- 19.4.2 獲取服務
- 19.5 領導選取
- 19.6 屏障
- 20 監控SpringBoot應用
- 20.1 安裝Acutator
- 20.2 HTTP 跟蹤
- 20.3 日志查看
- 20.4 線程棧信息
- 20.5 內存信息
- 20.6 查看URL映射
- 20.7 查看Spring管理Bean
- 20.8 其他監控
- 20.9 編寫自己的監控信息
- 20.9.1 編寫HealthIndicator
- 20.9.2 自定義監控。