Spring中集成Hessian的问题

请下载附件查看·····

Spring中集成Hessian的问题:

主要解决的两个问题

第一个请求超时的问题,

第二个在调用Hessian接口异常捕获不到异常的问题

Spring版本:3.2.11

Hessian版本:3.1.3

HessianSpring中的使用

<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="图片_x0020_1" o:spid="_x0000_i1043" type="#_x0000_t75" style='width:415.5pt;height:58.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

HessianProxyFactoryBeanSpring的代理Hessian工厂类,为构建HessianProxyFactory提供对应的配置参数,通过继承链来实现参数的的注入。

 

HessianProxyFactory中有具体的参数可自行选择配置

UrlBasedRemoteAccessor 注入 serviceUrl

RemoteAccessor注入serviceInterface

HessianClientInterceptor 注入其他字段设置,如请求超时,读取内容超时,等

 

  private String _user;//用户名

  private String _password; //密码

  private String _basicAuth;//此致默认为空

  private boolean _isOverloadEnabled = false; //是否是重载方法(不推荐)

  private boolean _isHessian2Reply = false; //是否使用Hessian2.0协议

  private boolean _isHessian2Request = false;//是否使用Hessian2.0协议

  private boolean _isChunkedPost = false;// 设置Chunked编码方式发送请求

  private boolean _isDebug = false;//是否调试

  private long _readTimeout = -1;//读取内容超时设置

 

那么spring是如何创建HessianProxyFactory对象的呢?

HessianClientInterceptor类中

<!--[if gte vml 1]><v:shape id="图片_x0020_2" o:spid="_x0000_i1042" type="#_x0000_t75" style='width:415.5pt; height:60pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image003.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

<!--[if gte vml 1]><v:shape id="图片_x0020_3" o:spid="_x0000_i1041" type="#_x0000_t75" style='width:415.5pt; height:290.25pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image005.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

它是直接创建一个HessianProxyFactory实例,set注入的属性值然后利用该实例完成创建远程服务

主要调用方法是创建一个HessianProxy

<!--[if gte vml 1]><v:shape id="图片_x0020_4" o:spid="_x0000_i1040" type="#_x0000_t75" style='width:415.5pt; height:236.25pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image007.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

HessianProxy代码片段

<!--[if gte vml 1]><v:shape id="图片_x0020_5" o:spid="_x0000_i1039" type="#_x0000_t75" style='width:414.75pt; height:228.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image009.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

<!--[if gte vml 1]><v:shape id="图片_x0020_6" o:spid="_x0000_i1038" type="#_x0000_t75" style='width:415.5pt; height:343.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image011.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

<!--[if gte vml 1]><v:shape id="图片_x0020_8" o:spid="_x0000_i1037" type="#_x0000_t75" style='width:415.5pt; height:261pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image013.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

此处的FactoryHessianProxyFactory _factory;

<!--[if gte vml 1]><v:shape id="图片_x0020_9" o:spid="_x0000_i1036" type="#_x0000_t75" style='width:414.75pt; height:256.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image015.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

 

 

 

 

 

 

 

 

HessianProxyFactory类中的方法

<!--[if gte vml 1]><v:shape id="图片_x0020_10" o:spid="_x0000_i1035" type="#_x0000_t75" style='width:415.5pt; height:292.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image017.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

请求响应的主要调用方法就是以上代码片段

 

 

第一个请求超时的问题的解决方案,

<!--[if !supportLists]-->1.  <!--[endif]-->通过查看HessianProxyFactoryopenConnection(URL url)的方法可以看到在URLConnection实例对象中只有readTimeout(注意readTimeoutout是小写)属性,并且默认值是-1,也就是无限制。

<!--[if !supportLists]-->2.  <!--[endif]-->首先我们继承HessianProxyFactory并覆openConnection(URL url)方法写一个如图

<!--[if gte vml 1]><v:shape id="图片_x0020_12" o:spid="_x0000_i1034" type="#_x0000_t75" style='width:415.5pt;height:431.25pt; visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image019.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

