6、SpringCloud之Rest請求模板類
服務消費端去呼叫服務提供者的服務的時候,使用了RestTemplate。RestTemplate通過getForEntity方法發起請求呼叫服務端的資料,並通過@LoadBanlaced註解開啟客戶端負載均衡。
RestTemplate中常見請求方法的使用
GET 查
POST 增
PUT 改
DELETE 刪
通過註解指定通過什麼請求方式進行訪問,如下:
@Autowired private RestTemplate restTemplate; // 通過@GetMapping註解就能夠指定請求方式 @GetMapping("/web/hello") public String hello(){ // Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了) return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class).getBody(); }
RestTemplate 的 GET請求
Get請求可以有兩種方式
第一種:getForEntity
該方法返回一個ResponseEntity
@Autowired private RestTemplate restTemplate; // @RequestMapping("/web/hello") @GetMapping("/web/hello") public String hello(){ //這裡泛型之所以是String型別,是因為方法的第二引數指定了返回型別為String ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class); int statusCodeValue = responseEntity.getStatusCodeValue(); HttpStatus statusCode = responseEntity.getStatusCode(); HttpHeaders headers = responseEntity.getHeaders(); String body = responseEntity.getBody(); System.out.println(statusCodeValue); System.out.println(statusCode); System.out.println(headers); System.out.println(body); // Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了) return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class).getBody(); }
getForEntity方法第二個引數String.class 表示希望返回的body型別是String型別,如果希望返回一個物件,也是可以的,比如User物件;
給兩個服務提供者端,提供實體類User
package com.example.springcloud.model; public class User { private Integer id; private String name; private String phone; @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", phone='" + phone + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
並提供返回值為User的Controller方法
@RequestMapping("/service/user")
public User user(){
User user = new User();
user.setId(12);
user.setName("小黑");
user.setPhone("12345678978");
return user;
}
此時,由於服務呼叫者呼叫此方法返回資料將資料繫結到實體類User物件上,所以也需要建立User實體類;
當多個工程都需要同一個實體類時,可以選擇構建父工程,用Maven進行模組化管理。
此外,服務呼叫端需要提供一個方法來呼叫服務提供端
@GetMapping("/web/user")
public String user(){
//這裡泛型之所以是String型別,是因為方法的第二引數指定了返回型別為String
ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/user", User.class);
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpStatus statusCode = responseEntity.getStatusCode();
HttpHeaders headers = responseEntity.getHeaders();
User body = responseEntity.getBody();
System.out.println(statusCodeValue);
System.out.println(statusCode);
System.out.println(headers);
System.out.println(body.getId()+","+body.getName()+","+body.getPhone());
// Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了)
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class).getBody();
}
完成之後,啟動服務註冊中心工程,服務提供端,以及服務呼叫端進行測試
getForEntity 常用的過載方法
服務提供端 接收請求引數並進行返回
//通過@RequestParam進行引數繫結
@RequestMapping("/service/user")
public User getUser(@RequestParam("id") Integer id,
@RequestParam("name") String name,
@RequestParam("phone") String phone){
System.out.println("服務提供者1");
User user = new User();
user.setId(id);
user.setName(name);
user.setPhone(phone);
return user;
}
服務消費端
下面以兩種方式。通過陣列和Map對url請求地址進行引數繫結
/**
* getForEntity()以陣列的方式將引數繫結到URL引數中
* 通過 {下標} 佔位符的方式進行繫結
* 返回資料的封裝型別為User型別(返回值型別也可以是String)
* @return
*/
@GetMapping("/web/ArrayParamGetUser")
public String getUser(){
String[] strArray = {"105", "小紅", "12345678989"};
// Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了)
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={1}&name={2}&phone={3}", User.class, strArray).getBody().toString();
}
/**
* getForEntity()以陣列的方式將引數繫結到URL引數中
* 通過 {key} 佔位符的方式進行繫結
* 返回值型別是String型別
* @return
*/
@GetMapping("/web/MapParamgetUser")
public String getUser2(){
Map<String, Object> paramMap = new ConcurrentHashMap<>();
paramMap.put("id",1);
paramMap.put("name","小誠");
paramMap.put("phone", "1546879166");
// Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了)
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&name={name}&phone={phone}", String.class, paramMap).getBody();
}
第二種:getForObject()
共同點
getForObject()方法是getForEntity()方法的封裝;
getForEntity方法過載的,getForObject方法也有,使用方式也類似;
不同點
getForEntity方法可以拿到返回的資料,同時也可以拿到頭部資訊狀態碼等;
getForObject方法只能用於獲取返回的body資訊;
/**
* getForEntity()以Map的方式將引數繫結到URL引數中
* @return
*/
@GetMapping("/web/getUserByGetForObject")
public String getUserByGetForObject(){
Map<String, Object> paramMap = new ConcurrentHashMap<>();
paramMap.put("id",1);
paramMap.put("name","小誠");
paramMap.put("phone", "1546879166");
//用請求模板類RestTemplate的getForObject方法,傳入一個Map物件通過{key}佔位符繫結url請求引數,返回值型別為String型別
String body = restTemplate.getForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&name={name}&phone={phone}", String.class, paramMap);
System.out.println(body);
String[] strArray = {"105", "小紅", "12345678989"};
//用請求模板類RestTemplate的getForObject方法,傳入一個Map物件通過{index}佔位符繫結url請求引數,返回值型別為User物件型別
User user2 = restTemplate.getForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&name={name}&phone={phone}", User.class, strArray);
System.out.println(user2);
return restTemplate.getForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class);
}
RestTemplate 的 POST 請求
POST 與 Get 請求 非常類似
restTemplate.postForObject()
restTemplate.postForEntity()
restTemplate.postForLocation()
服務提供者新增支援Post請求的方法
// @RequestMapping(value="/service/addUser", method = RequestMethod.POST)
@PostMapping("/service/addUser")
public User addUser(@RequestParam("id") Integer id,
@RequestParam("name") String name,
@RequestParam("phone") String phone){
System.out.println("服務提供者1");
User user = new User();
user.setId(id);
user.setName(name);
user.setPhone(phone);
//將user物件插入資料庫(暫時省略)
return user;
}
服務消費者新增呼叫Post請求的方法
/**
* 消費者呼叫 -addUser方法
* @return
*/
@RequestMapping("/web/addUser")
public String addUser(){
//注意post請求傳遞引數只能用MultiValueMap
MultiValueMap<String, Object> dataMap = new LinkedMultiValueMap();
dataMap.add("id",1);
dataMap.add("name","小誠");
dataMap.add("phone", "1546879166");
ResponseEntity<User> responseEntity = restTemplate.postForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/addUser", dataMap, User.class);
System.out.println(responseEntity.getStatusCodeValue());
System.out.println(responseEntity.getStatusCode());
System.out.println(responseEntity.getHeaders());
System.out.println(responseEntity.getBody());
User user = restTemplate.postForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/addUser", dataMap, User.class);
System.out.println(user);
return "請求成功";
}
RestTemplate 的 PUT 請求
服務提供者新增支援Put請求的方法
// @RequestMapping(value="/service/updateUser", method = RequestMethod.PUT)
@PutMapping("/service/updateUser")
public User updateUser(@RequestParam("id") Integer id,
@RequestParam("name") String name,
@RequestParam("phone") String phone){
User user = new User();
user.setId(id);
user.setName(name);
user.setPhone(phone);
System.out.println("服務提供者1");
System.out.println(user);
//將user物件插入資料庫(暫時省略)
return user;
}
服務消費者新增呼叫Put請求的方法
/**
* 消費者呼叫 -updateUser方法
* @return
*/
@RequestMapping("/web/updateUser")
public String updateUser(){
MultiValueMap<String, Object> dataMap = new LinkedMultiValueMap();
dataMap.add("id",1);
dataMap.add("name","小誠");
dataMap.add("phone", "1546879166");
//put請求沒有返回值
restTemplate.put("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/updateUser",dataMap);
return "請求成功";
}
RestTemplate 的 DELETE 請求
服務提供者新增支援Put請求的方法
// @RequestMapping(value="/service/addUser", method = RequestMethod.PUT)
@DeleteMapping("/service/deleteUser")
public User deleteUser(@RequestParam("id") Integer id,
@RequestParam("name") String name,
@RequestParam("phone") String phone){
User user = new User();
user.setId(id);
user.setName(name);
user.setPhone(phone);
System.out.println("服務提供者2");
System.out.println(user);
//將user物件插入資料庫(暫時省略)
return user;
}
服務消費者新增呼叫Delete請求的方法
/**
* 消費者呼叫 -deleteUser方法
* @return
*/
@RequestMapping("/web/deleteUser")
public String deleteUser(){
String[] strArray = {"105", "小紅", "12345678989"};
restTemplate.delete("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/deleteUser?id={0}&name={1}&phone={2}", strArray);
Map<String, Object> paramMap = new ConcurrentHashMap<>();
paramMap.put("id",1);
paramMap.put("name","小誠");
paramMap.put("phone", "1546879166");
restTemplate.delete("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/deleteUser?id={id}&name={name}&phone={phone}", paramMap);
return "請求成功";
}
總結:
Get 和 Delete 寫法相似
Post 和 Put 寫法相似