程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> J2EE企業應用之Applet和Servlet的通信

J2EE企業應用之Applet和Servlet的通信

編輯:關於JAVA

在今天的多層結構的web應用程序的設計中,我們可以同時使用Java applet和Servlet。Applet為建立功能強大的動態界面提供了便利的機制,Servlet為web服務器或者其他應用服務器處理請求提供了高效率的手段。

Sun公司的應用程序模型描述了在Java2平台下開發企業級的Java應用的最好的規范。一種被推薦的規范是:在前端使用Applet、HTML和JSP,在後端使用Enterprise JavaBeans支持的Servlet及其他成分。

這種體系結構的關鍵是在客戶端的Applet和在服務器說?ervlet之間的通信。但是由於Applet受浏覽器安全模式的限制,在一個Applet中存取數據和信息並不想看上去的那麼簡單。在這篇文章中,我們將解釋在Applet-Servlet結構中開發者所面對的限制,並探討幾個不同的可以在Applet和Servlet之間轉輸數據的通信策略。

如果你已經熟悉Applet和Servlet,這肯定會對你閱讀本文有幫助,如果你還不是那麼熟悉,那也沒關系,我們會簡要地介紹它們。

APPLET和SERVLET的簡介

Applet Java applets實際上是運行在web頁面上的Java程序。它是一個繼承於java.applet.applet的Java類,它通過引用被嵌入到HTML頁面中去,就象一個圖像一樣。Applet和HTML的組合,可以建立功能更為強大的動態界面。

對於一些只用來滾動正文和播放動畫的Applet,我們可以在一個企業級的應用程序中利用它來顯示和處理來自服務器上的資源的數據。例如,一個Applet可以用來浏覽和修改數據庫中的記錄或者控制運行在服務器上的其他應用程序。

Java applet除了可以使用它自己定義的類文件外,還可以使用其他的類,不管這些類是獨立存在的還是被打包成了一個JAR文件。Applet和它的類文件通過標准的HTTP請求進行分布,所以Applet可以越過web頁面數據所在的平台的防火牆進行發送。

除非是涉及到保持應用程序完整性的問題,Applet總會在每次用戶重新訪問web主機時自動刷新並會在客戶端保留一段時間。

我們得感謝Java操作系統的平台無關性,這才使得Applet可以運行在任何擁有Java虛擬機(JVM)的浏覽器上。Sun公司的Java插件甚至可以使用可以利用最新版本的JVM編制頁面,而不用擔心受你的用戶的浏覽器上的JVM的版本的限制。

因為Applet是Java平台的擴展,所以在你建立用Applet建立你的web應用程序的界面時,你可以重用已存在的Java組件。

正如我們在下面的例子中可以看到的那樣,你可以在你的Applet的組件中使用復雜的Java對象來開發本來由服務器端應用程序完成的工作。事實上,你可以編寫這樣的Java代碼,它既可以在Applet上執行,也可以在應用程序內執行。

Applet具有所有傳統的Java應用程序的功能,包括使用Sun公司的JFC/Swing組件。Applets也可以用來制作圖形以及應用程序中的用戶界面(盡管有些輔助的窗口會被標志為“Warning, Java Applet Window”)。

但是不管他們有多麼相似,在應用程序和Applet之間還是一些關鍵性的差別的。例如,我們不得不考慮到我們的Applet是受到安全模式的限制的。

Applet的安全約束

Applet代碼來自於web主機並在最終用戶的機器的浏覽器中運行。有害的含有病毒的Applet可能會造成破壞性的效果,為了防止這樣的Applet,Applet受到安全方面的約束,那就是Applet只可以與提供這個Applet的主機進行通信,而且Applet不能操作最終用戶的機器。

它們不能讀寫該用戶的文件系統,不能執行上面的程序,也不能檢查一些敏感的環境參數。(事實上,我們有一種方法可以回避這種限制,那就是開發者可以利用數字簽名的技術對Applet進行標志,這將會詢問用戶是否可以給予Applet某種特殊的待遇。

但是這已經超出我們這篇文章中所討論的范圍了。)此外,Applet不能建立或接受外來的socket連接。所謂外來的是指這個連接超出了提供這個Applet類文件的主機(不是提供引用這個Applet的HTML所在的主機)。

