Spring框架之spring-web http源码完全解析

时间:2024-10-22 12:05:38

Spring框架之spring-web http源码完全解析

Spring-web是Spring webMVC的基础,由http、remoting、web三部分组成。

http:封装了http协议中的client/server端的request请求/response响应,编解码,一些格式的转换(如cbor、Rss、json、xml)。

remoting:远程调用,包括caucho、httpinvoker、jaxws。caucho公司提出的基于HTTP实现的两种远程服务Burlap和hessian。HttpInvoker是spring 框架中基于 HTTP的一个远程调用模型,只能用于Spring框架。jaxws是Sun推出的web services协议栈。

web:包含了和web相关的accept、bind、client、context、cors、filter、jsf、method、multipart、server、util。

Spring-web是Spring webMVC的基础,HTTP用于Web浏览器和Web服务器之间的双工通信,所以Spring-web http模块又是Spring-web的基础,它包含五个模块:

1、 http 封装的基础,如httpHeader、HttpEntity 、HttpMessage 、MediaType 、HttpMethod 、httpStatus、HttpCookie等;

2、client端的request请求(发送出去的)及response响应(接收到的);

3、 server端的request请求(接收到的)及response响应(发送出去的);

4、格式的转换,如json,rss,xml等。

5、 编/解码器。

本文基于version为5.2.4.BUILD-SNAPSHOT的Spring源码版本进行分析,主要从HTTP基础及Spring-web http五个子模块共六部分进行分析。

一、HTTP基础

(1)HTTP协议:HTTP(Hypertext Transfer Protocol,超文本传输协议)是在万维网上进行通信时所使用的协议方案,基于TCP/IP的应用层协议。HTTP有很多应用,最著名的就是用于Web浏览器和Web服务器之间的双工通信。客户端向服务器发送HTTP请求,服务器在HTTP响应中回送所请求的数据。

(2)MIME类型:因特网上有数千中不同的数据类型,HTTP给每种要通过Web传输的对象都打上MIME类型的数据格式标签。MIME类型是一种文本标记,表示一种主要的对象类型和一个特定的子类型,中间由一条斜杠分隔。如text/html标记HTML 格式的文本文档;由text/plain标记普通的ASCII 文本文档;image/jpeg标记JPEG 格式的图片。

(3)URL:统一资源定位符。每个服务器资源都有一个名字,在世界范围内唯一的标识并定位信息资源。

(4)HTTP方法:每条HTTP请求报文都包含一个方法,这个方法告诉服务器要执行什么动作,比如获取一个页面、运行一个网关程序或者删除一个文件。五种常见的HTTP方法:

1、GET 从服务器向客户端发送命名资源;

2、PUT 将来自客户端的数据存储到一个命名的服务器资源中去;

3、DELETE 从服务器中删除命名资源;

4、POST 将客户端数据发送到一个服务器网关应用程序;

5、HEAD 仅发送命名资源响应中的HTTP 首部。

(5)状态码(HTTP Status Code):每条HTTP响应报文返回时都会携带一个状态码,是一个三位数字的代码,告知客户端请求是否成功,或者是否需要采取其他动作。

1xx消息:这一类型的状态码,代表请求已被接受,需要继续处理。

2xx成功:这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。

3xx重定向:这类状态码代表需要客户端采取进一步的操作才能完成请求。

4xx客户端错误:这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。

5xx服务器错误:表示服务器无法完成明显有效的请求。

(6)HTTP报文: HTTP报文是由一行行的简单字符串组成,都是纯文本,不是二进制代码,可以方便进行读写。分为HTTP请求和响应报文,无其他类型的HTTP报文,请求和响应报文格式很相似,包括起始行、首部字段、主体3个部分。

1、起始行:报文的第一行就是起始行,在请求报文中用来说明要做些什么,在响应报文中说明出现了什么情况。

2、首部字段:起始行后面有零个或多个首部字段。每个首部字段都包含一个名字和一个值,为了便于解析,两者之间用冒号来分隔。首部以一个空行结束。添加一个首部字段和添加新行一样简单。

3、主体:空行之后就是可选的报文主体了,其中包含了所有类型的数据。请求主体中包括了要发送给Web 服务器的数据;响应主体中装载了要返回给客户端的数据。起始行和首部都是文本形式且都是结构化的,而主体则不同,主体中可以包含任意的二进制数据,比如图片、视频、音轨、软件程序,文本等。

(7)请求报文(request message):从客户端发往服务器的HTTP报文。

请求报文示例:

GET/sample.Jsp HTTP/1.1

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)

Accept-Encoding:gzip,deflate

username=jinqiao&password=1234

1、起始行:请求报文的起始行又叫请求行,请求服务器对资源做一些操作,包含了一个方法和一个请求的URL。这个方法描述了服务器应该执行的操作,请求URL描述了要对哪个资源执行这个方法。请求行中还包含HTTP 的版本,用来告知服务器,客户端使用的是哪种HTTP。上例中“GET”代表请求方法,“/sample.jsp”表示URI,“HTTP/1.1代表协议和协议的版本。

2、请求头:跟在起始行后面的就是零个、一个或多个HTTP 首部字段。包含客户端的环境及请求正文相关信息。

3、请求体:首部字段和主体之间有一个空行,表示首部字段结束,接下来是主体。上例请求正文中包含客户提交的查询字符串信息.

(8)响应报文(response message):从服务器发往客户端的报文。

响应报文示例:

HTTP/1.0 200 OK

Date: Sun, o1 Oct 2000 23:25:17 GMT

Server: Apache/1.3.11 BSafe-SSL/1.38 (Unix)

Last-modified: Tue, 04 Jul 2000 09:46:21 GMT

Content-length: 403

Content-type: text/html

Hi! I’m a message!

1、起始行:响应报文的起始行又称响应行,包含了响应报文使用的HTTP 版本、数字状态码,以及描述操作状态的文本形式的原因短语。上例中:HTTP 版本为HTTP/1.0,状态码为200(表示成功),原因短语为OK,表示文档已经被成功返回了。

2、响应头:跟在起始行后面的就是零个、一个或多个HTTP 首部字段。

3、响应体:第三部分是可选的实体主体部分。实体的主体是HTTP 报文的负荷,就是HTTP 要传输的内容。可以承载多种类型的数字数据,如图片、视频、HTML 文档、软件应用程序、信用卡事务、电子邮件等。

(9)浏览器通过HTTP请求服务器HTML 资源步骤:

1、 浏览器从URL 中解析出服务器的主机名;

2、浏览器将服务器的主机名转换成服务器的IP 地址;

3、浏览器将端口号(如果有的话)从URL 中解析出来;

4、浏览器建立一条与Web 服务器的TCP 连接;

5、 浏览器向服务器发送一条HTTP 请求报文;

6、 服务器向浏览器回送一条HTTP 响应报文;

7、关闭连接,浏览器显示文档。

二、http封装的基础

(1)HttpHeaders:表示HTTP报文首部,首部内容为客户端和服务器分别处理请求和响应提供所需要的信息。HTTP首部字段是由首部字段名和字段值构成的,中间用冒号分隔(首部字段名: 字段值)。该类同时也为首部字段提供了get/set方法。HTTP 首部字段根据实际用途被分为以下 4 种类型:

1、通用首部字段(General Header Fields):请求报文和响应报文两方都会使用的首部。

2、请求首部字段(Request Header Fields):从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。

3、响应首部字段(Response Header Fields):从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。

4、实体首部字段(Entity Header Fields):针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。

(2)ReadOnlyHttpHeaders:只读类型的HTTP报文首部。继承自HttpHeaders,只能读取,不能写入。

