上一篇Hessian解析及应用(整合Spring)中,学习了Hessian的使用及原理后,总觉得有个“疙瘩” 遗留在心里......那就是超时时间的设置,这样的远程调用,难免会有超时的情况发生。
今日想起,遂Google之......然后看到了这位仁兄的文章http://www.blogjava.net/dongbule/archive/2010/12/16/340894.html (解决hessian远程调用连接超时问题),及网友评论,总结如下:
HessianProxyFactory对连接处理的源码
protected URLConnection openConnection(URL url)
throws IOException
{
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
if (_readTimeout > 0) {
try {
conn.setReadTimeout((int) _readTimeout);
} catch (Throwable e) {
}
}
conn.setRequestProperty("Content-Type", "x-application/hessian");
if (_basicAuth != null)
conn.setRequestProperty("Authorization", _basicAuth);
else if (_user != null && _password != null) {
_basicAuth = "Basic " + base64(_user + ":" + _password);
conn.setRequestProperty("Authorization", _basicAuth);
}
return conn;
}
所以我们针对此逻辑继承并重写该openConnection方法,在创建http连接的时候通过设置连接超时时间来解决因网络问题阻塞程序继续的问题
代码来自 Xuzhengsong
protected URLConnection openConnection(URL url) throws IOException {
URLConnection conn = super.openConnection(url);
if (this.connectTimeOut > 0) {
conn.setConnectTimeout(this.connectTimeOut);
}
retrun conn;
}
查看spring的HessianProxyFactoryBean源码发现(原码分析见Hessian解析及应用(整合Spring)),它在封装hessian是直接创建一个HessianProxyFactory实例,然后利用该实例完成创建远程服务,所以对此的解决方法与上面差不多,继承HessianProxyFactoryBean然后加入相应的连接超时和读取超时的变量,重写afterPropertiesSet方法,并且同时完成上面第一步对HessianProxyFactory的改造,这样就能保证连接远程webserver服务器时不会因为网络原因阻塞程序的执行。
public class MyHessianProxyFactoryBean extends HessianProxyFactoryBean { private MyHessianProxyFactory proxyFactory = new MyHessianProxyFactory(); private int readTimeOut = 10000; private int connectTimeOut = 10000; public int getReadTimeOut() { return readTimeOut; } public void setReadTimeOut(int readTimeOut) { this.readTimeOut = readTimeOut; } public int getConnectTimeOut() { return connectTimeOut; } public void setConnectTimeOut(int connectTimeOut) { this.connectTimeOut = connectTimeOut; } public void afterPropertiesSet() { proxyFactory.setReadTimeout(readTimeOut); proxyFactory.setConnectTimeOut(connectTimeOut); setProxyFactory(proxyFactory); super.afterPropertiesSet(); } }
---------------------------------------------------------------------分割线-----------------------------------------------------------------------------------
Google了以上内容,然后不断的对照Hessian原码分析,始终没有在HessianProxyFactory中发现openConnection方法,然后就想到了版本问题,本人使用hessian-4.0.7,在版本3的HessianProxyFactory中看到了openConnection方法。
然后看了4中相关的代码,在HessianProxyFactory看到以下代码(至于怎么到createHessianConnectionFactory()方法中的,还是看Hessian解析及应用(整合Spring)吧)
protected HessianConnectionFactory createHessianConnectionFactory()
{
String className
= System.getProperty(HessianConnectionFactory.class.getName());
HessianConnectionFactory factory = null;
try {
if (className != null) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class<?> cl = Class.forName(className, false, loader);
factory = (HessianConnectionFactory) cl.newInstance();
return factory;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return new HessianURLConnectionFactory();
}
进入HessianURLConnectionFactory类,看到里面的open方法
/**
* Opens a new or recycled connection to the HTTP server.
*/
public HessianConnection open(URL url)
throws IOException
{
if (log.isLoggable(Level.FINER))
log.finer(this + " open(" + url + ")");
URLConnection conn = url.openConnection();
// HttpURLConnection httpConn = (HttpURLConnection) conn;
// httpConn.setRequestMethod("POST");
// conn.setDoInput(true);
long connectTimeout = _proxyFactory.getConnectTimeout();
if (connectTimeout >= 0)
conn.setConnectTimeout((int) connectTimeout);
conn.setDoOutput(true);
long readTimeout = _proxyFactory.getReadTimeout();
if (readTimeout > 0) {
try {
conn.setReadTimeout((int) readTimeout);
} catch (Throwable e) {
}
}
可见hessian4对超时时间已经做了改进,所以使用时只需要通过Spring设置超时时间即可。
超时时间设置setConnectTimeout方法在HessianProxyFactory中,Spring的HessianClientInterceptor是它的子类并包含一个HessianProxyFactory实例,所以可以在HessianClientInterceptor中提供一个setConnectionTimeout方法:
public void setConnectTimeout(long timeout) {
this.proxyFactory.setConnectTimeout(timeout);
}
并在Spring配置设置时间即可。