RestTemplate 初解

在 Java 社區中,HTTP Client 主要有 JDK 的 HttpURLConnection、Apache的Http Client、Square 公司開源的 OkHttp。

1.RestTemplate簡介和使用

除了這幾個純粹的 HTTP Client 類庫以外, Spring 的 RestTemplate針對 Web Service 場景,尤其是 RESTful Web Service。它基於前面提到的 HTTP Client ,並在其基礎上提供了消息轉換、參數映射等對於 Web Service 來說十分必要的功能。

詳細查看 RestTemplate API


2.RestTemplate中http報文轉換處理

2.1 HttpMessageConverter

默認情況下RestTemplate自動幫我們註冊了一組HttpMessageConverter用來處理一些不同的contentType的請求。


    public RestTemplate() {
        this.messageConverters = new ArrayList();
        this.errorHandler = new DefaultResponseErrorHandler();
        this.uriTemplateHandler = new DefaultUriBuilderFactory();
        this.headersExtractor = new RestTemplate.HeadersExtractor();
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
        this.messageConverters.add(new ResourceHttpMessageConverter(false));
        this.messageConverters.add(new SourceHttpMessageConverter());
        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());
        }

    }

其中常用的Converter:

StringHttpMessageConverter處理text/plain;
AllEncompassingFormHttpMessageConverter處理application/x-www-form-urlencoded, multipart/form-data
MappingJackson2HttpMessageConverter處理application/json;
MappingJackson2XmlHttpMessageConverter處理application/xml。

2.2 RestTemplate請求中的報文轉換

當我們發送請求時,RestTemplate 從這組HttpMessageConverter中循環取出HttpMessageConverter,並通過canWrite((Type)requestBodyType, requestBodyClass, requestContentType)方法判斷當前的HttpMessageConverter是否合適。

requestBodyType和requestBodyClass是body數據類型。
requestContentType是我們設置的contentType。

    public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
        //當前的HttpMessageConverter是否支持轉換body數據類型
        //&設置的contentType是否支持轉換(這裏其實只是檢驗contentType是否在RestTemplate支持的MediaType中)
        return this.supports(clazz) && this.canWrite(mediaType);
    }


    protected boolean canWrite(@Nullable MediaType mediaType) {
        if (mediaType != null && !MediaType.ALL.equals(mediaType)) {
            Iterator var2 = this.getSupportedMediaTypes().iterator();

            MediaType supportedMediaType;
            do {
                if (!var2.hasNext()) {
                    return false;
                }

                supportedMediaType = (MediaType)var2.next();
            } while(!supportedMediaType.isCompatibleWith(mediaType));

            return true;
        } else {
            return true;
        }
    }

通過上面的代碼和裏面的增加的註釋,我們可以確定RestTemplate是根據我們傳入body的類型來選擇HttpMessageConverter,設置的contentType只要RestTemplate支持即可,並不會左右HttpMessageConverter的選擇。但是contentType會被加到http請求頭中。

2.3 一個陷阱

StringHttpMessageConverter默認使用ISO-8859-1編碼,中文會出現亂碼,可以統一改爲utf-8。修改的方法網上一堆,這裏就不寫了。當然你也可以選擇不使用String

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