因為這個安全性的限制,我們與Applet的通信必須采用一種特殊的策略。通信的唯一的途徑就是在提供Applet的主機和提供相應的HTML的主機之前的網絡連接。

Servlets Java servlet是服務器端的組件,它和CGI有很多相似。它可以處理web請求,並返回數據或HTML。Servlet可以訪問數據庫,進行計算,並和Enterprise JavaBean這樣的組件進行通信。

與CGI程序不同的是,Servlet是持久有效的,也就是說,它只要被示例一次就可以不斷地處理請求(這些請求很可能是同時發生的)。因此,Servlet比CGI來得更高效。

Servlet運行在一個Servlet引擎中,通常是在一個web服務器或應用程序服務器上。Netscape Enterprise Server 4.0和Netscape Application Server都支持最新版本的Java servlet規范。

和Applet不同,Servlet不受安全約束的限制。因為Servlet是完全在服務器上運行的,它具有所有操作系統所允許的性能。

Servlet可以用來很方便地建立在Applet和Web浏覽器這樣的客戶端和企業應用程序的核心之間的連接。對於客戶端來說,向Servlet發出的請求與其他web請求並沒有任何不同。客戶端通過一個URL來接受返回的信息,正如我們看到的那樣,返回的信息並不一定只能是HTML,實際上我們可以通過HTML協議發送和接受任何類型的數據。

構造方法

一個企業級的應用程序可以有幾種方法來構造Applet和Servlet的使用。我將向大家介紹三種不同的構造方法,並對它們的優缺點進行比較。

第一種方法實際上只使用了Applet而沒有使用Servlet,盡管Applet受到它們的安全模式的限制,但是Applet還是可以使用象JDBC、RMI這樣的協議來訪問象數據庫、LDAP目錄和Enterprise JavaBeans組件這樣的後端信息。

這種方法雖然看上去很簡單,但是這並不是一個好的方法,它會帶來很多的問題。首先, 這種安排要求你將所有的訪問信息直接嵌入到你的Applet代碼中。數據庫用戶名、口令、服務器標識,所有的這一切都必須包含在你的Applet代碼中,這樣最終用戶就有可能從類文件中搜集到這些信息。

此外,數據庫或任何其他你訪問的系統都必須在提供Applet的同一台服務器上。這意味著你的服務器將不得不承擔雙重的負擔,它既是一個web服務器,也是一個數據庫服務器。

典型的情況是,你的後端資源可能受到防火牆的保護,但是在這種情況下,這是不可能的,因為運行在客戶端上的Applet必須直接訪問你的機器。最後,使用這種方法,你想使用web服務器群集,如果不是不可能的,至少也是很困難的。

好一點的方法是將與後端資源通信的事務封裝到Servlet中,而Applet僅僅用來處理前端的工作。在這種構造方法中,正如我們在圖2中所示的那樣,Servlet克服了Applet固有的安全約束,並用來控制Applet訪問企業信息系統和事務邏輯。

當Servlet接受到一個請求時,它會在後端數據庫中查詢信息、執行計算、處理對代表Applet的信息的獲取並作用於來自Applet的信息。這種方法的一大進步是Applet/Servlet對可以分布在一個後端web服務器的群集上,所有與某一共享的數據庫的通信都存在於後端。

此外,使用Servlet的設計有助於設計的模塊化、抽象應用程序的後端處理商業邏輯並提高設計的靈活性。

如果你是圍繞Enterprise JavaBeans構建你的應用程序,Servlet就成了中間件。EJB組件可以更加有助於將商業邏輯從Servlet中分離出來,並將其更加抽象。

在這種情況下,一個Applet與它的Servlet通信,Servlet再與EJB組件通信。在應用程序構建中引入由EJB組件、Servlet和前端的applet/HTML這樣的層次結構,可以給我們提供最大限度的彈性和性能。盡管這樣做你必須附出復雜化和費用的代價。

通信策略

如果你使用了這樣的構造:在前端使用Applet,在後端使用Servlet,那麼你將需要執行Applet和Servlet的通信。因為Applet受浏覽器的安全模式的限制,我們在對一個Applet存取數據和信息時並沒有太多的選擇。

正如我們在前面提到的,我們不能讀取客戶端的文件系統、不能運行客戶端的程序,由於Applet不是在服務器上運行的,我們也不能訪問服務器上的文件系統。我們只能建立到運行在我們的主機上的服務的網絡連接。

另外,不要忘記應用程序是在一個公開的Internet上發布的,防火牆可能會限制通過HTTP到Servlet或其它web-server模塊的會話。事實上,因為Applet本身就是在網絡上通過HTTP發布的,所以我們必須准確把握通信的策略。

假定在客戶端的Applet和服務器端的Servlet之間的網絡連接是我們可以使用的唯一的通信路徑,我們可以有幾種方法交換信息。正如你知道的,文字流可以由服務器通過HTTP發放。

但是你可能不知道Java對象出可以用這種方式發放。我們將詳細地介紹HTTP文字流和HTTP對象流的使用。另外,我們將簡單地介紹通過Socket進行通信的方法。

Applet與Servlet交換信息的最簡單地方法就是通過HTTP文字流。Java的URL和URLConnection類型使得從一個URL讀取數據變得很容易,你可以不用擔心Socket和其它有關網絡工作的通常的復雜問題。我們所需要的只是一個服務器端的組件,這個組件應該可以通過URL發放信息。這就是我們在這兒使用Servlet的原因。

作為一個例子,我們想要監控服務器的JVM所能使用的內存的總數,並在一個Applet中用一個簡單的儀表顯示它。首先我們需要開發一個Servlet,當通過它的URL訪問這個Servlet時可以返回我們所需要繪制儀表的信息。這個Servlet的源代碼如清單1所示。

清單1

import javax.servlet.*;
import javax.servlet.http.*;
public class ShowMemservlet
extends Httpservlet
{
public void doGet(HttpservletRequest
req, HttpservletResponse res)
throws servletException, IOException
{
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
Runtime rt = Runtime.getRuntime();
out.println(rt.freeMemory());
out.println(rt.totalMemory());
}
}

這個非常簡單的Servlet會響應一個GET請求(直接通過浏覽器或者是象我們在下面將看到的那樣通過我們的Applet),並返回兩行文字。第一行顯示了服務器的JVM的剩余的自由空間,第二行顯示了JVM可用的全部空間(包括已使用的空間)。

要建立我們的Applet中的儀表,我們只需要建立一個到這個Servlet的連接,將它的InputStream封裝到一個DataInputStream中,讀出這兩個參數,將其轉換成數字,並更新我們的儀表。

我們可以讓我們的Applet執行Runnable接口並在其自己的線程中運行。每隔一秒鐘,我們可以運行一個方法來更新我們的儀表。refresh()方法的代碼如清單2所示。

清單2

private void refresh()
throws MalformedURLException,
IOException
{
URL url = new URL(getCodeBase(),
"/servlet/ShowMemServlet");
URLConnection con = url.openConnection();
con.setUseCaches(false);
InputStream in = con.getInputStream();
DataInputStream textStream;
textStream = new DataInputStream(in);
String line1 = textStream.readLine();
String line2 = textStream.readLine();
double freeMem = Double.parseDouble(line1);
double totalMem = Double.parseDouble(line2);
int usedMem = totalMem - freeMem;
int percentUsed =
(int) 100 *(usedMem / totalMem);
meter.setLength(percentUsed);
}

正如你看到的,HTTP文字流的使用相當簡單而且直接。Applet建立到Servlet的連接,讀取它返回的兩行信息並對其進行適當的處理。

使用簡單的文字流來交換數據有一個主要的弱點,那就是Applet並不直接理解數據的信息,而是要將其轉換成一個有用的格式。在我們的例子中,將字符串轉換成數字還不算太復雜,但是當我們試圖處理一個更復雜的數據和對象時,轉換的工作會很快變得無法控制。事實上,在下面我們可以看到我們一種簡單的方法來處理這些復雜的數據。

HTTP對象流

你也許還沒有意識到HTTP連接也可以用來傳輸二進制的數據,就象傳輸文本數據一樣,但是事實上每次你從一個web看到圖象時或者是下載.zip文件時都在使用這個功能。

我們可以利用這個功能並結合被稱之為“對象序列”的技術從Servlet向Applet傳輸完整的Java對象。復雜的數據可以很容易地被傳輸,你不需要做任何解析和解釋。

