2017-01-23 by 安静的下雪天 http://www.cnblogs.com/quiet-snowy-day/p/6343347.html

本篇概要

类说明

AsyncRestTemplate 是 Spring中提供异步的客户端HTTP访问的核心类。与RestTemplate类相似,它提供了一些类似的方法,只不过返回类型不是具体的结果,而是ListenableFuture包装类。
 
通过getRestOperations()方法,对外提供了一个同步的RestTemplate对象,并且通过这个RestTemplate对象来共享错误处理和消息转换。
 
注意:默认情况下,AsyncRestTemplate依靠标准JDK工具来创建HTTP链接。通过使用构造函数来接收AsyncClientHttpRequestFactory接口的具体实现类对象,你可以选用不同的HTTP库,例如Apache HttpComponents,Netty,以及OkHttp。
* Spring's central class for asynchronous client-side HTTP access. Exposes similar methods as RestTemplate, but returns ListenableFuture wrappers as opposed to concrete results.
The AsyncRestTemplate exposes a synchronous RestTemplate via the getRestOperations() method and shares its error handler and message converters with that RestTemplate.
Note: by default AsyncRestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents, Netty, and OkHttp by using a constructor accepting an AsyncClientHttpRequestFactory.
 

类图

类图中省略了一些参数类型及重载的方法,在不影响理解的情况下,保证各要素在一幅图中展现。

 
 

简单例子

    private String result = "";

    @Test
public void testAsyncPost() throws Exception {
String posturl = "http://xxxxxx";
String params = "xxxxxx"; MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); HttpEntity<Object> hpEntity = new HttpEntity<Object>(params, headers);
AsyncRestTemplate asyncRt = new AsyncRestTemplate(); ListenableFuture<ResponseEntity<String>> future = asyncRt.postForEntity(posturl, hpEntity, String.class); future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
public void onSuccess(ResponseEntity<String> resp) {
result = resp.getBody();
}
public void onFailure(Throwable t) {
System.out.println(t.getMessage());
}
});
System.out.println(result);
}
 

精辟的内部类

    /**
* Adapts a {@link RequestCallback} to the {@link AsyncRequestCallback} interface.
*/
private static class AsyncRequestCallbackAdapter implements AsyncRequestCallback { private final RequestCallback adaptee; /**
* Create a new {@code AsyncRequestCallbackAdapter} from the given
* {@link RequestCallback}.
* @param requestCallback the callback to base this adapter on
*/
public AsyncRequestCallbackAdapter(RequestCallback requestCallback) {
this.adaptee = requestCallback;
} @Override
public void doWithRequest(final AsyncClientHttpRequest request) throws IOException {
if (this.adaptee != null) {
this.adaptee.doWithRequest(new ClientHttpRequest() {
@Override
public ClientHttpResponse execute() throws IOException {
throw new UnsupportedOperationException("execute not supported");
}
@Override
public OutputStream getBody() throws IOException {
return request.getBody();
}
@Override
public HttpMethod getMethod() {
return request.getMethod();
}
@Override
public URI getURI() {
return request.getURI();
}
@Override
public HttpHeaders getHeaders() {
return request.getHeaders();
}
});
}
}
}

AsyncRequestCallbackAdapter源码

 
我觉得AsyncRestTemplate类巧妙之处就在于复用了RestTemplate类,而最精辟之处就是AsyncRequestCallbackAdapter内部类(名字太长,下文简称Adapter)。从这个内部类的名字就可以知道,此处使用了适配器设计模式。适配器模式的设计意图就是在两个不兼容的接口之间建立起沟通的桥梁。

那么,这里是如何将两个类连接起来的呢?答案关键在于匿名类的使用。

Adapter类中的成员变量adaptee,实际上引用的是RestTemplate中的*RequestCallback内部类对象。
Adapter.doWithRequest方法的参数类型是AsyncClientHttpRequest,而*RequestCallback.doWithRequest方法的参数类型是ClientHttpRequest。
通过创建匿名类对象,重写接口方法,将各方法的返回指向AsyncClientHttpRequest参数对象。
在Adapter.doWithRequest方法中,以刚刚创建的匿名类对象作为参数,直接调用*RequestCallback.doWithRequest方法。
这个匿名类对象就是两个方法之间的桥梁。
 
