當然,你也許跟我一樣,碰到以下RefuseConnection的問題:
java.rmi.ConnectException: Connection refused to host: 146.222.94.55; nested exception is:
這個在我重啓server端的程序以後,client端執行遠程訪問時產生的。
排查原因:
1. 有可能是client端對訪問失敗的歷史,具有牴觸情緒,一旦訪問失敗,第二次嘗試就不行了。
一位老外,跟我遇到同樣的問題:
http://stackoverflow.com/questions/1477121/reconnect-rmi-client-after-server-restart
I have an RMI server and a desktop RMI client. When I restart the server, I get errors in the client. Is it possible to restart the RMI connection without restarting the client?
網友回答:When the server is terminated, you will receive a ConnectException. After that you can just use Naming.lookup to get a new server object.
我想JDK1.5以後,這個naming的方法,我已經不適用了,拋棄。
網友回答:用Spring可以很好地解決這個問題。
If you're using Spring (namely RmiProxyFactoryBean), you can simply set the property refreshStubOnConnectFailure to true and the bean will survive a restart of the server.
<property name="refreshStubOnConnectFailure" value="true" />
沒有使用spring,所以這個對我來說,沒有什麼意義
2. 針對程序本身進行debug,提出問題,爲什麼重啓會產生問題呢?
百思不得其解,後來發現,是單例模式導致的。
這個註冊服務器(getRegister)的過程,是在單例模式的類中執行的。第一次註冊後,儲存的靜態變量
(stub對象)就沒有被釋放過。所以,重啓server端程序以後,執行servlet,還是沒有重新註冊,從而導致錯誤。
正確的解決方法是,在單例模式的類中,要增加一個釋放舊的stub對象的方法,在connection發生錯誤以後就可以調用。具體實現如下:
- private static DataServerInterface dataServer=null;
- private DataServer(){
- }
- public static void clearOldConnection(){
- dataServer=null;
- }
當然,在servlet調用的過程中,要記得捕獲異常,從而釋放stub對象:
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- List<Weibo> weibos = null;
- try{
- weibos = DataServer.getRmiService().getWeibos();
- for(Weibo item:weibos){
- System.out.println(item.getContent());
- response.getWriter().write(""+item.getContent());
- }
- }catch(Exception e){
- System.out.println("Connection error when calling dataserver");
- DataServer.clearOldConnection();
- System.out.println("Due to exception,old connection has been cleaned");
- }
- }