對象序列允許我們將對象封裝到二進制數據流,它可以到達一個OutputStream可以到達的任何地方:磁盤、屏幕或者是在我們的例子中,通過一個HTTP連接到達一個Applet。

對象序列是JVM1.1和更高的版本才支持的功能,所以有一些老版本的浏覽器不支持這一功能。但是Sun公司的Java插件幾乎可以對所有的浏覽器進行升級以支持最終版本的Java,這樣它就可以支持對象序列。

使用HTTP對象流和使用HTTP文字流的方法幾乎一樣。我們建立一個到我們的web主機上的Servlet的URL連接並讀取其返回的數據。只不過我們不再是將InputStream封裝到DataInputStream中,而是將其封裝到ObjectInputStream中。我們可以按照適當的類型讀取其中的對象。

清單3顯示了我們用來交換一個對象的一段代碼,這個對象用來從Servlet獲得有關書目的信息(包括作者、題目、價格和其它信息)。你會注意到在這裡我們用ObjectOutputStream取代了清單1中的PrintWriter,其基本概念是相同的。

清單3

public void doGet(HttpservletRequest req,
HttpservletResponse res)
throws servletException, IOException
{
OutputStream out;
ObjectOutputStream objStream;
out = res.getOutputStream();
objStream = new ObjectOutputStream(out);
Album album = fetchNextAlbum();
out.writeObject(album);
}

這個Servlet會生成書目對象的序列化版本,它可從它的fetchNextAlbum()方法作為一個數據流被接收。如果你通過一個web浏覽器來訪問這個Servlet,你會看到一堆垃圾,這是因為目前你只能處理文本而不能處理二進制數據的對象序列。

請注意這個對象必須執行Serializable接口以使其序列化。此外,任何引用這個對象的其他對象也必須執行Serializable接口。

在Applet端,每當用戶單擊Applet的Next按鈕時,我們可以使用方法getNextAlbum()(程序如清單4所示)來從服務器獲得書目對象。Applet將查詢這個對象並顯示其中的數據。

清單4

private Album getNextAlbum()
throws MalformedURLException,
IOException
{
URL url = new URL(getCodeBase(),
"/servlet/Albumservlet");
URLConnection con = url.openConnection();
con.setUseCaches(false);
InputStream in = con.getInputStream();
ObjectInputStream objStream;
objStream = new ObjectInputStream(in);
album = (Album)objStream.readObject();
return album;
}

正如你看到的,對象流給我們提供了一個非常簡便的方法在Applet和Servlet之前交換一組復雜的信息。請注意我們所處理的不是單純的數據而是對象,所以你可以在客戶端和服務器之間重用這個對象。這使得我們的程序更為智能化並且可以防止重復的邏輯處理。

Socket連接

另外,一種不太常用的Applet和Servlet的通信策略是在兩者之間建立Socket連接。這意味著開發者利用Socket連接設計並執行適當的協議來處理兩者之間的通信。

使用Socket的一個大的好處是這個連接是持續的而且是雙向的。

一個基於HTTP的連接只能短暫地交換信息。如果你想要不斷地用新的信息更新Applet,你必須不斷地建立新的HTTP連接。而對於一個Socket連接來說,你可以只建立一個與服務器的連接,就能實現不斷地更新。

當然,你可能想要建立一個多線程的系統,這樣可以有幾個Applet同時與服務器聯系。請注意使用Socket有的時候並不是一個適當的方法,絕大多數的防火牆不允許通過罕見的端口號進行通信。然而,在一個內部的Intranet上,這還是一項很有用的技術。

APPLET和SERVLET的協同工作

在這篇文章中,我們討論了有關建立一個前端使用Applet、後端使用Servlet的應用程序的一些有用的策略。Applet只有一個唯一的通信路徑,但是我們可以有幾種在Applet和Servlet之間交換信息的方式。

Sun公司的應用程序模型所推薦的策略和我們在這裡討論的一樣。將事務邏輯從界面中分離可以使得應用程序更加靈活,易於升級,這樣的應用程序也更易於設計和維護。

但是這個模型不允許你的Applet直接訪問你的企業數據,這會大大減少你的系統的復雜性並大大提高你的系統的安全性。Applet和Servlet的協同工作將有助於建立一個較好的應用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved