不同Web主機上的Servlet之間數據對象的相互傳輸(轉)
為什么要這樣做
在目前所做的一個項目中,我們使用了兩臺獨立的數據庫服務器,出于安全方面的考慮,我們同時使用兩臺Web服務器分別操作這兩個數據庫。這就形成了這樣的一個結構圖:
由于數據庫服務器A和服務庫服務器B之間存在著數據的交換,而WEB服務器A并不能直接訪問數據庫服務器B,同理WEB服務器B也不能直接訪問數據庫服務器A。這樣的交換只能是通過兩臺Web主機來進行。而在絕大多數時候,我們涉及的是較大規模的數據交換,使用帶參數的格式顯然不能滿足我們的要求,這就涉及了不同Web主機上的Servlet之間數據對象的相互傳輸的問題。
使用通常的Application域或是Session域的javabean看上去不能滿足我們的要求,雖然我們相信會有很多更為完美的方案可以解決這個問題,但是我們今天想看看如何直接通過HTTP連接來完成這樣的傳輸。
首先對于我們的每一個獨立的應用來說,兩臺WEB服務器都會存在一個主次的關系,情況也許是這樣的:訪問者訪問WEB服務器A上的一個servlet A,而這個servlet A產生一個數據對象傳輸到WEB服務器B上的另一個servlet B,servlet B接收到這個數據對象后對其進行相應的處理,然后它可能還會生成另一個數據對象傳輸到servlet A中。這樣的過程看上去有點象一個遠程函數調用的概念。限于篇幅的限制,我們這里討論一種較為簡單的情況,test將passobject傳輸到test2,test2對passobject進行處理后將其傳回到test。
簡單示例的源碼
passobject.java
首先,我們需要在兩臺WEB主機上分別建立對passobject的定義,在兩臺主機上的定義應該是完全一樣,這樣的類定義和我們通常使用并沒有什么不同。只是這樣的類必須實現序列化,也就是要實現Serializable:
package test;
import java.io.*;
public class PassObject implements Serializable {
String PassValue1;
String PassValue2;
public void setNewPassObject()
{PassValue1="yzysynew";
PassValue2="new";
}
public void setOldPassObject()
{PassValue1="yzysyold";
}
}
test.java
在其中的一臺web主機上建立。除去加注釋的那幾行,這完全是一個通常意義上的用于顯示的servlet,不過那幾行的內容看上去也許會有點讓你眼花繚亂。這幾行將數據對象傳輸到了另一臺主機的test2中,并接收經過test2處理的數據對象。對于這里所涉及的一些不太常用的API,我們將會在最后一并說明。
package test;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.net.*;
public class Test extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{PassObject passobject = new PassObject();
passobject.setNewPassObject();
PrintWriter out = response.getWriter();
out.println(passobject.PassValue1);
out.println(passobject.PassValue2);
//創建一個新的URL實例url
URL url = new URL("http://141.56.16.8/examples/servlet/test.Test2");
//根據url建立連接
URLConnection con = url.openConnection();
//設置該連接可寫
con.setDoOutput(true);
//禁用cache
con.setUseCaches(false);
//取出輸出流
OutputStream outs=con.getOutputStream();
//將該輸出流轉換為對象輸出流
ObjectOutputStream objout = new ObjectOutputStream(outs);
//將要傳輸的對象寫入該對象輸出流中
objout.writeObject(passobject);
//取得返回的輸入流
InputStream in = con.getInputStream();
//將該輸入流定義為對象輸入流
ObjectInputStream objStream;
objStream = new ObjectInputStream(in);
//按指定類的格式讀取輸入流的內容
try {
passobject=(PassObject)objStream.readObject();
out.println(passobject.PassValue1);
out.println(passobject.PassValue2);
}
catch (java.lang.ClassNotFoundException ysy )
{
out.println("fail");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
test2.java
在其中的另一臺web主機上建立,用來接收test發送的數據對象,并對其進行處理后返回到test。
package test;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.net.*;
public class Test2 extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{//封裝用于返回的對象輸出流
ObjectOutputStream out = new ObjectOutputStream(response.getOutputStream());
//封裝用于接收的對象輸入流
ObjectInputStream in = new ObjectInputStream(request.getInputStream());
PassObject passobject=new PassObject();
//按指定類的格式讀取對象輸入流中的內容
try {
passobject=(PassObject)in.readObject();
}
catch (java.lang.ClassNotFoundException ysy )
{
}
//對接受到的數據對象進行處理
passobject.setOldPassObject();
//將處理后的數據對象返回到對象輸出流中
out.writeObject(passobject);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
程序中涉及的部分API的說明
java.net.URL
URL類表示了一個統一資源路徑。這樣的資源可能是一個文件或目錄,也可能是更為復雜的諸如數據庫的查詢或是搜索引擎。
在我們的程序中使用了URL的一種構造函數:
URL(String spec)
直接使用字符串作為構造函數的參數,這實際上是URL的眾多構造函數中最為簡單的一種。
此外,我們還用到了URL的openConnection()方法:
public URLConnection openConnection()
throws IOException
該方法返回了一個URLConnection對象。每次調用該方法時會開啟一個到指定URL的新的連接。
這里需要注意的是,調用該方法的結果是建立了一個連接,這與通常的頁面跳轉完全是兩回事。在更多的情況下,這里僅僅是建立了一個連接的通路,而并沒有實現任何其它的操作。
java.net.URLConnection
這是一個抽象類,是所有反映application和一個URL之前的通信的類的超類。這個類的實例可以用來對一個URL表示的資源進行讀寫。
在我們的程序中我們使用了這個類的如下方法:
getInputStream
public InputStream getInputStream()
throws IOException
返回從這個連接讀取的一個輸入流
getOutputStream
public OutputStream getOutputStream()
throws IOException
返回一個用于寫入這個連接的輸出流
setDoOutput
public void setDoOutput(boolean dooutput)
設置該連接是否可以寫入
setUseCaches
public void setUseCaches(boolean usecaches)
設置該連接是否使用cache
java.io.OutputStream
這是一個抽象類,是所有反映一個二進制輸出流的類的超類。一個這樣的輸出流可以對二進制數據進行輸出或發送。
java.io.ObjectOutputStream
該類用來向一個OutputStream寫入java的對象。這個對象可以使用ObjectInputStream進行讀取或再造。
只有實現java.io.Serializable接口的對象可以寫入該數據流中。
在我們的程序中還使用了該類的writeObject()方法:
public final void writeObject(Object obj)
throws IOException
將指定的對象寫入ObjectOutputStream。
java.io.InputStream
這是一個抽象類,是所有反映一個二進制輸入流的類的超類。
java.io.ObjectInputStream
一個ObjectInputStream對一個使用ObjectOutputStream寫入的對象進行解析。
在我們的程序中使用了該類的readObject()方法:
public final Object readObject()
throws OptionalDataException,
ClassNotFoundException,
IOException
從一個ObjectInputStream中讀取一個對象。
程序執行的結果
如果一切正常,訪問test.Test你應該可以看到這樣的結果:
yzysynew
new
yzysyold
new
其中yzysynew,new是對象原來的內容,而yzysyold,new所反映的那個對象已經是傳送到test2后經test2處理過的了。
在目前所做的一個項目中,我們使用了兩臺獨立的數據庫服務器,出于安全方面的考慮,我們同時使用兩臺Web服務器分別操作這兩個數據庫。這就形成了這樣的一個結構圖:

由于數據庫服務器A和服務庫服務器B之間存在著數據的交換,而WEB服務器A并不能直接訪問數據庫服務器B,同理WEB服務器B也不能直接訪問數據庫服務器A。這樣的交換只能是通過兩臺Web主機來進行。而在絕大多數時候,我們涉及的是較大規模的數據交換,使用帶參數的格式顯然不能滿足我們的要求,這就涉及了不同Web主機上的Servlet之間數據對象的相互傳輸的問題。
使用通常的Application域或是Session域的javabean看上去不能滿足我們的要求,雖然我們相信會有很多更為完美的方案可以解決這個問題,但是我們今天想看看如何直接通過HTTP連接來完成這樣的傳輸。
首先對于我們的每一個獨立的應用來說,兩臺WEB服務器都會存在一個主次的關系,情況也許是這樣的:訪問者訪問WEB服務器A上的一個servlet A,而這個servlet A產生一個數據對象傳輸到WEB服務器B上的另一個servlet B,servlet B接收到這個數據對象后對其進行相應的處理,然后它可能還會生成另一個數據對象傳輸到servlet A中。這樣的過程看上去有點象一個遠程函數調用的概念。限于篇幅的限制,我們這里討論一種較為簡單的情況,test將passobject傳輸到test2,test2對passobject進行處理后將其傳回到test。
簡單示例的源碼
passobject.java
首先,我們需要在兩臺WEB主機上分別建立對passobject的定義,在兩臺主機上的定義應該是完全一樣,這樣的類定義和我們通常使用并沒有什么不同。只是這樣的類必須實現序列化,也就是要實現Serializable:













test.java
在其中的一臺web主機上建立。除去加注釋的那幾行,這完全是一個通常意義上的用于顯示的servlet,不過那幾行的內容看上去也許會有點讓你眼花繚亂。這幾行將數據對象傳輸到了另一臺主機的test2中,并接收經過test2處理的數據對象。對于這里所涉及的一些不太常用的API,我們將會在最后一并說明。























































test2.java
在其中的另一臺web主機上建立,用來接收test發送的數據對象,并對其進行處理后返回到test。





































程序中涉及的部分API的說明
java.net.URL
URL類表示了一個統一資源路徑。這樣的資源可能是一個文件或目錄,也可能是更為復雜的諸如數據庫的查詢或是搜索引擎。
在我們的程序中使用了URL的一種構造函數:
URL(String spec)
直接使用字符串作為構造函數的參數,這實際上是URL的眾多構造函數中最為簡單的一種。
此外,我們還用到了URL的openConnection()方法:
public URLConnection openConnection()
throws IOException
該方法返回了一個URLConnection對象。每次調用該方法時會開啟一個到指定URL的新的連接。
這里需要注意的是,調用該方法的結果是建立了一個連接,這與通常的頁面跳轉完全是兩回事。在更多的情況下,這里僅僅是建立了一個連接的通路,而并沒有實現任何其它的操作。
java.net.URLConnection
這是一個抽象類,是所有反映application和一個URL之前的通信的類的超類。這個類的實例可以用來對一個URL表示的資源進行讀寫。
在我們的程序中我們使用了這個類的如下方法:
getInputStream
public InputStream getInputStream()
throws IOException
返回從這個連接讀取的一個輸入流
getOutputStream
public OutputStream getOutputStream()
throws IOException
返回一個用于寫入這個連接的輸出流
setDoOutput
public void setDoOutput(boolean dooutput)
設置該連接是否可以寫入
setUseCaches
public void setUseCaches(boolean usecaches)
設置該連接是否使用cache
java.io.OutputStream
這是一個抽象類,是所有反映一個二進制輸出流的類的超類。一個這樣的輸出流可以對二進制數據進行輸出或發送。
java.io.ObjectOutputStream
該類用來向一個OutputStream寫入java的對象。這個對象可以使用ObjectInputStream進行讀取或再造。
只有實現java.io.Serializable接口的對象可以寫入該數據流中。
在我們的程序中還使用了該類的writeObject()方法:
public final void writeObject(Object obj)
throws IOException
將指定的對象寫入ObjectOutputStream。
java.io.InputStream
這是一個抽象類,是所有反映一個二進制輸入流的類的超類。
java.io.ObjectInputStream
一個ObjectInputStream對一個使用ObjectOutputStream寫入的對象進行解析。
在我們的程序中使用了該類的readObject()方法:
public final Object readObject()
throws OptionalDataException,
ClassNotFoundException,
IOException
從一個ObjectInputStream中讀取一個對象。
程序執行的結果
如果一切正常,訪問test.Test你應該可以看到這樣的結果:
yzysynew
new
yzysyold
new
其中yzysynew,new是對象原來的內容,而yzysyold,new所反映的那個對象已經是傳送到test2后經test2處理過的了。
posted on 2008-03-13 15:53 都市淘沙者 閱讀(1110) 評論(1) 編輯 收藏 所屬分類: JSP/PHP