美文网首页
RestTemplate 初解

RestTemplate 初解

作者: 卓三阳 | 来源:发表于2020-03-01 00:44 被阅读0次

    在 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 初解

          本文链接:https://www.haomeiwen.com/subject/ulmphhtx.html