Spring RestTemplate的使用詳解

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();

    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章