国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java遠程方法調用(二)

2019-11-18 16:20:19
字體:
來源:轉載
供稿:網友

  出自:java愛好者  
傳遞屬性

  前面我們講到,RMI可以傳遞屬性,并簡單介紹了一下一個有關開支報告程序的情況。下面我們將深入討論如何設計這樣的系統。這樣介紹的目的是使您能夠利用RMI的功能將屬性從一個系統傳遞到另一個系統,并隨心所欲地安排當前的計算地點,并便于將來的改變。下面的例子并未涉及真實世界可能發生的所有問題,但可幫助讀者了解處理問題的方法。

服務器定義的策略

  圖1是可進行動態配置的開支報告系統的示意圖。客戶機向用戶顯示圖形用戶界面(GUI),用戶填寫開支報告。客戶機程序使用RMI與服務器進行通信。服務器使用JDBC( Java關系數據庫連接包)將開支報告存儲在數據庫中。至此,這看起來與其它多層次系統大同小異,但有一個重大區別-- RMI能下載屬性。
假定公司關于開支報告的政策發生改變。例如,目前公司只要求對超過20美元的開支需開具發票。但到明天,公司認為這太寬松了,便決定除不超過20美元的餐費以外,任何開支均需開具發票。如果不能下載屬性的話,那么在設計便于修改的系統時您可選擇下列方法之一:

  用客戶端安裝與政策有關的程序。政策改變時,必須更新包含此政策的所有客戶端程序。您可在若干服務器上安裝客戶程序,并要求所有用戶從這些服務器之一運行客戶程序,從而減少問題。但這仍不能徹底解決問題-- 那些讓程序運行好幾天的用戶就無法使程序更新,而總是會有一些用戶為了方便而把軟件復制到本地磁盤上。
  您可要求服務器在每次向開支報告添加項目時檢查政策。但這樣就會在客戶機和服務器之間產生大量數據流,并增加服務器的工作量。這還會使系統變得更加脆弱--網絡故障會立即妨礙用戶,而不僅僅是只在其呈交開支報告或啟動新的報告時對其產生影響。同時,添加項目的速度也會變慢,因為這需要穿越整個網絡往返一圈才能到達(不堪重負的)服務器。
您可在呈交報告時要求服務器對政策進行檢查。這樣就會使用戶創建很多必須待批報告的錯誤項目,而不是立刻捕捉到第一個錯誤,從而使用戶有機會停止制造錯誤。為避免浪費時間,用戶需要立刻得到有關錯誤的反饋。
  有了RMI,您就能以簡單的方法調用程序從服務器得到屬性,從而提供了一種靈活的方式,將計算任務從服務器卸載到客戶機上,同時為用戶提供速度更快的反饋。當用戶準備編寫一份新的開支報告時,客戶機就會向服務器要求一個對象,該對象嵌入了適用于該開支報告的當前政策,就如同通過用Java編寫的政策接口所表示的那樣。該對象可以以任何方式實現當前政策。如果這是客戶機RMI首次看到這種專門執行的政策,就會要求服務器提供一份執行過程的副本。如果執行過程將來發生變化,則一種新的政策對象將被返回給客戶機,而RMI運行時則會要求得到新的執行過程。
  這表明,政策永遠是動態的。您要想修改政策,就只需簡單地編寫通用政策接口的新的執行程序,把它安裝在服務器上,并對服務器進行配置以返回這種新類型的對象即可。這樣,每臺客戶機都會根據新的政策對新的開支報告進行檢查。

這是一種比任何靜態方法都更好的方法,原因如下:

  所有客戶機不必暫停或用新的軟件來升級--軟件可根據需要在不工作時加以更新。
  服務器不必參與項目檢查工作,該工作可在本地完成。
  允許動態限制,因為對象執行程序(而不僅僅是數據)是在客戶機和服務器之間進行傳遞的。
  使用戶能立刻看到錯誤。

使客戶機在服務器上所能調用的方法的遠程接口定義如下:
import java.rmi.*;
public interface EXPenseServer extends Remote {
Policy getPolicy() throws RemoteException;
void submitReport(ExpenseReport report)
throws RemoteException, InvalidReportException;
}
import語句輸入Java RMI包。所有RMI類型均在包java.rmi或其子包內定義。接口ExpenseServer是一般的Java接口,具有如下兩種有趣的特點:

它擴展了名為Remote的RMI接口,這使該接口標記為可用于遠程調用。

它的所有方法均拋出RemoteException,后者用來表示網絡或信息故障。

  遠程方法還可拋出您所需要的任何其他例外,但至少必須拋出RemoteException,這樣您才能處理只會在分布式系統中發生的錯誤狀態。該接口本身支持兩個方法:getPolicy (返回一個實現政策接口的對象),和submitReport (提交一個完成的開支請求,并在報告無論因何種原因使表格出現錯誤時,拋出一個例外)。