(3)HttpEntity:表示HTTP request或者response实体,由header首部和body主体两部分组成。

(4)RequestEntity:继承自HttpEntity,Request请求实体,在HttpEntity基础上增加了两个属性:HttpMethod类和URI类。HttpMethod枚举了HTTP请求报文的几种方法:GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS/TRACE。URI(java.net.URI)表示统一资源标识符(URI)引用。HttpEntity主要被RestTemplate使用(package org.springframework.web.client,RestTemplate 对 http 的封装类似 JdbcTemplate 对 jdbc 的封装,能够以 rest 风格的方式,以 GET/POST/PUT/DELETE/HEAD/ OPTIONS 等不同的方式向服务器发起HTTP 请求)。

(5)ResponseEntity:继承自HttpEntity,Response响应实体,在HttpEntity基础上增加了一个属性HttpStatus。HttpStatus枚举了HTTP的状态码。1xx消息、2xx成功、3xx重定向、4xx客户端错误、5xx服务器错误,每条HTTP响应报文返回时都会携带一个状态码,告知客户端请求是否成功,或者是否需要采取其他动作。同样,该类主要被RestTemplate使用。

(6)HttpMessage:HTTP request请求报文和response响应报文的父接口。提供了一个方法getHeaders(),获得该报文的首部HttpHeaders。

(7)HttpRequest(extends HttpMessage):表示一个HTTP request请求报文。在父类基础上新增了两个函数:getMethod()获取报文的HttpMethod,描述了服务器应该执行的操作方法;getURI()获取该报文的URL,描述了要对哪个资源执行上述方法。

(8)HttpInputMessage(extends HttpMessage):表示一条接收到的HTTP报文,从服务器端来看就是接收到request报文,从客户端来看就是接收到response报文。在父接口HttpMessage定义的函数getHeaders()基础上新增了一个函数getBody(),获得报文的主体,返回类型是可读的字节输入流InputStream(java.io.InputStream)。

(9)HttpOutputMessage(extends HttpMessage):表示一条发送出去的HTTP报文,从服务器端来看就是发送出去的response报文,从客户端来看就是发送出去的request报文。在父接口HttpMessage定义的函数getHeaders()基础上新增了一个函数getBody(),获得报文的主体,返回类型是可写的字节输入流OutputStream(java.io.OutputStream)。

(10)StreamingHttpOutputMessage(extends HttpOutputMessage):继承自HttpOutputMessage,该报文允许设置一个streaming流类型的报文主体。相应的,这种报文类型也就不支持getBody()函数读取报文主体了。

(11)ReactiveHttpInputMessage(extends HttpMessage):一个响应式的HTTP input报文,会将这个input报文当做Publisher发布者暴露。这个接口主要会被服务器端接收到的request请求报文类或者客户端接收到的response响应报文类实现。reactive programming(响应式编程)是相对于imperative programming(命令式编程)而言的,一种异步编程风格,它关注数据流和变化的传播。

(12)ReactiveHttpOutputMessage(extends HttpMessage):一个响应式的HTTP output报文,会将这个output报文当做Publisher发送出去。这个接口主要会被服务器端发送的response响应报文类或者客户端发送的request请求报文类实现。

(13)ZeroCopyHttpOutputMessage(extends ReactiveHttpOutputMessage):在类ReactiveHttpOutputMessage继承上增加了对零拷贝的文件传输的支持。零拷贝技术(Zero-Copy)是指将数据直接从磁盘文件复制到网卡设备中,而不需要经由应用程序之手 。零拷贝大大提高了应用程序的性能,减少了内核和用户模式之间的上下文切换 。

(14)MediaType:继承自MimeType(org.springframework.util.MimeType),在父类MimeType基础上增加了对在HTTP规范中定义的一些高质量的参数提供的方法支持。媒体类型决定浏览器将以何种形式对资源进行解析。常见的媒体格式类型(<type>/<subtype>)如下:

text/html: HTML格式

text/plain:纯文本格式

image/gif:gif图片格式

application/pdf:pdf格式

application/octet-stream:二进制流数据

...

Content-Type实体头部用于指示资源的MIME类型media type。如:

Content-Type: text/html; charset=utf-8

Content-Type: multipart/form-data; boundary=something

(15)MediaTypeEditor:继承自PropertyEditorSupport(java.beans.PropertyEditorSupport),自动的把字符串类型的说明(如"text/html")转换成MediaType对象。

(16)MediaTypeFactory:该工厂类用来从资源句柄或者文件名中解析出MediaType对象。

(17)InvalidMediaTypeException:执行解析函数parseMediaType(String)时遇到一个非法的media type抛出的异常。

(18)HttpMethod:枚举了HTTP request 几种方法:GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS、TRACE。该枚举类型主要被ClientHttpRequest(package  org.springframework.http)和RestTemplate(package org.springframework.web.client)使用。

枚举是Java1.5引入的新特性,通过关键字enum来定义枚举类。枚举类是一种特殊类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口,但枚举类不能继承其他类。

(19)HttpStatus:枚举了HTTP的状态码。通过提供的series()函数可以得到该状态码属于哪一大类:INFORMATIONAL(1xx消息)、SUCCESSFUL(2xx成功)、REDIRECTION(3xx重定向)、CLIENT_ERROR(4xx客户端错误)、SERVER_ERROR(5xx服务器错误)。

(20)HttpRange:使用Range首部来表示一个HTTP(byte) range。HTTP通过首部Range属性允许客户端只请求文档的一部分,或者说某个范围。

GET /bigfile.html HTTP/1.1

Host: www.joes-hardware.com

Range: bytes=4000-

User-Agent: Mozilla/4.61 [en] (WinNT; I)

...

在上例中,客户端请求的是文档开头4000 字节之后的部分(不必给出结尾字节数,因为请求方可能不知道文档的大小)。在客户端收到了开头的4000 字节之后就失败的情况下,可以使用这种形式的范围请求。

还可以用Range 首部来请求多个范围(这些范围可以按任意顺序给出,也可以相互重叠)。例如,假设客户端同时连接到多个服务器,为了加速下载文档而从不同的服务器下载同一个文档的不同部分。对于客户端在一个请求内请求多个不同范围的情况,返回的响应也是单个实体,它有一个多部分主体及Content-Type: multipart/byteranges 首部。Range 首部在流行的点对点(Peer-to-Peer,P2P)文件共享客户端软件中得到广泛应用,它们从不同的对等实体同时下载多媒体文件的不同部分。

(21)CacheControl:控制缓存的开关,用于标识请求或响应中是否开启了缓存,使用了哪种缓存方式。

1、在请求中使用Cache-Control时,可选的值有:

no-cache:告知(代理)服务器不直接使用缓存,要求向原服务器发起请求。

no-store:所有内容都不会被保存到缓存或Internet临时文件中。

max-age=delta-seconds:告知服务器客户端希望接收一个存在时间不大于delta-seconds秒的资源。

max-stale[=delat-seconds] :告知(代理)服务器客户端愿意接收一个超过缓存时间的资源,若有定义delta-seconds则为delta-seconds秒,若没有则为任意超出时间。

min-fresh=delta-seconds:告知(代理)服务器客户端希望接收一个在小于delta-seconds秒内被更新过的资源。

no-transform:告知(代理)服务器客户端希望获取试题数据没有被转换(比如压缩)过的资源。

only-if-cached:告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向服务器发去请求。

cache-extension:自定义拓展值,若服务器不识别该值将被忽略掉。

2、在响应中使用Cache-Control时,可选的值有:

public:表明任何情况下都得缓存该资源(即使是需要HTTP认证的资源)。

