参数:    请求路径, 请求参数, 返回类型, 扩展模板变量
 
参数:    请求参数, 返回类型
 
HttpEntityRequestCallback构造器
HttpEntityRequestCallback是RestTemplate的私有内部类,继承了RestTemplate私有内部类 AcceptHeaderRequestCallback,AcceptHeaderRequestCallback实现了RequestCallback接口,重写了doWithRequest方法
HttpEntity是    HTTP请求或响应实体
 
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
    //调用父类方法
    super.doWithRequest(httpRequest);
    Object requestBody = this.requestEntity.getBody();
    //判断内部类中的HttpEntity是否有参数
    if (requestBody == null) {
        HttpHeaders httpHeaders = httpRequest.getHeaders();
        HttpHeaders requestHeaders = this.requestEntity.getHeaders();
        if (!requestHeaders.isEmpty()) {
            //如果header不为空,将header的值赋给方法接收的参数ClientHttpRequest
            requestHeaders.forEach((key, values) -> {
                httpHeaders.put(key, new LinkedList(values));
            });
        }
        //添加content长度
        if (httpHeaders.getContentLength() < 0L) {
            httpHeaders.setContentLength(0L);
        }
    } else {
        Class<?> requestBodyClass = requestBody.getClass();
        Type requestBodyType = this.requestEntity instanceof RequestEntity ? ((RequestEntity)this.requestEntity).getType() : requestBodyClass;
        HttpHeaders httpHeadersx = httpRequest.getHeaders();
        HttpHeaders requestHeadersx = this.requestEntity.getHeaders();
        MediaType requestContentType = requestHeadersx.getContentType();
        //消息转换器列表
        Iterator var8 = RestTemplate.this.getMessageConverters().iterator();
        while(var8.hasNext()) {
            //策略接口,指定可以从HTTP请求和响应转换的转换器
            HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var8.next();
            if (messageConverter instanceof GenericHttpMessageConverter) {
                //可以将HTTP请求转换为指定泛型类型的目标对象,将指定泛型类型的源对象转换为HTTP响应
                GenericHttpMessageConverter<Object> genericConverter = (GenericHttpMessageConverter)messageConverter;
                //判断  指示此转换器是否可以写入给定的类
                if (genericConverter.canWrite((Type)requestBodyType, requestBodyClass, requestContentType)) {
                    if (!requestHeadersx.isEmpty()) {
                        requestHeadersx.forEach((key, values) -> {
                            httpHeadersx.put(key, new LinkedList(values));
                        });
                    }
                    //打印debug日志
                    this.logBody(requestBody, requestContentType, genericConverter);
                    将给定对象写入给定的输出消息
                    genericConverter.write(requestBody, (Type)requestBodyType, requestContentType, httpRequest);
                    return;
                }
            } else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
                if (!requestHeadersx.isEmpty()) {
                    requestHeadersx.forEach((key, values) -> {
                        httpHeadersx.put(key, new LinkedList(values));
                    });
                }
                this.logBody(requestBody, requestContentType, messageConverter);
                messageConverter.write(requestBody, requestContentType, httpRequest);
                return;
            }
        }
        String message = "No HttpMessageConverter for [" + requestBodyClass.getName() + "]";
        if (requestContentType != null) {
            message = message + " and content type [" + requestContentType + "]";
        }
        throw new RestClientException(message);
    }
}
private void logBody(Object body, @Nullable MediaType mediaType, HttpMessageConverter<?> converter) {
    if (RestTemplate.this.logger.isDebugEnabled()) {
        if (mediaType != null) {
            RestTemplate.this.logger.debug("Writing [" + body + "] as \"" + mediaType + "\"");
        } else {
            String classname = converter.getClass().getName();
            RestTemplate.this.logger.debug("Writing [" + body + "] with " + classname);
        }
    }
}
 
响应提取器,它使用给定的实体转换器 将响应转换为类型T
 
最后的execute方法
@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
    //使用URI变量映射展开给定的URI模板
    URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
    return this.doExecute(expanded, method, requestCallback, responseExtractor);
}
 
参数:url - 要连接的完全扩展的URL, method - 要执行的HTTP方法(GET,POST等), requestCallback- 准备请求的对象(可以null), responseExtractor- 从响应中提取返回值的对象(可以null)
@Nullable
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
    Assert.notNull(url, "URI is required");
    Assert.notNull(method, "HttpMethod is required");
    ClientHttpResponse response = null;
    Object var14;
    try {
        //通过工厂模式创建ClientHttpRequest对象
        ClientHttpRequest request = this.createRequest(url, method);
        if (requestCallback != null) {
            requestCallback.doWithRequest(request);
        }
        //执行请求
        response = request.execute();
        //处理给定的响应,执行适当的日志记录并在ResponseErrorHandler必要时调用
        this.handleResponse(url, method, response);
        //extractData  从给定数据中提取数据ClientHttpResponse并将其返回
        var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;
    } catch (IOException var12) {
        String resource = url.toString();
        String query = url.getRawQuery();
        resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;
        throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
    } finally {
        if (response != null) {
            response.close();
        }
    }
    return var14;
}
 
 