政策接口本身可聲明一種使客戶機知道能否在開支報告中添加一個項目的方法:
public interface Policy {
void checkValid (Expenseentry entry)
throws PolicyViolationException;
}
如果該項目有效--即符合當前政策,則該方法可正常返回。否則就會拋出一個描述該錯誤的例外。政策接口是本地的(而非遠程的),所以將通過本機對象在客戶機上執行--在客戶機的虛擬機上,而非整個網絡上運行的對象。客戶機可能運行下列程序:
Policy curPolicy = server.getPolicy();
start a new expense report
show the GUI to the user
while (user keeps adding entries) {
try {
curPolicy.checkValid(entry); // throws exception if not OK
add the entry to the expense report
} catch (PolicyViolationException e) {
show the error to the user
}
}
server.submitReport(report);

  當用戶請求客戶機軟件啟動一份新的開支報告時,客戶機就調用server.getPolicy,并要求服務器返回一個包含當前開支政策的對象。
添加的每個項目首先都被提交給該政策對象,以獲得批準。如果政策對象報告無錯誤,則該項目就被添加到報告中;否則錯誤就被顯示給用戶,而后者可采取修正措施。當用戶完成向報告中添加項目時,整個報告就被呈交。服務程序如下:
import java.rmi. *;
import java.rmi.server. *;
class ExpenseServerImpl
extends UnicastRemoteObject
implements ExpenseServer
{
ExpenseServerImpl() throws RemoteException {
// . . . set up server state . . .
}
public Policy getPolicy() {
return new TodaysPolicy();
}
public void submitReport(ExpenseReport report) {
// . . . write the report into the db . . .
}
}
除基本程序包外,我們還輸入RMI的服務程序包。類型UnicastRemoteObject 定義了此服務程序遠程對象的類型,在本例中,應為單一服務程序而非復制服務(下面還會詳細介紹)。Java類ExpenseSeverImpl實現遠程接ExpenseServer的方法。遠程主機的客戶機可使用RMI將信息發送給ExpenseServerImpl對象。

本文中討論的重要方法是getPolicy,它簡單地返回定義當前政策的對象。下面看一個執行政策的例子:

public class TodaysPolicy implements Policy {
public void checkValid(ExpenseEntry entry)
throws PolicyViolationException
{
if (entry.dollars() < 20) {
return; // no receipt required
else if (entry.haveReceipt() == false) {
throw new PolicyViolationException;
}
}
}
TodaysPolicy進行檢查的目的是確保無收據的任何項目均少于20美元。如果將來政策發生變化,僅少于20美元的餐費可不受“需要收據”政策的限制,則您可提供新的政策實現:
public class TomorrowsPolicy implements Policy {
public void checkValid(ExpenseEntry entry)
throws PolicyViolationException
{
if (entry.isMeal() && entry.dollars() < 20) {
return; // no receipt required
} else if (entry.haveReceipt() == false) {
throw new PolicyViolationException;
}
}
}
  編寫這個類,并把它安裝在服務器上,然后告訴服務器開始提供TomorrowsPolicy對象,而非daysPolicy對象,這樣您的整個系統就會開始使用新的政策。當客戶機調用服務器的getPolicy方法時,客戶機的RMI就會檢查返回的對象是否為已知類型。每臺客戶機首次遇到TomorrowsPolicy時,RMI就會在getPolicy返回前下載政策的實現。客戶機可輕松地開始增強這個新的政策。

  RMI使用標準Java對象序列化機制傳遞對象。引用遠程對象參數作為遠程引用傳遞。如果向某方法提供的參數為原始類型或本機(非遠程)對象,則向服務器傳遞一個深副本。返回值也拾?照同樣的方式處理,只不過是沿其它方向。RMI可使用戶向本機對象傳遞和返回完整對象圖并為遠程對象傳遞和返回引用。

  在真實的系統中,getPolicy方法可能會有一個可以識別用戶及開支報告類型(差旅、客戶關系等)的參數,這樣可使政策加以區別。您或者可以不要求單獨的政策和開支報告對象,但您可以有一種newExpenseReport方法,它可返回一個直接檢查政策的ExpenseReport對象。這最后一種策略可使您像修改政策一樣簡單地修改開支報告的內容--當公司決定需要把餐費劃分為早餐、午餐和晚餐項目,而且像上述修改政策一樣簡單地執行修改時--可編寫一個實現該報告的新類,客戶程序就會自動使用這個類。

(出處:http://m.survivalescaperooms.com)



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 祁阳县| 黄浦区| 延吉市| 太和县| 商城县| 南昌市| 五指山市| 承德县| 南昌县| 红安县| 合阳县| 呼玛县| 介休市| 双城市| 灌云县| 屯门区| 海口市| 平果县| 沈丘县| 巩留县| 蓬安县| 海安县| 石渠县| 达拉特旗| 仲巴县| 呼玛县| 安远县| 东台市| 张家港市| 内乡县| 诸暨市| 屏东县| 涞源县| 深水埗区| 仁布县| 绥芬河市| 黔东| 始兴县| 时尚| 鄂州市| 荆州市|