restTemplate源碼解析(一)構造restTemplate的Bean實例


所有文章

https://www.cnblogs.com/lay2017/p/11740855.html

 

正文

構造一個restTemplate的Bean實例很容易,只需這樣配置

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

但我們希望更多得了解一個這個構造過程做了哪些事情。為此,我們需要去打開restTemplate這個黑盒子。

 

restTemplate設計

先試着從restTemplate得類圖上獲得一些靈感,看看spring的作者是一個什么樣的設計思路吧。

我們看到,簡單的幾個類和接口展示了標准的抽象設計。

HttpAccessor是一個抽象類,它抽象的是一個http訪問器的概念。這說明,RestTemplate具備http方式請求響應的處理能力。再看RestOperations,它是一個接口,抽象的是restful風格的操作方法,這意味着RestTemplate的操作風格將是Restful的。

http訪問器和restful風格操作做了一個分離。restTemplate則是聚合了兩者,既有http訪問器的基礎能力,又在這個基礎之上構建了restful風格。設計者把Restful操作作為接口,其實從規范角度上,我們應該面向RestOperations接口使用它。但大多數人似乎都直接使用RestTemplate,我們上面的代碼示例也無意識地直接面向了RestTemplate這個實現類。

 

restTemplate實例構造過程

接下來,我們再看看new一個RestTemplate對象做了哪些事情。

進入RestTemplate類的構造方法

private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();

private UriTemplateHandler uriTemplateHandler;

public RestTemplate() {
    // 添加HttpMessageConverterjie
    this.messageConverters.add(new ByteArrayHttpMessageConverter());
    this.messageConverters.add(new StringHttpMessageConverter());
    this.messageConverters.add(new ResourceHttpMessageConverter(false));
    try {
        this.messageConverters.add(new SourceHttpMessageConverter<>());
    }
    catch (Error err) {
        // Ignore when no TransformerFactory implementation is available
    }
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());

    if (romePresent) {
        this.messageConverters.add(new AtomFeedHttpMessageConverter());
        this.messageConverters.add(new RssChannelHttpMessageConverter());
    }

    if (jackson2XmlPresent) {
        this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
    }
    else if (jaxb2Present) {
        this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    }

    if (jackson2Present) {
        this.messageConverters.add(new MappingJackson2HttpMessageConverter());
    }
    else if (gsonPresent) {
        this.messageConverters.add(new GsonHttpMessageConverter());
    }
    else if (jsonbPresent) {
        this.messageConverters.add(new JsonbHttpMessageConverter());
    }

    if (jackson2SmilePresent) {
        this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
    }
    if (jackson2CborPresent) {
        this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
    }
    // uri模板處理器
    this.uriTemplateHandler = initUriTemplateHandler();
}

構造方法有點長,但只做了兩件事

1)添加HttpMessageConverter的實現類,熟悉springmvc的話估計知道HttpMessageConverter。顧名思義,它就是用來轉換http請求響應過程中的消息數據的。

2)初始化一個UriTemplateHandler

 

我們跟進initUriTemplateHandler方法,看看怎么初始化一個uri模板處理器的

private static DefaultUriBuilderFactory initUriTemplateHandler() {
    DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
    uriFactory.setEncodingMode(EncodingMode.URI_COMPONENT);  // for backwards compatibility..
    return uriFactory;
}

這里只是簡單地構造了實例,並直接返回。由此可見,DefaultUriBuilderFactory應該直接或者間接實現了UriTemplateHandler

我們看看DefaultUriBuilderFactory的類圖

與我們猜想的一樣,DefaultUriBuilderFactory間接實現了UriTemplateHandler

 

RestTemplate的構造方法中就做了這兩件事,我們再看看HttpAccessor

public abstract class HttpAccessor {
    // ...

    private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

    // ...
}

默認創建了一個ClientHttpRequestFactory的實例,ClientHttpRequestFactory這個接口是用來創建客戶端的request請求對象的,我們並沒有去自定義設置它默認采用SimpleClientHttpRequestFactory這個實現類。

ClientHttpRequestFactory作為工廠模式,將會生產ClientHttpRequest。ClientHttpRequest抽象了Http請求操作,執行ClientHttpRequest將會發送請求與服務端交互。

 

總結

到這里,RestTemplate的實例構造過程就結束了。其實它的原理就是封裝了http請求操作而已。

我們再大體過一下RestTemplate的構造過程

1)在RestTemplate構造方法中添加了多個HttpMessageConverter后續用於http請求響應的數據轉換

2)在RestTemplate構造方法中初始化了一個Uri模板的處理器,后續用於處理uri相關的東西

3)HttpAccessor默認創建了一個ClientHttpRequestFactory的成員實例,后續用於創建請求對象。

不過,似乎最有學習價值的還是一開始的restTemplate的設計圖。能夠理解抽象類與接口的標准設計理念,興許對面向對象分析與設計大有裨益。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM