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. [转]Axis2创建WebService实例

    以下文章来自http://clq9761.iteye.com/blog/976029,作者clq9761 一.Axis2的下载和安装 1.可从http://ws.apache.org/axis2/ 下 ...

  2. JAV基础语法之---数据类型转换

    数制转换": 1.string 转 byte[] String str = "Hello";byte[] srtbyte = str.getBytes(); 2.byte ...

  3. hibernate---一对一单向外键关联--annotation (重要!!!)

    1. 生成wife.java: package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persisten ...

  4. Linux系统的/proc目录

    1. /proc目录 Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机 制.proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它 ...

  5. ASP.NET AJAX 创建类

    <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans ...

  6. 6种炫酷的CSS3按钮边框动画特效

    6种炫酷的CSS3按钮边框动画特效Button border animate 用鼠标滑过下面的按钮看看效果! Draw Draw Meet Center Spin Spin Circle Spin T ...

  7. CodeForces 625A Guest From the Past

    贪心水题 #include <stdio.h> #include <algorithm> #include <string.h> #include <queu ...

  8. 关于ios 推送功能的终极解决

    刚刚做了一个使用推送功能的应用 遇到了一些问题整的很郁闷 搞了两天总算是弄明白了 特此分享给大家 本帖 主要是针对产品发布版本的一些问题 综合了网上一些资料根据自己实践写的 不过测试也可以看看 首先要 ...

  9. UIAlertView使用全解

    举例: UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Default Alert View"messa ...

  10. Linux cronolog

    1. 关于本文    本文将以cronolog 1.6.2.apache 2.2.6为例,以CentOS 5为平台,讲述cronolog的安装和设置. 2. 关于cronolog     cronol ...