Private[=”field-name”] :表明返回报文中全部或部分(若指定了field-name则为field-name的字段数据)仅开放给某些用户(服务器指定的share-user,如代理服务器)做缓存使用,其他用户则不能缓存这些数据。

no-cache:不直接使用缓存,要求向服务器发起请求。

no-store:所有内容都不会被保存到缓存或Internet临时文件中。

no-transform:告知客户端缓存文件时不得对实体数据做任何改变。

only-if-cached:告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向原服务器发去请求。

must-revalidate:当前资源一定是向原服务器发去验证请求的,若请求失败会返回504(而非代理服务器上的缓存)

proxy-revalidate:与must-revalidate类似,但仅能应用于共享缓存(如代理)。

max-age=delta-seconds:告知客户端该资源在delta-seconds秒内是新鲜的,无需向服务器发请求。

s-maxage=delta-seconds:同max-age,但仅应用于共享缓存(如代理)

cache-extension:自定义拓展值,若服务器不识别该值将被忽略掉。

(22)ContentDisposition:该类表示在RFC 6266中定义的属性Content-Disposition。Content-Disposition 属性是作为对下载文件的一个标识字段,有两种类型:inline 和 attachment。inline :将文件内容直接显示在页面;attachment:弹出对话框让用户下载。RFC 6266正式将Content-Disposition纳入 HTTP 标准。

(23)HttpLogging:如果"org.springframework.web"日志功能开启,但是"org.springframework.http"日志功能没有开始,那么此时创建一个共享的日志记录器(命名为org.springframework.web.HttpLogging),用来记录和HTTP相关的日志。这也就是说"org.springframework.web"会开启所有web日志记录器,包括一些低层级的包(如"org.springframework.http")和模块(比如来自于spring-core被包装进EncoderHttpMessageWriter或DecoderHttpMessageReader的编解码器)。

(24)HttpCookie:用来表示一条HTTP cookie,以name-value(名称-键值对)形式表示。

HTTP协议是无状态的协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足,是http协议的一个扩展。

有两个http头部是专门负责设置以及发送cookie的,它们分别是Set-Cookie(响应报文首部)以及Cookie(请求报文首部)。当服务器返回给客户端一个http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。

(25)ResponseCookie:继承自HttpCookie,增加了Set-Cookie 响应首部的一些属性。下面是Set-cookie一个简单的例子:

HTTP/1.0 200 OK

Set-cookie: id="34294"; domain="joes-hardware.com"

Content-type: text/html

Content-length: 1903

最初的cookie 规范是由网景公司定义的。这些“ 版本0” 的cookie 定义了Set-Cookie 响应首部、cookie 请求首部以及用于控制cookie 的字段。版本0(网景)的Set-Cookie属性:

1、NAME=VALUE:强制的,服务器可以创建任意的NAME=VALUE关联,在后续对站点的访问中会将其送回给服务器。

2、Expires:可选的,该属性用来指定一个日期字符串,用来定义cookie的实际生存期。一旦到了过了生存日期,就不再存储或者发布这个cookie了。

3、Domain:可选的。浏览器只向指定域中的服务器发送cookie。

4、Path:可选的。这个属性可以为服务器上特定的文档分配cookie。

5、Secure:可选的。如果包含了这一属性,就只有在HTTP使用SSL安全连接时才会发送cookie。

三、client端的request请求(发送出去的)/response响应(接收到的)

client端的类主要有三种:

ClientHttpRequest表示一个客户端发送的HTTP request请求报文(包括基本实现类及支持Buffering、Streaming、Async、StreamingAsync、BufferingAsync拓展类)。

ClientHttpResponse表示一个客户端接收到的HTTP response响应报文。(包括基本实现类和支持Async拓展类)。

ClientHttpRequestFactory用来创建ClientHttpRequest的工厂(包括基本实现类和支持Async拓展类)。

上述又分为基于jkd自带功能、Apache的HttpClient、OkHttp3、Netty4的实现。使用Apache的HttpClient、OkHttp3、Netty4都可,但这些都需要额外导包,默认情况下Spring使用的是java.net.HttpURLConnection。

(一)http/client/

接口

(1)ClientHttpRequest:表示一个客户端的request请求报文。继承自HttpRequest、 HttpOutputMessage(因为从客户端看request是发送出去的,所以继承自HttpOutputMessage。同理,客户端的ClientHttpResponse是接收到的报文,继承自HttpInputMessage)。通过ClientHttpRequestFactory工厂的实现类创建。该接口定义了一个函数execute(),函数的返回类型就是ClientHttpResponse。

(2)ClientHttpResponse:表示客户端接收到的HTTP response响应报文。继承自HttpInputMessage、Closeable。通过执行ClientHttpRequest的execute()函数获得。

(3)ClientHttpRequestFactory:创建ClientHttpRequest对象的工厂。定义了一个函数createRequest(URI, HttpMethod),根据URI和HttpMethod创建出一个ClientHttpRequest来发送请求。

(4)ClientHttpRequestInitializer:回调接口,在ClientHttpRequest使用之前先对其初始化。

(5)ClientHttpRequestExecution:表示客户端HTTP request报文执行(execute)的上下文。主要在ClientHttpRequestInterceptor使用,用来在一个拦截器链上调用下一个拦截器,如果到了拦截器末尾,执行request本身。

(6)ClientHttpRequestInterceptor:客户端的Http request请求拦截器,在Http消息发送到服务器前,该方法被调用,对Http Request报文做些处理,比如加头,更改请求的URL,授权等等。对于客户端接收到的ClientHttpResponse也能处理。

(7)AsyncClientHttpRequest:继承自HttpRequest、HttpOutputMessage,表示客户端一个异步的HTTP request请求,通过工厂类创建。(Spring4.0新增,Spring 5.0中废弃,使用org.springframework.web.reactive.function.client.ClientRequest替代)

应用层的网络模型有同步与异步。同步意味当前线程是阻塞的,只有本次请求完成后才能进行下一次请求;异步意味着所有的请求可以同时塞入缓冲区,不阻塞当前的线程。

(8)AsyncClientHttpRequestFactory:创建AsyncClientHttpRequest的工厂,。通过函数createAsyncRequest(URI, HttpMethod)创建。(Spring4.0新增,Spring 5.0中废弃,使用org.springframework.http.client.reactive.ClientHttpConnector替代)

(9)AsyncClientHttpRequestExecution:ClientHttpRequestExecution异步拓展。(Spring4.3新增,Spring 5.0中废弃,使用org.springframework.web.reactive.function.client.ExchangeFilterFunction替代)

(10)AsyncClientHttpRequestInterceptor:ClientHttpRequestInterceptor异步拓展。(Spring4.3新增,Spring 5.0中废弃,使用org.springframework.web.reactive.function.client.ExchangeFilterFunction替代)

抽象类

(11)AbstractClientHttpRequest:实现接口ClientHttpRequest,确保首部和报文体不会多次写入。

(12)AbstractBufferingClientHttpRequest:继承自AbstractClientHttpRequest。在request请求报文发送出去之前,缓存request body,内部private ByteArrayOutputStream bufferedOutput变量保存了request body的内容,避免流的二次读取会导致读取不到数据。

(13)AbstractAsyncClientHttpRequest:实现 AsyncClientHttpRequest接口的抽象类。( Spring 5.0中废弃,使用org.springframework.http.client.reactive. AbstractClientHttpRequest替代。)

(14)AbstractBufferingAsyncClientHttpRequest:同时拓展了异步和缓存功能的request报文,继承自AbstractAsyncClientHttpRequest。(Spring 5.0中废弃,无直接替代者)。

(15)AbstractClientHttpResponse:实现接口ClientHttpResponse。

