所有文章
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的設計圖。能夠理解抽象類與接口的標准設計理念,興許對面向對象分析與設計大有裨益。