3.继承SpringHessian代理Bean – HessianProxyFactoryBean如图

<!--[if gte vml 1]><v:shape id="图片_x0020_13" o:spid="_x0000_i1033" type="#_x0000_t75" style='width:415.5pt; height:351pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image021.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

然后在Spring中调用的配置是:

<!--[if gte vml 1]><v:shape id="图片_x0020_14" o:spid="_x0000_i1032" type="#_x0000_t75" style='width:415.5pt; height:88.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image023.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

参数说明:

此处列出主要参数,其中我们主要使用的参数是,其他参数默认值即可

serviceUrl – 请求地址

serviceInterface  -  接口类

overloadEnabled  - 是否支持重写(推荐否)

readTimeout  -  根据需求自行设定

connectTimeOut  - 根据需求自行设定

 

其中user,password,baseicAuthor是在请求协议中设置头信息,服务端会校验这个头信息(单在源码中没有发现,可能需要自行实现)例如像:conn.setRequestProperty("Content-Type", "x-application/hessian");

 

第二个在调用Hessian接口异常捕获不到异常的问题

异常信息例如:

<!--[if gte vml 1]><v:shape id="图片_x0020_15" o:spid="_x0000_i1031" type="#_x0000_t75" style='width:415.5pt; height:140.25pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image025.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

在服务端如果服务宕掉,或者接口版本不一致,或者在客户端抛出的异常,都可以被捕获到并且调用上层,并最终被catch,例如抛出的是一个HessianRuntimeException异常在

 

<!--[if gte vml 1]><v:shape id="图片_x0020_18" o:spid="_x0000_i1030" type="#_x0000_t75" style='width:415.5pt; height:267.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image027.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

Hessian的在远程调用的时候也是采用JDK动态代理方法,可以通过

public class HessianProxy implements InvocationHandler源码中看出

 

在异常体系中ThroableExceptionError的子类,RunTimeExceptionException的子类。也就是说异常链中异常只能捕获异常本身和以及继承了该异常的子类抛出的异常,如果捕获不了就抛给上层处理。

 

在看源码过程中在执行方法中直接抛出的是Throwable,对我们来说调用Hessian服务端接口有不可预知的异常或者错误,所以我们直接使用Throwable来捕获异常和错误。

例如:

<!--[if gte vml 1]><v:shape id="图片_x0020_19" o:spid="_x0000_i1029" type="#_x0000_t75" style='width:415.5pt; height:193.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image029.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

Hessian服务端代码浅析

<!--[if !supportLists]-->1.       <!--[endif]-->Spring配置如下:

<!--[if gte vml 1]><v:shape id="图片_x0020_20" o:spid="_x0000_i1028" type="#_x0000_t75" style='width:414.75pt;height:61.5pt; visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image031.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

从类HessianServiceExporter可以看出Hessian只接收Post请求

<!--[if gte vml 1]><v:shape id="图片_x0020_21" o:spid="_x0000_i1027" type="#_x0000_t75" style='width:415.5pt; height:196.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image033.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

通过继承链实现属性的注入:

HessianExporter中可以注入: debug调试客户端请求参数

RemoteExporter中可以注入:service  serviceInterface

服务端主要是通过对请求参数的反序列化和对返回结果的反序列化,通过

 

HessianServiceExporter中的入口方法

<!--[if gte vml 1]><v:shape id="图片_x0020_23" o:spid="_x0000_i1026" type="#_x0000_t75" style='width:415.5pt; height:145.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image035.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

调用以下方法来实现

<!--[if gte vml 1]><v:shape id="图片_x0020_22" o:spid="_x0000_i1025" type="#_x0000_t75" style='width:414.75pt; height:216.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\134891\AppData\Local\Temp\msohtmlclip1\01\clip_image037.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->

 

猜你喜欢

转载自wo-niu.iteye.com/blog/2200720