RestTemplate詳解
一:get
之前實驗中我們已經使用過RestTemplate去實現服務訪問了,我們現在可以仔細研究下這個對象針對幾種不同請求類型和參數類型的服務調用實現
依舊是我們剛纔的實驗,參與者有 Eureka Server(服務註冊中心),product(服務調用者)、user(服務提供者)
啓動服務如上
現在product中調用服務提供者的代碼如下:
訪問結果:
這裏我們調用的方法是:
User user=restTemplate.getForObject("http://USER/user/"+String.valueOf(id),User.class);
關於restTemplate提供的主要方法,get方式的請求主要包含以下的兩種,其一就是我們使用的getForObject,還有一種爲getForEntity
首先我們來看getForEntity,官方重載函數有以下:
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}
參數說明:
1:請求的URL地址
2: Class responseType 規定封裝爲某種需要的對象類型
3:Object… uriVariables 參數列表-可以多個也可以封裝成一個map信息傳遞
該方法的返回值都爲ResponseEntity,其中主要存儲了http的幾個重要元素,例如請求狀態碼的枚舉類型Httpstatus、其父類HttpEntity中還存儲着頭信息等重要屬性
方法調用如下:
public User getUserById(@PathVariable("id") long id){
//User user=restTemplate.getForObject("http://USER/user/"+String.valueOf(id),User.class);
ResponseEntity<User> responseEntity= restTemplate.getForEntity("http://USER/user/{id}"+String.valueOf(id),User.class,id);
System.out.println("---------------------------------------------------");
System.out.println(responseEntity);
System.out.println("---------------------------------------------------");
User user=responseEntity.getBody();
return user;
}
現在去訪問:
我們發現依舊是正常訪問,但是我們來看後臺打印結果值
<200,com.bigsoft.bigsoftproduct.pojo.User@358c78bd,[Content-Type:"application/json", Transfer-Encoding:"chunked", Date:"Thu, 07 May 2020 06:04:39 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>
我們發現這裏打印信息比較全面(和瀏覽器控制檯打印的差不多)
反過頭再看我們的另外個主要的方法getForObject 官方定義如下:
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> T getForObject(URI url, Class<T> responseType)
其實我們發現和上邊方法重載一樣的,都是地址+type+參數的形式
我們修改我們的代碼如下:
@Autowired
private RestTemplate restTemplate;
@GetMapping("product/user/{id}")
public User getUserById(@PathVariable("id") long id){
User user=restTemplate.getForObject("http://USER/user/{id}"+String.valueOf(id),User.class,id);
return user;
}
訪問服務:
我們發現也能正常訪問
其實以上的兩個方法區別就在於,一個直接幫你綁定成你需要的對象,另外一個返回了更多的訪問信息
二:post
關於post請求RestTemplate也提供了全面的方法供我們調用
1:postForEntity
這個方法不管名字和用法其實和get中的getForEntity也非常相似,主要重載如下:
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException
我們看到參數也非常相似,主要使用的前兩種也是url+type+參數的組合拳,下邊我們的做一個具體的測試,首先在user服務提供節點新增addUser方法
這裏爲了測試返回了一段文字,現實中千萬不要這麼做
代碼如下:
@PostMapping("/addUser")
public String addUser(@RequestBody User user){
System.out.println(user);
return "add--------"+user+"-----------success";
}
然後在product節點中通過去調用該方法,具體調用如下:
@PostMapping("product/addUser")
public String addUser(){
User user=new User();
user.setUserId(10086L);
user.setUserName("user1");
user.setUserPwd("admin");
ResponseEntity<String> resp=restTemplate.postForEntity("http://USER/addUser",user,String.class);
System.out.println(resp);
return "add--------"+user+"-----------success";
}
這裏restTemplate.postForEntity("http://USER/addUser",user,String.class);
三個參數分別代表了路徑、參數類型、期待返回類型
我們使用postman 測試,測試結果如下:
我們再來看看後臺打印的ResponseEntity
<200,add--------User{userId=10086, userName=‘user1’, userPwd=‘admin’}-----------success,[Content-Type:“text/plain;charset=UTF-8”, Content-Length:“82”, Date:“Wed, 13 May 2020 06:17:58 GMT”, Keep-Alive:“timeout=60”, Connection:“keep-alive”]>
這樣就完成了我們的post請求調用,我們這裏修改一句上邊的代碼:
System.out.println(resp.getBody());
這次我們直接獲取它的body信息,我們可以看到如下,這次的打印結果如下
add--------User{userId=10086, userName=‘user1’, userPwd=‘admin’}-----------success
這裏其實body中的類容就是我們在這調用的時候規定了返回值爲string類型,所以body中指存在了user節點返回的值
和get相似的是post除了有postForEntity方法也存在postForObject方法,一樣的是,postForEntity返回的是整個response 信息,而postForObject 只是返回我們泛型中規定的信息
通過這兩個方法我們就能使用ribbon去調用微服務各個節點了