平时工作中匿名类用的比较少,刚看这段源码的时候真的有点蒙,接口怎么能直接new一个对象了呢?忍不住开始怀疑人生-_-|||
baidu之后明白了,这不正是匿名类嘛~~~只不过它看起来像new了一个接口的对象,但是实际上编译后会自动生成一个实现类。
 
其实,上面代码写成这样↓↓↓就容易理解了。由此可以看出,使用匿名类省略了一个实现类的定义和开销。
    @Override
public void doWithRequest(final AsyncClientHttpRequest request) throws IOException {
if (this.adaptee != null) {
this.adaptee.doWithRequest(new ClientHttpRequestImpl(request));
}
}
private class ClientHttpRequestImpl implements ClientHttpRequest{ private AsyncClientHttpRequest request; public ClientHttpRequestImpl(AsyncClientHttpRequest request){
this.request = request;
}
@Override
public ClientHttpResponse execute() throws IOException {
throw new UnsupportedOperationException("execute not supported");
}
@Override
public HttpMethod getMethod() {
return request.getMethod();
}
@Override
public URI getURI() {
return request.getURI();
}
@Override
public HttpHeaders getHeaders() {
return request.getHeaders();
}
@Override
public OutputStream getBody() throws IOException {
return request.getBody();
}
}

返回顶部

【Spring-web】AsyncRestTemplate源码学习的更多相关文章

  1. spring源码学习(三)--spring循环引用源码学习

    在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...

  2. 捋一捋Spring Web的源码思路

    Servlet前提 Java规定了Servlet Container为每一个web app创建一个Servlet Context:而Servlet Context中又包含了诸多Servlet -- 其 ...

  3. 【目录】Spring 源码学习

    [目录]Spring 源码学习 jwfy 关注 2018.01.31 19:57* 字数 896 阅读 152评论 0喜欢 9 用来记录自己学习spring源码的一些心得和体会以及相关功能的实现原理, ...

  4. spring源码学习——spring整体架构和设计理念

    Spring是在Rod Johnson的<Expert One-On-One J2EE Development and Design >的基础上衍生而来的.主要目的是通过使用基本的java ...

  5. Spring5.0源码学习系列之Spring AOP简述

    前言介绍 附录:Spring源码学习专栏 在前面章节的学习中,我们对Spring框架的IOC实现源码有了一定的了解,接着本文继续学习Springframework一个核心的技术点AOP技术. 在学习S ...

  6. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  7. SpringBoot源码学习1——SpringBoot自动装配源码解析+Spring如何处理配置类的

    系列文章目录和关于我 一丶什么是SpringBoot自动装配 SpringBoot通过SPI的机制,在我们程序员引入一些starter之后,扫描外部引用 jar 包中的META-INF/spring. ...

  8. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  9. spring源码学习之路---IOC初探(二)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...

随机推荐

  1. 在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互

    Android的私钥和信任证书的格式必须是BKS格式的,通过配置本地JDK,让keytool可以生成BKS格式的私钥和信任证书,java本身没有BouncyCastle密库 服务端: Java代码  ...

  2. php dependency innjection

    You’ve probably heard of the acronym SOLID by now, which is an object oriented programming paradigm ...

  3. openstack controller ha测试环境搭建记录(六)——配置keystone

    在所有节点的hosts文件添加:10.0.0.10 myvip 在所有节点安装# yum install -y openstack-keystone python-keystoneclient# yu ...

  4. jquery.validate.js 一个jQuery验证格式控件

    官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery plugin: Validation 使用说明 转载 ...

  5. HTML学习(七)表格

    表格表格由 <table> 标签来定义.每个表格均有若干行(由 <tr> 标签定义),每行被分割为若干单元格(由 <td> 标签定义).字母 td 指表格数据(ta ...

  6. MVC笔记2:mvc+jquery.validate.js 进行前端验证

    1.引用如下js和css 代码 <link href="@Url.Content("~/Content/Site.css")" rel="sty ...

  7. java 环境变量 windows(Java之负基础实战)

    1.已经安装了JDK 添加系统变量 1.1.添加JAVA_HOME jdk路径,例如:C:\Program Files\Java\jdk1.8.0_65 1.2. PATH 添加内容 %JAVA_HO ...

  8. IOS Cell重用机制

    重用机制: -(UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *) ...

  9. HBuilder mui引导页制作

    http://www.bcty365.com/content-146-2582-1.html

  10. Android Studio快捷键汇总