Spring RestTemplate的使用
Spring Boot在1.4版本及之後,Spring Boot不再自動定義一個RestTemplate,而是定義了一個RestTemplateBuilder,允許您更好地控制RestTemplate的對象。你可以在標註了@Bean註解的方法中注入一個RestTemplateBuilder對象的參數來創建一個RestTemplate:(也就是說使用RestTemplate需要添加一個配置類)
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
然後就可以自動裝配RestTemplate:
@Autowiredprivate
RestTemplate restTemplate;
GET請求
在RestTemplate中,發送一個GET請求,我們可以通過如下兩種方式:
第一種:getForEntity
getForEntity方法的返回值是一個ResponseEntity<T>,ResponseEntity<T>是Spring對HTTP請求響應的封裝,包括了幾個重要的元素,如響應碼、contentType、contentLength、響應消息體等。比如下面一個例子:
@RequestMapping("/gethello")
public String getHello() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class);
String body = responseEntity.getBody();
return body ;
}
關於這段代碼,我說如下幾點:
getForEntity的第一個參數爲我要調用的服務的地址,這裏我調用了服務提供者提供的/hello接口,注意這裏是通過服務名調用而不是服務地址,如果寫成服務地址就沒法實現客戶端負載均衡了。
getForEntity第二個參數String.class表示我希望返回的body類型是String.
有時候我在調用服務提供者提供的接口時,可能需要傳遞參數,有兩種不同的方式,如下:
@RequestMapping("/sayhello")
public String sayHello() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={1}", String.class, "張三");
return responseEntity.getBody();
}
@RequestMapping("/sayhello2")
public String sayHello2() {
Map<String, String> map = new HashMap<>();
map.put("name", "李四");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={name}", String.class, map);
return responseEntity.getBody();
}
一:用一個數字做佔位符,最後是一個可變長度的參數,來一一替換前面的佔位符
二:用name={name}這種形式,最後一個參數是一個map,map的key即爲前邊佔位符的名字,map的value爲參數值
第一個調用地址也可以是一個URI而不是字符串,這個時候我們構建一個URI即可,參數神馬的都包含在URI中了,如下:
@RequestMapping("/sayhello3")
public String sayHello3() {
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/sayhello?name={name}").build().expand("王五").encode();
URI uri = uriComponents.toUri();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
return responseEntity.getBody();
}
當然,服務提供者不僅可以返回String,也可以返回一個自定義類型的對象,比如我的服務提供者中有如下方法:
@RequestMapping(value = "/getbook1", method = RequestMethod.GET)
public Book book1() {
return new Book("三國演義", 90, "羅貫中", "花城出版社");
}
對於該方法我可以在服務消費者中通過如下方式來調用:
@RequestMapping("/book1")
public Book book1() {
ResponseEntity<Book> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/getbook1", Book.class);
return responseEntity.getBody();
}
運行結果如下:
第二種:getForObject
getForObject函數實際上是對getForEntity函數的進一步封裝,如果你只關注返回的消息體的內容,對其他信息都不關注,此時可以使用getForObject,舉一個簡單的例子,如下:
RequestMapping("/book2")
public Book book2() {
Book book = restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
return book;
}
POST請求
在RestTemplate中,POST請求可以通過如下三個方法來發起:
第一種:postForEntity
該方法和get請求中的getForEntity方法類似,如下例子:
@RequestMapping("/book3")
public Book book3() {
Book book = new Book();
book.setName("紅樓夢");
ResponseEntity<Book> responseEntity = restTemplate.postForEntity("http://HELLO-SERVICE/getbook2", book, Book.class);
return responseEntity.getBody();
}
方法的第一參數表示要調用的服務的地址
方法的第二個參數表示上傳的參數
方法的第三個參數表示返回的消息體的數據類型
我這裏創建了一個Book對象,這個Book對象只有name屬性有值,將之傳遞到服務提供者那裏去,服務提供者代碼如下:
@RequestMapping(value = "/getbook2", method = RequestMethod.POST)
public Book book2(@RequestBody Book book) {
System.out.println(book.getName());
book.setPrice(33);
book.setAuthor("曹雪芹");
book.setPublisher("人民文學出版社");
return book;
}
服務提供者接收到服務消費者傳來的參數book,給其他屬性設置上值再返回,調用結果如下:
exchange方法
restTemplate.exchange(
String url,
HttpMethod method,
HttpEntity requestEntity,
Class responseType,
Object uriVariables[]
)
說明:1)url: 請求地址;2)method: 請求類型(如:POST,PUT,DELETE,GET);3)requestEntity: 請求實體,封裝請求頭,請求內容4)responseType: 響應類型,根據服務接口的返回類型決定5)uriVariables: url中參數變量值
post請求自定義header
@RequestMapping("/headerApi")//模擬遠程的restful API
public JSONObject withHeader(@RequestBody JSONObject parm, HttpServletRequest req){
System.out.println("headerApi====="+parm.toJSONString());
Enumeration<String> headers = req.getHeaderNames();
JSONObject result = new JSONObject();
while(headers.hasMoreElements()){
String name = headers.nextElement();
System.out.println("["+name+"]="+req.getHeader(name));
result.put(name, req.getHeader(name));
}
result.put("descp", "this is from header");
return result;
}
@RequestMapping("/header")
public Object postWithHeader(){
//該方法通過restTemplate請求遠程restfulAPI
HttpHeaders headers = new HttpHeaders();
headers.set("auth_token", "asdfgh");
headers.set("Other-Header", "othervalue");
headers.setContentType(MediaType.APPLICATION_JSON);
JSONObject parm = new JSONObject();
parm.put("parm", "1234");
HttpEntity<JSONObject> entity = new HttpEntity<JSONObject>(parm, headers);
HttpEntity<String> response = restTemplate.exchange(
"http://localhost:8080/headerApi", HttpMethod.POST, entity, String.class);//這裏放JSONObject, String 都可以。因爲JSONObject返回的時候其實也就是string
return response.getBody();
}