上一篇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配置設置時間即可。