(16)AbstractClientHttpRequestFactoryWrapper:装饰抽象类,实现接口ClientHttpRequestFactory,装饰另一个request factory。装饰模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。装饰类一般是一个抽象类,属性里有一个private变量指向ClientHttpRequestFactory,通过构造函数传递给被该修饰者,createRequest方法委托给被修饰者执行。

 

装饰器类

(17)BufferingClientHttpRequestWrapper:包装另外一个request。

(28)BufferingClientHttpResponseWrapper:实现ClientHttpResponse接口。考虑到多次调用getBody(),将接收到的response报文的body部分读入到内存中。

(19)BufferingClientHttpRequestFactory:ClientHttpRequestFactory的装饰器,使得具有缓存的能力。若开启缓存功能(有开关可控),会使用BufferingClientHttpRequestWrapper包装原来的ClientHttpRequest。这样发送请求后得到的是BufferingClientHttpResponseWrapper响应。

(20)InterceptingClientHttpRequest:包装了ClientHttpRequest,支持HTTP 请求拦截器 ClientHttpRequestInterceptor。该类重写了executeInternal方法,通过内部类InterceptingRequestExecution实现interceptors顺序执行。该内部类中的的execute()方法的特点是:若存在拦截器,交给给拦截器去执行发送请求return nextInterceptor.intercept(request, body, this),否则就自己上。

(21)InterceptingAsyncClientHttpRequest:包装了AsyncClientHttpRequest,该类重写了executeInternal方法,通过内部类AsyncRequestExecution实现AsyncClientHttpRequestInterceptor顺序执行。该内部类中的的executeAsync()方法的特点是:若存在拦截器,交给给拦截器去执行发送请求:

return interceptor.intercept(request, body, this);

否则就自己上:

delegate = requestFactory.createAsyncRequest(uri, method);

return delegate.executeAsync();

(22)InterceptingClientHttpRequestFactory:继承自AbstractClientHttpRequestFactoryWrapper。包装ClientHttpRequestFactory,以支持ClientHttpRequestInterceptor(客户端的Http request请求拦截器,在Http消息发送到服务器前,该方法被调用,对Http Request报文做些处理)。

(23)InterceptingAsyncClientHttpRequestFactory:实现接口AsyncClientHttpRequestFactory。包装AsyncClientHttpRequestFactory,以支持AsyncClientHttpRequestInterceptor。(Spring 5.0,废弃,无代替者)

在介绍下面类之前,先总体介绍下ClientHttpRequest和ClientHttpRequestFactory在不同库下的实现:

ClientHttpRequest它代表请求的客户端,该接口继承自HttpRequest、HttpOutputMessage,只有一个ClientHttpResponse execute() throws IOException方法。其中HttpUrlConnection 、OkHttp3、Netty、HttpComponents对它都有实现。默认情况下Spring使用的是java.net.HttpURLConnection,也可以使用OkHttp3、Netty4、Apache的HttpClient,但这些都需要额外导包。

ClientHttpRequestFactory是一个函数式接口,用于根据URI和HttpMethod创建出一个ClientHttpRequest来发送请求。根据使用底层http库的不同可以分为:

1、SimpleClientHttpRequestFactory:Spring内置ClientHttpRequestFactory默认的实现,它使用JDK工具(来自java.net包的类),因此不依赖于第三方库。

2、OkHttp3ClientHttpRequestFactory:封装OkHttp 3.x

3、Netty4ClientHttpRequestFactory:封装Netty 4。(Spring 5.0中废弃,使用org.springframework.http.client.reactive.ReactorClientHttpConnector替代)。

4、HttpComponentsClientHttpRequestFactory:封装Apache的HttpClient。

使用JDK内置库

(24)SimpleBufferingClientHttpRequest:ClientHttpRequest接口的实现类,带缓冲功能。通过SimpleClientHttpRequestFactory创建。

(25)SimpleStreamingClientHttpRequest:ClientHttpRequest接口的实现类,能执行流处理请求,通过SimpleClientHttpRequestFactory创建。

(26)SimpleBufferingAsyncClientHttpRequest:继承自AbstractBufferingAsyncClientHttpRequest,通过SimpleClientHttpRequestFactory创建。

(27)SimpleStreamingAsyncClientHttpRequest:继承自AbstractAsyncClientHttpRequest,能执行流处理请求,通过SimpleClientHttpRequestFactory创建。

(28)SimpleClientHttpResponse:ClientHttpResponse接口实现类,通过执行SimpleBufferingClientHttpRequest的函数execute()或者SimpleStreamingClientHttpRequest的函数execute()获得。

(29)SimpleClientHttpRequestFactory:ClientHttpRequestFactory接口的实现类,继承自ClientHttpRequestFactory和AsyncClientHttpRequestFactory。重写了ClientHttpRequestFactory的createRequest()函数(用来生成上面24、25两种类型的request)和AsyncClientHttpRequestFactory的createAsyncRequest()函数(用来生成上面26、27两种类型的request)。

使用OkHttp 3.x框架

OkHttp是一款优秀的HTTP框架,一个处理网络请求的开源项目,是安卓端的轻量级框架,由移动支付Square公司贡献。支持get请求和post请求,支持基于Http的文件上传和下载,支持加载图片,支持下载文件透明的GZIP压缩,支持响应缓存避免重复的网络请求,支持使用连接池来降低响应延迟问题。导包示例:

<dependency>

<groupId>com.squareup.okhttp3</groupId>

<artifactId>okhttp</artifactId>

<version>3.14.0</version>

</dependency>

(30)OkHttp3ClientHttpRequest:基于OkHttp 3.x的ClientHttpRequest接口的实现类。通过OkHttp3ClientHttpRequestFactory创建。

(31)OkHttp3AsyncClientHttpRequest:基于OkHttp 3.x的AsyncClientHttpRequest接口的实现类。通过OkHttp3ClientHttpRequestFactory创建。(Spring 5.0中废弃,无替代者)。

(32)OkHttp3ClientHttpResponse:基于OkHttp 3.x的ClientHttpResponse接口实现类。通过执行OkHttp3ClientHttpRequest的executeInternal()函数获得。

(33)OkHttp3ClientHttpRequestFactory:ClientHttpRequestFactory接口的实现类,基于OkHttp 3.x创建request,createRequest()函数创建OkHttp3ClientHttpRequest;createAsyncRequest()函数创建OkHttp3AsyncClientHttpRequest。

使用Netty 4框架

Netty是由JBOSS提供给的一个java开源框架。Netty提供异步的、事件驱动的网络应用框架和工具,用以快速开发高性能、高可靠的网络服务器和客户端程序。导包示例:

<dependency>

<groupId>io.netty</groupId>

<artifactId>netty-all</artifactId>

<version>5.0.0.Alpha2</version>

</dependency>

(34)Netty4ClientHttpRequest:基于Netty 4的ClientHttpRequest接口的实现类,通过Netty4ClientHttpRequestFactory创建。

(35)Netty4ClientHttpResponse:基于Netty 4的ClientHttpResponse接口的实现类。

(36)Netty4ClientHttpRequestFactory :ClientHttpRequestFactory接口的实现类,基于Netty 4创建Netty4ClientHttpRequest。

使用Apache的HttpClient框架

Apache开源组织的HttpComponents 也就是以前的httpclient项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端/服务器编程工具包,支持 HTTP 协议最新的版本和建议。现在的 HttpComponents 包含多个子项目:HttpComponents Core、HttpComponents Client、HttpComponents AsyncClient、Commons HttpClient。导包示例:

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpclient</artifactId>

<version>4.5.10</version>

</dependency>