RestTemplate-postForObject源码的更多相关文章

  1. restTemplate源码解析(五)处理ClientHttpResponse响应对象

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们执行了ClientHttpRequest与服务端进行交互.并返回了一个 ...

  2. RestTemplate post请求使用map传参 Controller 接收不到值的解决方案 postForObject方法源码解析.md

    结论 post方法中如果使用map传参,需要使用MultiValueMap来传递 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 ...

  3. RestTemplate post请求 Controller 接收不到值的解决方案 postForObject方法源码解析

    springboot 整合 RestTemplate 与 使用方法 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 这个参数是请求 ...

  4. 【Spring-web】RestTemplate源码学习

     2016-12-22   by 安静的下雪天  http://www.cnblogs.com/quiet-snowy-day/p/6210288.html 前言 在Web开发工作中,有一部分开发任务 ...

  5. restTemplate源码解析(目录)

    restTemplate是spring实现的,基于restful风格的http请求模板.使用restTemplate可以简化请求操作的复杂性,同时规范了代码风格.本系列文章,将根据以下目录顺序,从源码 ...

  6. restTemplate源码详解深入剖析底层实现思路

    一 准备工作 1 启动一个项目,发布一个restful的get请求,端口设置为8090. @RestController @RequestMapping("/youku1327") ...

  7. Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法

    如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...

  8. RestTemplate Hashmap变为LinkedHashMap源码解读

    使用restTemplate远程调用服务,正常应该接收List<HashMap>数据,但实际却是List<LikedHashMap>经过不断地debug,终于找到了数据被转换成 ...

  9. restTemplate.postForObject上传文件中文乱码(???.xls)

    一.问题描述 项目中, 使用restTemplate上传文件时, 文件名中文乱码, 一串问号, 源文件名为: 测试中文乱码哦哦哦.zip, 通过restTemplate.postForObject调用 ...

  10. spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign

    基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...

随机推荐

  1. In-App Purchase Programming Guide----(六) ----Working with Subscriptions

    Working with Subscriptions Apps that use subscriptions have some additional behaviors and considerat ...

  2. 3.9-3.10 分布式协作服务框架Zookeeper

    一.zookeeper概述 一个开源的分布式的,为分布式应用提供协调服务的Apache项目. 提供一个简单的原语集合,以便于分布式应用可以在它之上构建更高层次的同步服务. 设计非常易于编程,它使用的是 ...

  3. gitbucket

    github固然强大,但不怎么适合企业级的开发版本管理,原因相信大家都明白,首先在github上上传和拉取代码速度是比较慢的,再者,在Github上创建一个私有仓库是收费的,那么gitbucket是一 ...

  4. 洛谷 - P2598 - 狼和羊的故事 - 最大流

    https://www.luogu.org/problemnew/show/P2598 第一次写这种修篱笆的题目,上次好像晓阳dalao写了一个堵人的.好像还有能改变土地属性的. #include&l ...

  5. WPF 加载 WINFORM控件 异常: 调度程序进程已挂起,但消息仍在处理中

    在加载TradeAtServer的统计中的 单个合约盈亏情况 异常:,调度程序进程已挂起,但消息仍在处理中 发现可能是属性设置引发的问题 比如DateTimePikcer.Value+= set, g ...

  6. IT兄弟连 JavaWeb教程 经典面试题3

    1.简述什么是重定向? 服务器向浏览器发送—个302状态码及一个Location消息头(该消息头的值是一个地址,称之为重定向地址),浏览器收到后会立即向重定向地址发出请求. 2.简述什么是转发?怎么实 ...

  7. Luogu P1156 垃圾陷阱 【dp】By cellur925

    题目传送门 这题...看上去浓浓的背包气息...但是并不好设计状态啊emmm. 我们考虑可能成为状态的量:高度.血量.时间.物品.看数据范围也猜到应该大概是个二维dp了w. 正确的状态设计之一:设$f ...

  8. AForge.NET .NET2.0程序集无法在.net 4.0 中运行的解决方案

    如有雷同,不胜荣欣,若转载,请注明 最近在项目上一直使用.net4.0 framework,突然发现一个AForge.net中使用ffmepeg下的一个dll时,提示只能在2.0下运行,在众多MSDN ...

  9. mui.init()方法中可以有子页面和预加载两项内容,它们是否都在页面加载完成时创建其对应的webview对象?

    subpages和preloadPages区别是什么? mui.init({ subpages: [{ url: 'subject.html', //子页面HTML地址,支持本地地址和网络地址 id: ...

  10. js 合并2个结构

    var conditions = getJsonObj("conditionArea"); var plogId = { ProgId: getProgId() }; $.exte ...