目前几套系统中主要使用的hessian进行远程调用webservice服务的有hessian的HessianProxyFactory(com.caucho.hessian.client.HessianProxyFactory)和spring的HessianProxyFactoryBean(org.springframework.remoting.caucho.HessianProxyFactoryBean).
1.HessianProxyFactory
查看HessianProxyFactory源码后发现,hessian在创建http请求连接webservice服务并没有对连接超时进行相关的参数设置,所以当网络出现问题就会造成整个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连接的时候通过设置连接超时时间来解决因网络问题阻塞程序继续的问题
public class MyHessianProxyFactory extends HessianProxyFactory {
private int connectTimeOut = 10000;
private int readTimeOut = 10000;
public int getConnectTimeOut() {
return connectTimeOut;
}
public void setConnectTimeOut(int connectTimeOut) {
this.connectTimeOut = connectTimeOut;
}
public int getReadTimeOut() {
return readTimeOut;
}
public void setReadTimeOut(int readTimeOut) {
this.readTimeOut = readTimeOut;
}
protected URLConnection openConnection(URL url) throws IOException {
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
if (this.connectTimeOut > 0) {
conn.setConnectTimeout(this.connectTimeOut);
}
if (this.readTimeOut > 0) {
conn.setReadTimeout(this.readTimeOut);
}
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;
}
}
2.HessianProxyFactoryBean
查看spring的HessianProxyFactoryBean源码发现,它在封装hessian是直接创建一个HessianProxyFactory实例,然后利用该实例完成创建远程服务
public class HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean {
private Object serviceProxy;
public void afterPropertiesSet() {
super.afterPropertiesSet();
this.serviceProxy = ProxyFactory.getProxy(getServiceInterface(), this);
}
public Object getObject() {
return this.serviceProxy;
}
public Class getObjectType() {
return getServiceInterface();
}
public boolean isSingleton() {
return true;
}
}
所以对此的解决方法与上面差不多,继承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();
}
}