(37)HttpComponentsClientHttpRequest:基于Apache HttpComponents HttpClient的ClientHttpRequest接口的实现类。通过(42)HttpComponentsClientHttpRequestFactory创建。

(38)HttpComponentsStreamingClientHttpRequest:基于Apache HttpComponents HttpClient的执行流处理请求的ClientHttpRequest接口的实现类。通过(42)HttpComponentsClientHttpRequestFactory创建。

(39)HttpComponentsAsyncClientHttpRequest:基于Apache HttpComponents HttpAsyncClient的ClientHttpRequest接口的实现类,通过(43)HttpComponentsAsyncClientHttpRequestFactory创建。(Spring 5.0中废弃,无替代者)

(40)HttpComponentsClientHttpResponse:基于Apache HttpComponents HttpClient的ClientHttpResponse接口的实现类。通过(37)HttpComponentsClientHttpRequest的executeInternal()函数创建。

(41)HttpComponentsAsyncClientHttpResponse:基于Apache HttpComponents HttpAsyncClient的ClientHttpResponse接口的实现类。通过(39)HttpComponentsAsyncClientHttpRequest创建。(Spring 5.0中废弃,无替代者)

(42)HttpComponentsClientHttpRequestFactory:ClientHttpRequestFactory接口的实现类,基于Apache HttpComponents HttpClient创建request。通过createRequest()函数来创建(37)HttpComponentsClientHttpRequest(bufferRequestBody属性为true情况下,属性bufferRequestBody用来表示该工厂是否需要在内部缓存request body,默认为true)或者(38)HttpComponentsStreamingClientHttpRequest(bufferRequestBody属性为false情况下,如果通过POST或者PUT方法发送大量的数据,推荐设置为false,以防止缓存溢出)。

(43)HttpComponentsAsyncClientHttpRequestFactory:继承自HttpComponentsClientHttpRequestFactory,基于Apache HttpComponents HttpAsyncClient 4.0创建(39)HttpComponentsAsyncClientHttpRequest(Spring 5.0中废弃,无替代者)

(44)MultipartBodyBuilder:为multipart请求类准备请求体,以MultiValueMap<String, HttpEntity>形式返回。http协议采纳了多部对象集合(multipart),multipart 请求类主要是对文件上传进行的处理,发送一份报文主体内可含有多个类型实体,通常在图片或者文本上传时使用,其中邮件上传各种附件的机制也是用了MIME的Mulipart方法。

(二)http/client/reactive

reactive programming(响应式编程)是一种异步编程风格,它关注数据流和变化的传播,与之相对应的是imperative programming(命令式编程)。

在命令式编程中,a:=b+c意味着将b+c的结果赋值给a,并且此后b或c的值发生变化不会影响到a的值。而在响应式编程中,a的值会随着b或c的改变而自动更新,并且不需要重新执行a:=b+c来确定当前分配给a的值。例如,在 model–view–controller (MVC) 架构中,响应式编程可以促进基础模型中的更改,这些更改会自动反映在关联的视图中。

如果从推拉的角度来看的话,响应式编程是“推”,它主动将变化推送给它的订阅者。Publisher-Subscriber是两个非常重要的概念。本质来讲,响应式编程上是对数据流或某种变化所作出的反应,但是这个变化什么时候发生是未知的,所以他是一种基于异步、回调的方式在处理问题

接口

(1)ClientHttpRequest:继承自ReactiveHttpOutputMessage的接口,表示一个客户端的响应式HTTP request请求报文。

(2)ClientHttpResponse:继承自ReactiveHttpInputMessage的接口,表示一个客户端的响应式HTTP response响应报文。

(3)ClientHttpConnector:客户端的HTTP连接器接口,从HTTP客户端抽象出来的一个功能,使HTTP客户端连接到服务器上,也提供了发送ClientHttpRequest和接收ClientHttpResponse所有必要的基础设施。

抽象类

(4)AbstractClientHttpRequest:上述ClientHttpRequest接口实现的抽象类。

装饰器类

(5)ClientHttpRequestDecorator:ClientHttpRequest的装饰器。

(6)ClientHttpResponseDecorator:ClientHttpResponse的装饰器。

 

Jetty ReactiveStreams HTTP client

Jetty 是一个开源的servlet容器,适用于一个通用的Reactive Streams API。

(7)JettyClientHttpRequest:继承自AbstractClientHttpRequest。

(8)JettyClientHttpResponse:ClientHttpResponse接口实现类。

(9)JettyClientHttpConnector:ClientHttpConnector接口实现类。

(10)JettyResourceFactory:在Spring的ApplicationContext容器生命周期范围内,用来管理Jetty资源的工厂,比如Executor、ByteBufferPool、Scheduler。该工厂实现了InitializingBean、DisposableBean接口。一般被声明为Spring管理bean。

 

Reactor-Netty HTTP client

Netty是一个java开源框架,适用于一个通用的Reactive Streams API。

(11)ReactorClientHttpRequest:继承自AbstractClientHttpRequest、ZeroCopyHttpOutputMessage。

(12)ReactorClientHttpResponse:ClientHttpResponse接口实现类。

(13)ReactorClientHttpConnector:ClientHttpConnector接口实现类。

(14)ReactorResourceFactory:在Spring的ApplicationContext容器生命周期范围内,用来管理Reactor Netty资源的工厂,比如LoopResources、ConnectionProvider。该工厂实现了InitializingBean、DisposableBean接口。一般被声明为Spring管理bean。

(三)http/client/support

(1)HttpAccessor:作为RestTemplate的基类或者其他HTTP访问网关的助手类。定义了一些通用的属性,如ClientHttpRequestFactory。

(2)AsyncHttpAccessor:作为AsyncRestTemplate的基类或者其他HTTP访问网关的助手类。定义了一些通用的属性,如AsyncClientHttpRequestFactory。

(3)InterceptingHttpAccessor:继承自HttpAccessor,增加了一些拦截器相关的属性。

(4)InterceptingAsyncHttpAccessor:继承自AsyncHttpAccessor,增加了请求拦截功能。

(5)BasicAuthenticationInterceptor:ClientHttpRequestInterceptor接口的实现类,使用username/password做一个HTTP基本认证,除非的Authorization header设置好了。

(6)BasicAuthorizationInterceptor:ClientHttpRequestInterceptor接口的实现类,使用一个基本的 Authorization 消息头。

(7)HttpRequestWrapper:HttpRequest装饰器类。

(8)ProxyFactoryBean:实现ProxyFactoryBean、InitializingBean接口,用于生成代理对象java.net.Proxy。重写了InitializingBean的afterPropertiesSet函数,这个方法在所有的属性被初始化后但是在init前调用。

四、server端的request请求(接收到的)/response响应(发送出去的)

(一)http/server/

(1)PathContainer:接口,将通过执行函数parsePath(String)得到的URI path结构化表示成一系列的分隔符和PathSegment。

(2)DefaultPathContainer:PathContainer接口的默认实现。

(3)RequestPath:继承自PathContainer的接口,表示一个请求报文完整的路径。

(4)DefaultRequestPath:RequestPath接口的默认实现。

(5)ServerHttpRequest:继承自HttpRequest、HttpInputMessage的接口,表示服务器端接收到的HTTP request请求报文。

(6)ServerHttpResponse:继承自HttpOutputMessage、Flushable、Closeable的接口,表示服务器端发送出去的HTTP response响应报文。

(7)ServerHttpAsyncRequestControl:一个控件接口,能将对HTTP request请求报文的处理置于异步模式下,在response响应处于open的状态下直至明确关闭。

(8)ServletServerHttpRequest:基于HttpServletRequest的ServerHttpRequest接口的实现类。

