深入剖析Spring Web源码(十) - 处理器映射,处理器适配器以及处理器的实现 - 基于HTTP请求处理器流程的实现

 

 

1.1.1.1             基于 HTTP 请求处理器流程的实现

这一节,我们将分析 Spring Web MVC 中的另外一个流程,它是用来支持基于 HTTP 协议的远程调用的流程。它并不是应用到一个简单的 HTTP 请求,它使用 Servlet 通过 HTTP 协议导出一个服务,服务的客户端可以通过 HTTP 协议使用和调用此服务。 Spring Web MVC 支持基于 HTTP 协议的三个类型的远程调用,基于 Burlap 的远程调用 , 基于 Hessian 的远程调用和基于序列化的远程调用。这里我们只分析基于序列化的远程调用,在后面小节中我们将分析所有远程调用流程的架构实现。

 

既然这是一个远程调用流程的实现,那么必然存在客户端和服务器端的实现,客户端是通过一个工厂 Bean 的实现导出服务器接口的代理,代理的实现把对方法的调用封装成远程调用对象并且进行序列化,通过配置的 HTTP URL 把序列化的远程调用对象通过 HTTP 请求体传入到服务器,服务器解析序列化的远程调用对象,然后通过反射调用远程调用对象里包含的方法,最后发送返回值到客户端。如下流程图所示,

 

图表 4 23

 

首先我们深入分析基于 HTTP 请求处理器流程的远程调用的客户端的实现体系结构。如下类图所示,

 

图表 4 24

 

客户端的实现是通过 AOP 代理拦截方法调用,然后,将传入的方法参数和正在调用的方法封装到远程调用对象并且序列化为字节流。最后,通过 HTTP 调用器请求执行器写入到远程主机的 HTTP 服务中的。下面我们根据流程的先后顺序对实现代码进行分析,如下代码注释,

 

当在客户端的 Spring 环境中配置一个 HTTP 服务,首先我们需要声明一个 HTTP 唤起器代理工厂 Bean(HttpInvokerProxyFactoryBean) ,然后指定需要代理的接口类和服务器端服务的 URL 。如下 Spring 配置文件所示,

 

 

HTTP 唤起器代理工厂 Bean 实现了工厂 Bean 接口,当它被初始化后进行 Bean 连接的时候,它会提供一个代理对象。如下代码注释,

 

 

产生了代理对象后,客户端会根据业务需要调用代理对象的服务方法。当调用任何方法的时候,代理机制会统一的调用到超类 HTTP 唤起器客户拦截器 (HttpInvokerClientInterceptor) 中对方法拦截器接口 (MethodInterceptor) 中的 invoke 方法的是实现。如下代码所示,

 

 

我们看到拦截器方法除了实现对远程 HTTP 服务的调用外,还对返回结果进行了处理。如果在调用过程中产生任何连接异常,结果解析异常等,则直接翻译这些异常并且抛出。然后,有些情况下,一个调用在服务器端产生了异常,异常信息通过返回的调用结果返回给客户端,这样客户端需要解析这些异常,并且重现他们。

 

我们也理解,对远程 HTTP 服务的调用是通过 HTTP 调用器请求执行器实现的。它将远程调用序列化成对象流后,通过 HTTP 连接类的支持,写入到远程服务。当远程服务处理这个请求后,返回了远程调用结果对象,并且通过反序列化解析远程调用结果对象。如下代码所示,

 

 

程序分析到这里,我们理解所有远程调用的处理过程是通过 HTTP 调用器请求执行器实现的。 HTTP 调用器请求执行器并不是一个单一的实现,它是一个接口,并且有两个常用的实现,一个使用 JDK 自带的 HTTP 客户端进行通讯,而另外一个使用 Apache Commons HTTP 客户端,如下类图所示,

 

图表 4 25

 

为了使我们的分析简单明白,我们这里仅仅分析基于 JDK 自带的 HTTP 客户端进行通讯的实现。首先,我们分析一下如下抽象 HTTP 唤起器请求执行器( AbstractHttpInvokerRequestExecutor )的实现。如下代码注释,

 

 

如此可见,对于一个远程调用抽象 HTTP 唤起器请求执行器实现了整个流程框架,但是留下了一个抽象方法,这个方法是提供给子类使用不同的方式与 HTTP 远程服务通信的。下面我们分析简单 HTTP 唤起器请求执行器( SimpleHttpInvokerRequestExecutor )是如何通过 JDK 自带的 HTTP 客户端来完成这个任务的。如下代码所示,

 

 

由此可见,简单 HTTP 唤起器请求执行器通过 JDK 自带的 URL 连接类实现了远程调用所需要 HTTP 通信的流程。这个流程支持 HTTP 请求体的压缩,并且能够使用地域信息进行一定程度的客户化。

 

代码分析到这里,我们理解一个远程调用( RemoteInvocation )对象写入了 HTTP 服务中后,服务器就会返回一个远程调用结果( RemoteInvocationResult )对象。下面我们分析服务器端是如何实现这个过程的。如下类图所示,

 

图表 4 26

 

服务器端对基于 HTTP 请求处理器流程的实现仍然是建立在 Spring Web MVC 的实现架构中的。它和基于简单控制器流程的实现和基于注解控制器流程的实现非常相似,同样有处理器映射,处理器适配器和处理器的实现,但是唯一不同的是它并没有特殊的处理器映射的实现,因为客户端是通过配置的 URL 查找和调用服务器端的服务的,所以简单基于简单控制器流程的实现中的 Bean URL 处理器映射在这里可以被完全重用。如下流程图所示,

 

图表 4 27

 

下面我们根据上图中流程的先后顺序分析它的实现。首先,派遣器 Servlet 接收到一个包含有远程调用序列化的二进制流的 HTTP 请求,它会使用配置的处理器映射查找能够处理当前 HTTP 请求的处理器。通常情况下, Bean URL 处理器映射会返回配置的 HTTP 调用器服务导出器 (HttpInvokerServiceExporter) 。如下配置代码所示,

 

 

 

Bean URL 处理器映射会发现这个 Bean 是一个处理器 Bean, 然后使用 Bean 作为 URL 注册此处理器。客户端 HTTP 请求发送到这个 URL, 作为总控制器的派遣器 Servlet 要求 Bean URL 处理器映射解析当前请求所需要的处理器,于是返回配置的 HTTP 调用器服务导出器。

 

既然 HTTP 调用器服务导出器实现了 HTTP 请求处理器接口 (HttpRequestHandler) HTTP 请求处理器适配器 (HttpRequestHandlerAdapter) 支持这个类型的处理器,所以,调用的控制流通过 HTTP 请求处理器适配器传递给 HTTP 调用器服务导出器。如下代码注释,

 

 

程序分析到这里,我们看到包含有远程调用序列化的二进制流的 HTTP 请求传递给 HTTP 调用器服务导出器,它将从序列化的二进制流中解析远程调用对象,进而解析方法调用对象,最后使用反射调用配置的服务中相应的方法,返回结果给客户端。如下代码所示,

 

 

上述方法中可以看到实现的总体流程,这个流程分为三个步骤,一个步骤是读取远程调用对象,第二个步骤是调用相关的服务方法,第三个步骤则是写入返回的结果。

 

第一个步骤,读取远程调用对象代码注释如下,

 

 

第二个步骤,调用相关的服务方法代码注释如下所示,

 

 

第三个步骤,写入返回的结果的代码注释如下所示,

 

 

如上分析,我们知道服务端的实现是讲客户端传递过来的远程调用的序列化对象进行反序列化,根据远程调用对象信息调用业务逻辑方法,最后同样以序列化的方法将调用结果传递回客户端。

 

事实上,还有另外一种配置方法配置基于 HTTP 请求处理器流程的实现方式。这种方法不需要任何的处理器映射和处理器适配器的实现,而是使用特殊的 HTTP 请求处理器 Servlet HttpRequestHandlerServlet )。这个 Servlet 会将 HTTP 请求直接发送给相应的 HTTP 调用器服务导出器进行处理。如下图所示,

 

图表 4 28

 

如下代码所示,

 

 

根据上面的这个简单 Servlet 的实现,我们可以这样配置我们的远程调用导出器。如下代码所示,

 

跟环境

 

 

 

web.xml

 

 

 

我们可以看到这种实现方法涉及组件会更少,不需要处理器映射和处理器适配器的参与,直接实现了 Servlet 到处理器适配器的调用,相对于第一种方法而言可以称为是一个捷径。但是它需要单独配置一个 Servlet ,除此之外, HTTP 请求处理器 Servlet 仅仅实现了 HTTP Servlet, 它并不拥有专用的子环境,所以需要在根环境声明服务导出 Bean

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值