RestTemplate 初解

在 Java 社区中,HTTP Client 主要有 JDK 的 HttpURLConnection、Apache Commons HttpClient(Apache HttpClient 3.x)、Apache HttpComponents Client(Apache HttpClient 4.x)、Square 公司开源的 OkHttp。


1.RestTemplate简介

除了这几个纯粹的 HTTP Client 类库以外, Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。

RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如Apache HttpComponents、或OkHttp等其它HTTP library。并在其基础上提供了消息转换、参数映射等对于 Web Service 来说十分必要的功能。

RestTemplate包含以下几个部分:

  • HttpMessageConverter 对象转换器
  • ClientHttpRequestFactory 默认是JDK的HttpURLConnection
  • ResponseErrorHandler 异常处理
  • ClientHttpRequestInterceptor 请求拦截器

用一张图可以很直观的理解:


restemplate.png

2.RestTemplate用法

restem.png

详细查看
RestTemplate API
SpringBoot系列 - 使用RestTemplate


3.RestTemplate中http报文转换处理

3.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。

3.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请求头中。

3.3 一个陷阱

StringHttpMessageConverter默认使用ISO-8859-1编码,中文会出现乱码,可以统一改为utf-8。修改的方法网上一堆,这里就不写了。当然你也可以选择不使用String


参考

RestTemplate 深度解析

你可能感兴趣的:(RestTemplate 初解)