HttpServletRequest(javax.servlet.http.HttpServletRequest)继承自ServletRequest,代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,包含了客户端请求信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。通过这个对象提供的方法,可以获得客户端请求的所有信息。

(9)ServletServerHttpResponse:基于HttpServletResponse的ServerHttpResponse接口的实现类。

HttpServletResponse继承了ServletResponse接口,代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。并提供了与Http协议有关的方法,这些方法的主要功能是设置HTTP状态码和管理Cookie。

(10)ServletServerHttpAsyncRequestControl:实现了接口AsyncListener、ServerHttpAsyncRequestControl,在Servlet容器(Servlet 3.0+)上使用。

(二)http/server/reactive

(1)AbstractListenerReadPublisher:实现接口Publisher的抽象类,用来在event-listener read APIs 和Reactive Streams建立联系。具体来说就是使用Servlet 3.1 non-blocking I/O和Undertow XNIO读取HTTP request请求体,此外也可以使用标准的Java WebSocket (JSR-356)、Jetty、Undertow处理刚收到的WebSocket消息。

(2)AbstractListenerServerHttpResponse:抽象类,作为基于listener的服务器端响应报文 的父类,比如Servlet 3.1和Undertow。

(3)AbstractListenerWriteProcessor:实现Processor接口的抽象类,用来在event-listener write APIs 和Reactive Streams建立联系。具体来说就是使用Servlet 3.1 non-blocking I/O和Undertow XNIO写入HTTP request请求体,此外也可以使用标准的Java WebSocket (JSR-356)、Jetty、Undertow写入WebSocket消息。

(4)AbstractListenerWriteFlushProcessor:实现Processor接口的抽象类,AbstractListenerWriteProcessor的一个替代类,不同的是在每一个嵌套Publisher都完成后,writing a Publisher with flush boundaries enforces。

(5)ChannelSendOperator:考虑一个用source Publisher写的写函数,返回的结果是一个result Pulisher,这个操作符的作用就是推迟这个写函数的调用,直到我们确定source Publisher将会无错误的发布。

(6)DefaultServerHttpRequestBuilder:ServerHttpRequest.Builder接口的默认实现类。

(7)WriteResultPublisher:实现Publisher接口,该发布者通过执行ServerHttpResponse的writeWith(Publisher)函数得到。

Publisher是一个可以提供 0-N 个序列元素的提供者,并根据其订阅者Subscriber的需求推送元素。一个Publisher可以支持多个订阅者,并可以根据订阅者的逻辑进行推送序列元素。Reactor中有两种Publisher:Flux和Mono,其中Flux用来表示0-N个元素的异步序列,Mono用来表示0-1个元素的异步序列。

1、Flux 是一个发出(emit)0-N个元素组成的异步序列的Publisher<T>,可以被onComplete信号或者onError信号所终止。在响应流规范中存在三种给下游消费者调用的方法 onNext、onComplete和onError。

2、Mono 是一个发出(emit)0-1个元素的Publisher<T>,可以被onComplete信号或者onError信号所终止。

(8)SslInfo:SSL 会话信息的句柄。SSL(Secure Sockets Layer 安全套接字协议)是为网络通信提供安全及数据完整性的一种安全协议。

(9)DefaultSslInfo:SslInfo接口的默认实现。

(10)JettyHeadersAdapter:实现MultiValueMap接口,用于包装Jetty HTTP headers。

MultiValueMap即一个键对应多个值,我们平时使用的Map一个key只能对应一个value,如果想要一个key对应多个value,通常我们会将多个value放到一个集合中。sping对此做了简单的封装,封装之后的接口为MultiValueMap。

Netty、Undertow、Tomcat、Jetty都是web容器,都适用于一个通用的Reactive Streams API。

(11)NettyHeadersAdapter:实现MultiValueMap接口,用于包装Netty HTTP headers。

(12)TomcatHeadersAdapter:实现MultiValueMap接口,用于包装Tomcat HTTP headers。

(13)UndertowHeadersAdapter:实现MultiValueMap接口,用于包装Jetty HTTP headers。

 

(14)HttpHandler:一个对于HTTP请求的略偏底层的协定, 规范了Tomcat、Jetty、Netty、Undertow、Servlet3.1等服务器。 旨在对于不同的Web服务器提供更加抽象统一的接口。更高一级的通用模块,如WebFilter、WebSession、ServerWebExchange在org.springframework.web.server包中。应用级别编程模型,如注解控制器和功能处理程序在spring-webflux模块中。

(15)ContextPathCompositeHandler:HttpHandler接口实现类。

(16)ReactorHttpHandlerAdapter:适配器,适配HttpHandler和处理Netty channel响应式函数。实现了接口BiFunction<HttpServerRequest, HttpServerResponse, Mono<Void>>,HttpServerRequest表示函数的第一个参数的类型,HttpServerResponse表示函数的第二个参数的类型,Mono<Void>表示函数结果的类型。方法apply​(reactorRequest, reactorResponse)将此函数应用于给定的参数。

(17)ServletHttpHandlerAdapter:适配器,适配HttpHandler和HttpServlet

(18)TomcatHttpHandlerAdapter:继承自ServletHttpHandlerAdapter,对ServletHttpHandlerAdapter适配器做了拓展,使用Tomcat APIs读取接收到的request请求报文或者写入要发送出去的response响应报文。

(19)JettyHttpHandlerAdapter:继承自ServletHttpHandlerAdapter,对ServletHttpHandlerAdapter适配器做了拓展,使用Jetty APIs写入要发送出去的response响应报文。

(20)UndertowHttpHandlerAdapter:实现接口io.undertow.server.HttpHandler,适配HttpHandler和io.undertow.server.HttpHandler。

(21)ServerHttpRequest:继承自HttpRequest,ReactiveHttpInputMessage的接口。表示一个响应式的服务器端接收到的HTTP request请求报文。

(22)ServerHttpResponse:继承自ReactiveHttpOutputMessage的接口。表示一个响应式的服务器端发送出去的HTTP response响应报文。

(23)AbstractServerHttpRequest:ServerHttpRequest接口实现的抽象类。

(24)AbstractServerHttpResponse:ServerHttpResponse接口实现的抽象类。

(25)ServerHttpRequestDecorator:ServerHttpRequest装饰类。

(26)ServerHttpResponseDecorator:ServerHttpResponse装饰类。

(27)HttpHeadResponseDecorator:继承自ServerHttpResponseDecorator,HTTP request使用head方法的请求报文(HEAD方法请求一个与GET请求的响应相同的响应,但没有响应体)返回的响应报文ServerHttpResponse的装饰类。

(28)ServletServerHttpRequest:Servlet服务器端收到的请求报文。

(29)ServletServerHttpResponse:Servlet服务器端发送出去的响应报文。

(30)ReactorServerHttpRequest:Reactor服务器端收到的请求报文。

(31)ReactorServerHttpResponse:Reactor服务器端发送出去的响应报文。

(32)UndertowServerHttpRequest:Undertow服务器端收到的请求报文。

(33)UndertowServerHttpResponse:Undertow服务器端发送出去的响应报文。

五、格式的转换,如json,rss,xml等

(一)http/converter/

(1)HttpMessageConverter:策略接口, HTTP request 请求报文和response响应报文的转换器,将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。该接口有5个方法:获取该转换器支持的 MediaType列表(getSupportedMediaTypes),判断接收到request是否能读(canRead),判断能否写发送出去的报文(canWrite),读取接收到的报文(read),写入要发送的报文(write)。

