在Java5.0中對于RMI的使用發生了一些改變, 使得RMI的使用更加容易方便.
一. 定義RMI接口, 這一步最簡單, 與以前相比, 也沒有變化.
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Payment extends Remote {
    public double calculatePayment(double principal, double annualRate, int terms)
                    throws RemoteException;
}

注意點:
1. 必須繼承java.rmi.Remote
2. 接口中的方法必須拋出java.rmi.RemoteException異常

二. 定義遠程類實現接口
與以前相比, 也沒有發生變化


import java.rmi.RemoteException;

public class PaymentImpl implements Payment {

    public double calculatePayment(double principal, double annRate, int years)
                                  throws RemoteException {
        double monthlyInt = annRate / 12;
        double monthlyPayment = (principal * monthlyInt)
                    / (1 - Math.pow(1/ (1 + monthlyInt), years * 12));
        return format(monthlyPayment, 2);
    }
    public double format(double amount, int places) {
        double temp = amount;
        temp = temp * Math.pow(10, places);
        temp = Math.round(temp);
        temp = temp/Math.pow(10, places);
        return temp;
    }
}

注意點:
1. 遠程對象必須實現第一步定義的接口, 在這里是Payment接口.
2. 遠程對象中可以定義接口中不包括的方法, 比如: format, 但是這些方法不能遠程使用.
3. 實現遠程方法時, 可以不拋出java.rmi.RemoteException異常


三. 定義遠程服務
此處與以前相比, 發生了一些變化, 需要注意.

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
   
public class Server {
   
    public Server() {}

    public static void main(String args[]) {
   
    try {
        PaymentImpl robj = new PaymentImpl();
        Payment stub = (Payment) UnicastRemoteObject.exportObject(robj, 0);

        Registry registry = LocateRegistry.getRegistry();
        registry.bind("Mortgage", stub);
        System.out.println("Mortgage Server is ready to listen");

    } catch (Exception e) {
        System.err.println("Server exception thrown: " + e.toString());
        e.printStackTrace();
    }
    }
}


而傳統的做法是這樣的:
public class Server extends java.rmi.server.UnicastRemoteObject implements aRemoteInterface{
    public Server(int port) {
         super(port);
    }
    ....
    Naming.bind(uniqueName, this);
    ....
}

請自行進行比較.

四. 定義客戶端類
相應地, 這部分也有了變化.

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
    private static Payment stub = null;
    private Client() {}

    public static void main(String[] args) {

    double payment, principal = 80000;
        double annualInterest = .065;
        int years = 15;
    try {
        Registry reg = LocateRegistry.getRegistry("localhost");
        stub = (Payment) reg.lookup("Mortgage");
       
    } catch (Exception e) {
        System.err.println("Client exception thrown: " + e.toString());
        e.printStackTrace();
    }
   
        if (args.length == 3) {
           try {
              principal = Double.parseDouble(args[0]);
              annualInterest = Double.parseDouble(args[1]);
              years = Integer.parseInt(args[2]);
           }
           catch (Exception e) {
              System.out.println("Wrong input " + e.getMessage() );
              System.exit(0);
           }
           print(principal, annualInterest, years);
       
        } else {
            System.out.println("Usage: java Client principal annualInterest years ");
            System.out.println("\nFor example: java Client 80000 .065 15 ");
            System.out.println("\nYou will get the output like the following: \n");
        print(principal, annualInterest, years);
            System.exit(0);
        }       
       
    }
   
    public static void print(double pr, double annRate, int years){
        double mpayment = 0;
        try {
            mpayment = stub.calculatePayment(pr, annRate, years);
        }catch(Exception e) {
            System.out.println("Remote method exception thrown: " + e.getMessage());
        }
        System.out.println("The principal is $" + (int)pr);
        System.out.println("The annual interest rate is " + annRate*100 +"%");
        System.out.println("The term is " + years + " years");
        System.out.println("Your monthly payment is $" + mpayment);
    }
}

注意點: lookup服務的方法與以前是不同的

五. 測試使用
現在我們有了4個類
Payment.java-- a remote interface
PaymentImpl.java-- a remote object class
Server.java-- an RMI server
Client.java-- an RMI client

1. 我們把它們都放到一個目錄下, 比如: 以 c:\myrmi
2. 使用javac編譯這4個類. javac -d . Payment.java PaymentImpl.java Server.java Client.java
3. 注意: Java5.0的新特性, 現在在不需要在啟動服務之前生成Stub了, stub現在自動生成.
而在Java5.0以前是需要用rmic手工生成的.
4. start rmiregistry, 出現一個窗口, 不要關閉.
5. start java Server, 出現一個窗口, 顯示 Mortgage server is ready to listen...
6. 啟動客戶端java Client, 如果出現
The principal is $150000
The annual interest rate is 6.0%
The term is 15 years
Your monthly payment is $1265.79
那就大功告成了.

注意點: 安全策略機制進行了弱化, 不再需要指定策略文件 授這個權,那個權的了.