1.快速入門

一、簡介

RestTemplate是spring提供的http客戶端模版,類似JdbcTemplate,它是線程安全的,支持切換不同的http客戶端,目前支持HttpClient-4.3, OKHttp3, 基於netty4實現的http客戶端和基於java的URLConnection實現的http客戶端。

二、引入

RestTemplate默認已經包含在spring-web中,其默認採用java的URLConnection實現的http客戶端,如果想更換不同的http客戶端需要在pom增加需要的依賴,比如依賴okhttp

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.8.1</version>
</dependency>

三、構造實例

  1. 使用默認構造

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
  2. 使用okhttp

    @Bean
    public RestTemplate restTemplate() {
        OkHttp3ClientHttpRequestFactory f  =new OkHttp3ClientHttpRequestFactory();
        f.setConnectTimeout(2000);
        f.setReadTimeout(1000);
        f.setWriteTimeout(1000);
        return new RestTemplate(f);
    }
    

四、參數相關

  1. GET,無參或參數直接寫死到url中,返回string

    String result = restTemplate.getForObject("http://vstat.v.blog.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", String.class);
    
  2. GET,參數較多,追加到url中

    String url = "http://vstat.v.blog.aa.com/dostat.do";
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
        .queryParam("method", "getVideoPlayCount")
        .queryParam("v", "85152140|85162109")
        .queryParam("rt", "json");
    String rst = restTemplate.getForObject(builder.buildAndExpand().toUri(), String.class);
    
  3. GET,佔位符替換

    String url = "http://vstat.v.a.aa.com/dostat.do?method={method}&ids={ids}&rt={rt}&test={test}";
    String rst = restTemplate.getForObject(url, String.class, "getVideoPlayCount", "85152140|85162109;", "json", "測試");
    

    注意:這裏的傳的參數會進行編碼操作,結果會是如下url:

    http://vstat.v.a.aa.com/dostat.do?method=getVideoPlayCount&ids=85152140%7C85162109%3B&rt=json&test=%E6%B5%8B%E8%AF%95

  4. GET,佔位符替換(與3一樣,只不過參數放到map中)

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("method", "getVideoPlayCount");
    map.put("ids", "85152140|85162109;");
    map.put("rt", "json");
    map.put("test", "測試");
    String url = "http://vstat.v.aa.com/dostat.do?method={method}&ids={ids}&rt={rt}&test={test}";
    String rst = restTemplate.getForObject(url, String.class, map);
    
  5. GET,佔位符替換加參數追加:

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("method", "getVideoPlayCount");
    String url = "http://vstat.aa.com/dostat.do?method={method}";
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
        .queryParam("v", "85152140|85162109")
        .queryParam("rt", "json");
    String rst = restTemplate.getForObject(builder.buildAndExpand(map).toUri(), String.class);
    
  6. POST與GET類似,但是涉及到POST傳參,如下:

    //用於發送post請求的參數
    Map<String, String> postMap = new HashMap<String, String>();
    postMap.put("a", "b");
    String url = "http://{domain}/dostat.do";
    //用於替換路徑中的參數
    Map<String, String> map = new HashMap<String, String>();
    map.put("domain", "vstat.aa.com");
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
    HttpEntity<Map<String, String>> httpEntity = new HttpEntity<Map<String, String>>(postMap);
    String rst = restTemplate.postForObject(builder.buildAndExpand(map).toUri(), httpEntity, String.class);
    

五、返回值相關

  1. 返回String類型

    上面的例子都是返回String

  2. 返回對象

    CountEntity countEntity = restTemplate.getForObject("http://vstat.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", CountEntity.class);
    

    默認,RestTemplate已經具備jackson來進行反序列化json。注意:如果響應中沒有設置application/json的header,那麼會報出如下錯誤:no suitable HttpMessageConverter found for response type此時需要返回String類型,然後使用外部的json工具解析

  3. 只返回http響應頭:

    ResponseEntity<Void> rst = restTemplate.getForEntity("http://vstat.v.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", Void.class);
    

六、異常處理

  1. http狀態碼

    默認情況下,響應頭的狀態碼爲1xx或2xx或3xx都認爲響應正常,4xx的會拋出HttpClientErrorException異常,5xx的會拋出HttpServerErrorException異常。

    可以繼承org.springframework.web.client.DefaultResponseErrorHandler進行異常處理,默認的處理如下:

    public void handleError(ClientHttpResponse response) throws IOException {
        HttpStatus statusCode = getHttpStatusCode(response);
        switch (statusCode.series()) {
            case CLIENT_ERROR:
                throw new HttpClientErrorException(statusCode, response.getStatusText(),
                        response.getHeaders(), getResponseBody(response), getCharset(response));
            case SERVER_ERROR:
                throw new HttpServerErrorException(statusCode, response.getStatusText(),
                        response.getHeaders(), getResponseBody(response), getCharset(response));
            default:
                throw new RestClientException("Unknown status code [" + statusCode + "]");
        }
    }
    

    並設置restTemplate.setErrorHandler();

  2. 超時等其他異常

鏈接超時或者讀取超時都會拋出ResourceAccessException,一般情況下,需要try…catch做處理,但是如果採用hystrix,千萬不要捕獲異常,因爲hystrix會捕獲異常進行降級。

七、一些配置

  1. http鏈接超時和讀寫超時:需要根據不同的httpclient實現來進行具體配置,一般都在ClientHttpRequestFactory的具體子類中配置,例如okhttp:

    OkHttp3ClientHttpRequestFactory f  =new OkHttp3ClientHttpRequestFactory();
    f.setConnectTimeout(2000);
    f.setReadTimeout(1000);
    
  2. 配置默認參數:如果某些參數確定是每次請求都攜帶且不變的,可以在初始化的時候就設置進去,例如:

    RestTemplate restTemplate = new RestTemplate();
    Map defaultUriVariables = new HashMap();
    defaultUriVariables.put("host", "a.aa.com");
    restTemplate.setDefaultUriVariables(defaultUriVariables);
    

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