(2)AbstractHttpMessageConverter:大部分HttpMessageConverter接口实现类的抽象基类。通过setSupportedMediaTypes(List)函数可以设置支持的MediaTypes,在写入要发送出去的消息时增加了对Content-Type和Content-Length支持。

(3)GenericHttpMessageConverter:继承自HttpMessageConverter的接口,用来将一个HTTP request报文转换成指定通用类型的目标对象,或者将一个指定通用类型的源对象转换成一个HTTP response报文。

(4)AbstractGenericHttpMessageConverter:大部分GenericHttpMessageConverter接口实现类的抽象基类。

(5)ByteArrayHttpMessageConverter:将request信息转换为byte数组,或者将byte数组输出为response信息。

(6)StringHttpMessageConverter:将request信息转换为String类型,或者将String类型输出为response信息。

(7)ObjectToStringHttpMessageConverter:使用StringHttpMessageConverter对content进行读写,使用ConversionService对String content和目标对象进行相互转换。

(8)FormHttpMessageConverter:将request信息转换为HTML表单,或者将HTML表单输出为response信息,或者将MultiValueMap<String, String>输出为response信息(但是不会将request信息转换成MultiValueMap)。

(9)BufferedImageHttpMessageConverter:将request信息转换为BufferedImage,或者将BufferedImage输出为response信息。

(10)ResourceHttpMessageConverter:将request信息转换为Resources,或者将Resources输出为response信息。默认情况下,该转换器可以读取所有类型的media(读取request),能输出到response中的类型在MediaTypeFactory定义。

(11)ResourceRegionHttpMessageConverter:将一个或者一批ResourceRegion输出为response信息。

(二)http/converter/cbor

MappingJackson2CborHttpMessageConverter:能使用专用的Jackson 2.x拓展库对CBOR格式的数据进行读写。简明二进制对象展现(CBOR,Concise Binary Object Representation)是一种提供良好压缩性,扩展性强,不需要进行版本协商的二进制数据交换形式。

(三)http/converter/feed

(1)AbstractWireFeedHttpMessageConverter:作为AtomFeedHttpMessageConverter和RssChannelHttpMessageConverter的基类,使用了Rome开源包。

Feed:消息来源,是一种资料格式,网站通过它将最新资讯传播给用户。将feed汇流于一处称为聚合。RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容),通常被用于新闻和其他按顺序排列的网站,例如Blog。ATOM是Rss的一个替代品。RSS和ATOM两种订阅方式出形式都是FEED。Rome是为RSS聚合而开发的开源包。

(2)AtomFeedHttpMessageConverter:转换Atom feeds。

(3)RssChannelHttpMessageConverter:转换RSS feeds。

(四)http/converter/json

json (JavaScript Object Notation) 是javascript对象的一种形态,一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。

json有两种数据类型:json和jsonb,而两者唯一的区别在于效率,json是对输入的完整拷贝,使用时再去解析,所以它会保留输入的空格,重复键以及顺序等。而jsonb是解析输入后保存的二进制,它在解析时会删除不必要的空格和重复的键,顺序和输入可能也不相同。使用时不用再次解析。两者对重复键的处理都是保留最后一个键值对。效率的差别:json类型存储快,使用慢,jsonb类型存储稍慢,使用较快。

Java操作json的库有:JSON-B 、Jackson、Gson和fastjson。

Java EE8 中新的 JSON Binding API (JSON-B) 支持在 Java 对象与JSON之间序列化和反序列化。从功能上讲,JSON-B API包含两个入口点接口:javax.json.bind.Jsonb和javax.json.bindJsonBuilder。Jsonb接口分别通过方法toJson()和fromJson()实现序列化和反序列化。JsonBuilder接口基于一组可选的操作而构造Jsonb实例,并为客户端提供对实例的访问权。

Jackson 是一个 Java 的用来处理 JSON 格式数据的类库。

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。使用如下例所示:

public class User{
//省略带参构造方法
private int id;
private String userName;
}
User user = new User(1,"zs");
String userJson = gson.toJson(user); // 序列化user对象为 {"id":1,"userName":"zs"}
user = gson.fromJson(userJson,User.class); //反序列化

(1)AbstractJsonHttpMessageConverter:JSON转换器的基类,比如GSON和JSON-B。

(2)JsonbHttpMessageConverter:使用JSON-B库的JSON转换器。

(3)MappingJacksonValue:MappingJackson2HttpMessageConverter要执行序列化操作(将Java对象序列化为JSON字符串)的简单Java对象。

(4)MappingJacksonInputMessage:此message用来存储一个Jsonb实例,该message会被进行反序列化成Java对象。

(5)Jackson2ObjectMapperBuilder:构建器,使用流式 API接口来创建ObjectMapper实例。ObjectMapper类是Jackson库的主要类。ObjectMapper类的readValue API 可以解析或反序列化json内容为java对象。 反之,writeValue API可以序列化任何java对象为json字符串。

(6)Jackson2ObjectMapperFactoryBean:一个FactoryBean,用来创建Jackson 2.x ObjectMapper对象(默认情况下),或者XmlMapper对象(createXmlMapper属性设置为true情况下)。

(7)SpringHandlerInstantiator:通过Spring 的ApplicationContext容器创建Jackson自动装配的JsonSerializer、JsonDeserializer、KeyDeserializer、TypeResolverBuilder、TypeIdResolver的beans。

(8)AbstractJackson2HttpMessageConverter:基于Jackson、与Content-Type无关的HttpMessageConverter接口实现类的抽象基类。

(9)MappingJackson2HttpMessageConverter:HttpMessageConverter接口的实现类,使用Jackson 2.x的ObjectMapper对JSON进行转换。

(10)GsonFactoryBean:FactoryBean,用来创建一个Google Gson 2.x Gson实例。

(11)GsonBuilderUtils:取得Google Gson 2.x  GsonBuilder功能类。GsonBuilder用来生成Gson对象,规定Gson的序列化和返序列化时的格式等内容。

(12)GsonHttpMessageConverter:HttpMessageConverter接口实现类,使用Google Gson库来对JSON进行转换。

(五)http/converter/protobuf

(1)ExtensionRegistryInitializer:Google协议消息能够包含可以被解析的消息拓展,如果相应的配置信息在ExtensionRegistry中已经被注册过。该接口使用协议消息拓展来初始化ExtensionRegistry

(2)ProtobufHttpMessageConverter:使用Google Protocol Buffers来对com.google.protobuf.Messages进行转换。

(3)ProtobufJsonFormatHttpMessageConverter:ProtobufHttpMessageConverter的子类,使用Protobuf 3和它的官方库在对JSON处理上做了增强。Protobuf是google开发的一种跨语言和平台的序列化数据结构的方式,类似于XML但是更小更快而且更简单,只需要定义一次结构体,通过生成的源代码可以在不同的数据流和不同的语言平台上去读写数据结构。最新的protobuf3支持更多的语言使用,比如go、object-c等。

(六)http/converter/smile

MappingJackson2SmileHttpMessageConverter:使用Jackson 2.x专用的拓展对Smile数据格式(binary JSON)进行转换。

BSON(binary json)是10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式。BSON基于JSON格式,普通JSON标记和BSON之间的主要区别在于BSON是JSON的二进制标记版本。由于BSON更紧凑,因此在反序列化时它具有更少的开销,并且对于大型和复杂的有效载荷来说是更好的选择。

(七)http/converter/support

AllEncompassingFormHttpMessageConverter:FormHttpMessageConverter转换器的拓展,增加了对XML和JSON-based parts的支持。

(八)http/converter/xml

(1)AbstractXmlHttpMessageConverter:用来转换XML的转换器的抽象基类。继承该抽象类的转换器支持text/xml、application/xml、application/*-xml。

(2)AbstractJaxb2HttpMessageConverter:使用JAXB2的转换器的抽象基类。getJaxbContext()函数用来为指定的类创建JAXBContext。

JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到 XML实例文档。Jaxb 2.0是JDK 1.6的组成部分,不需要下载第三方jar包即可做到轻松转换。

JAXBContext 类提供到 JAXB API 的客户端入口点。它提供了管理实现 JAXB 绑定框架操作所需的 XML/Java 绑定信息的抽象,这些操作包括:解组、编组和验证。

(3)SourceHttpMessageConverter:用来转换Source对象。

(4)Jaxb2CollectionHttpMessageConverter:该转换器使用JAXB2来将一个HTTP request报文转换成XML collections,但是不支持将其转换成一个HTTP response报文。

(5)Jaxb2RootElementHttpMessageConverter:使用JAXB2来转换XML(支持读写,也就是支持将request转换成XML,将XML转换成response报文)

(6)MappingJackson2XmlHttpMessageConverter:使用Jackson 2.x拓展部件来转换XML,该转换器支持application/xml、text/xml、application/*+xml,使用UTF-8编码方式。

(7)MarshallingHttpMessageConverter:使用Spring的Marshaller和Unmarshaller来转换XML,在转换器使用之前要先准备好Marshaller和Unmarshaller。

六、编/解码器

对于表单数据,二进制/文件内容,服务器发送的事件等spring-web模块提供了包括Jackson JSON,Jackson Smile,JAXB2,Protocol Buffers的编/解码器以及只支持web的HTTP消息读/写器实现。

(一)http/codec/

(1)CodecConfigurer:用来配置和自定义客户端或者服务器端处理HTTP报文的编解码器的通用接口。

(2)CodecConfigurerFactory:创建CodecConfigurer的工厂类。

(3)ClientCodecConfigurer:拓展自CodecConfigurer的接口,用于配置和自定义要在客户端使用的编解码器。

(4)ServerCodecConfigurer:拓展自CodecConfigurer的接口,用于配置和自定义要在服务器端使用的编解码器。

(5)LoggingCodecSupport:Encoder、Decoder、HttpMessageReader、HttpMessageWriter类的基类,使用一个日志记录器,记录一些敏感的信息。

(6)HttpMessageDecoder:用于解码分离开的HTTP内容。拓展自Decoder的接口,增加了一些解码HTTP request 和response body相关的函数。

(7)HttpMessageEncoder:用于编码分离开的HTTP内容。拓展自Encoder的接口,增加了一些编码HTTP request 和response body相关的函数。

(8)HttpMessageReader:接口,用于解码HTTP 消息内容的解码器。

(9)HttpMessageWriter:接口,用于编码HTTP 消息内容的编码器。

(10)DecoderHttpMessageReader:封装解码器HttpMessageReader,使其可以合适的用于Web应用。

(11)EncoderHttpMessageWriter:封装编码器HttpMessageWriter,使其可以合适的用于Web应用。

(12)FormHttpMessageReader:解码HTML表单数据的解码器,比如request请求体中"application/x-www-form-urlencoded"类型的内容。

(13)FormHttpMessageWriter:编码MultiValueMap<String, String>成为HTML表单数据,如"application/x-www-form-urlencoded",到request请求体中。

(14)ResourceHttpMessageReader:解码Resource

(15)ResourceHttpMessageWriter:编码Resource。

(16)ServerSentEvent:表示一个使用Spring reactive web框架支持的服务器发送事件。服务器向浏览器推送信息,除了 WebSocket,还有就是Server-Sent Events。

(17)ServerSentEventHttpMessageReader:解码器,支持一连串的服务器发送事件、简单对象。

(18)ServerSentEventHttpMessageWriter:"text/event-stream" responses的编码器。

(二)http/codec/support

(1)BaseCodecConfigurer:实现CodecConfigurer接口的抽象类。

(2)BaseDefaultCodecs:CodecConfigurer.DefaultCodecs接口的默认实现。配置和自定义HTTP报文的默认的编解码器。

(3)DefaultClientCodecConfigurer:ClientCodecConfigurer接口的默认实现。

(4)DefaultServerCodecConfigurer:ServerCodecConfigurer接口的默认实现。

(5)ClientDefaultCodecsImpl:ClientCodecConfigurer.ClientDefaultCodecs接口的默认实现。

(6)ServerDefaultCodecsImpl:ServerCodecConfigurer.ServerDefaultCodecs接口的默认实现。

(三)http/codec/json

(1)Jackson2CodecSupport:提供支持Jackson 2.9编解码的方法的抽象基类。

(2)Jackson2Tokenizer:将一个任意大小、字节数组块的JSON stream转换成Flux<TokenBuffer>,其中每一个token buffer都是一个结构良好的JSON对象。

(3)AbstractJackson2Decoder:Jackson 2.9解码器的抽象基类。

(4)AbstractJackson2Encoder:为Jackson 2.9编码器提供了一些支持性方法的基类。

(5)Jackson2JsonDecoder:将字节流解码为JSON并使用Jackson 2.9转换为Object。

(6)Jackson2JsonEncoder:使用Jackson 2.9编码Json。

(7)Jackson2SmileDecoder:使用Jackson 2.9解码Smile。

(8)Jackson2SmileEncoder:使用Jackson 2.9编码Smile。

(四)http/codec/cbor

(1)Jackson2CborDecoder:使用Jackson解码Cbor。

(2)Jackson2CborEncoder:使用Jackson编码Cbor。

(五)http/codec/multipart

(1)Part:表示"multipart/form-data"数据的一个部分。

(2)FilePart:专指一个multipart request的上传文件部分。

(3)FormFieldPart:专指表单字段。

(4)MultipartHttpMessageReader:提供对于"multipart/form-data"类型的数据的解码支持。

(5)MultipartHttpMessageWriter:提供对于"multipart/form-data"类型的数据的编码支持。

(6)SynchronossPartHttpMessageReader:使用Synchronoss NIO Multipart库解码"multipart/form-data"类型的数据。

(六)http/codec/protobuf

(1)ProtobufCodecSupport:提供了Protobuf编解码一些支持性方法。

(2)ProtobufDecoder:使用Google Protocol Buffers来解码com.google.protobuf.Message的解码器。

(3)ProtobufEncoder:使用Google Protocol Buffers来编码com.google.protobuf.Message的编码器。

(4)ProtobufHttpMessageWriter:HttpMessageWriter接口的实现类,用于编码protobuf消息。

(七)http/codec/xml

(1)JaxbContextContainer:JAXBContext实例的句柄。JAXBContext 类提供到 JAXB API 的客户端入口点。它提供了管理实现 JAXB 绑定框架操作所需的 XML/Java 绑定信息的抽象,这些操作包括:解组、编组和验证。

(2)XmlEventDecoder:继承自AbstractDecoder,将一个DataBuffer流解码成一连串的XMLEvents。

(3)Jaxb2XmlDecoder:继承自AbstractDecoder,将包含XML元素的字节流解码成一连串的POJO。

(4)Jaxb2XmlEncoder:将一个单独的value值编码成包含XML元素的字节流。

本文参考了博客园、****部分文献。

拓展阅读:

Spring框架之beans源码完全解析(https://www.cnblogs.com/xxkj/p/13929565.html)

Spring框架之AOP源码完全解析(https://www.cnblogs.com/xxkj/p/14094203.html)

Spring框架之jms源码完全解析(https://www.cnblogs.com/xxkj/p/14137694.html)

博众家之所长,集群英之荟萃。遴选各IT领域精品雄文!

欢迎关注“IT架构精选”

Spring框架之spring-web http源码完全解析