vi du rmi, bai tap rmi, java, lap trinh phan tan voi rmin rmi java tutorials A simple Java RMI example.

Sau khi giới thiệu về RMI trong Java ở bài trước. Hôm nay s cùng với các bạn sẽ làm một ví dụ đơn giản về lập trình phân tán RMI bằng ngôn ngữ java nhé. Trong lập trình RMI, người lập trình chỉ cần viết lời gọi phương thức vì đối tượng được gọi đã hiện diện trong máy ảo Java.


Hôm nay chúng ta sẽ cùng phát triển một Máy tính đơn giản sử dụng công nghê RMI. Các bước phát triển ứng dụng RMI đó nhứ sau:
  • Định nghĩa một Interface dùng chung.
  • Tạo lớp thực thi Implements cho Interface trên.
  • Cài đặt cho đối tượng trên Server.
  • Cài đặt cho Client.
  • Biên dịch và thực thi ứng dụng.
Lưu ý đây chỉ là một ứng dụng đơn giản chủ yếu là để làm quen với RMI nên mình sẽ dùng notepad để code và chạy nó với command line. Còn bây giờ thì bắt tay ngay thui.

Đầu tiên bạn phải xác định lớp nào là lớp cục bộ, lớp nào là lớp được gọi từ xa. Nó bao gồm các bước sau:
Định nghĩa các giao diện cho các phương thức ở xa (remote interfaces): Một remote interface mô tả các phương thức mà nó có thể được kích hoạt từ xa bởi các Client. Đi cùng với việc định nghĩa Remote Interface là việc xác định các lớp cục bộ làm tham số hay giá trị trả về của các phương thức được gọi từ xa.
Cài đặt các đối tượng từ xa (remote objects): Các Remote Object phải cài đặt cho một hoặc nhiều Remote Interfaces đã được định nghĩa. Các lớp của Remote Object class cài đặt cho các phương thức được gọi từ xa đã được khai báo trong Remote Interface và có thể định nghĩa và cài đặt cho cả các phương thức được sử dụng cục bộ. Nếu có các lớp làm đối số hay giá trị trả về cho các phương thức được gọi từ xa thì ta cũng định nghĩa và cài đặt chúng.
Cài đặt các chương trình Client: Các chương trình Client có sử dụng các Remote Object có thể được cài đặt ở bất kỳ thời điểm nào sau khi các Remote Interface đã được định nghĩa.

Định nghĩa một Interface dùng chung.
Interface này như là một tờ giao kèo của Server và Client. Cả Client và Server phải tuân thủ nó, chỉ được triển khai và gọi các phương thức nó cho phép. Các phương thức đều kèm theo throws RemoteException.
Với ví dụ này, s sẽ tạo một Interface Class với tên là Calculator. Nó chỉ bao gồm một phương thức addNum() dùng để cộng 2 số nguyên mà thôi. Bạn có thể phát triển thêm các phương thức khác.
Mở notepad gõ đoạn code phía dưới và lưu với tên Calculator.java (Lưu ý tên file phải trùng với tên lớp.)

Calculator.java
import java.rmi.*;
public interface Calculator extends Remote{
public int addNum(int x,int y) throws RemoteException ;
}

Tạo lớp thực thi Implements cho Interface.
Lớp cài đặt không những cài đặt phần thực thi cho Interface Class mà còn phải thừa kế từ một lớp của Java là lớp UnicastRemoteObject.

CalculatorImpl.java
import java.rmi.*;
import java.rmi.server.*;
public class CalculatorImpl implements Calculator {
public int addNum(int x,int y) throws RemoteException {
System.out.println("Client request to Calculator!!");
return (x+y);
}
}

Cài đặt cho đối tượng trên Server.
CalculatorServer.java
import java.rmi.*;
import java.rmi.server.*;
public class CalculatorServer {
public static void main(String[] args) {
try {
CalculatorImpl c = new CalculatorImpl();
System.out.println("Exporting ...!!!");
UnicastRemoteObject.exportObject(c);
Naming.bind("rmi://localhost/MyCalculator", c);
System.out.println("Register...!!!");
}
catch (Exception e) {
System.out.println("Loi" + e);
}
}
}
Trên server, chúng ta phải xác định được vị trí của đối tượng từ xa, RMI cung cấp một máy chủ chuyên quản lý tên là RMI Registry để thực hiện chức năng này. Quá trình đăng kí bao gồm:
  • Tạo một Object từ đối tượng từ xa CalculatorImpl c = new CalculatorImpl();
  • Khai báo đối tượng này có khả năng truy xuất từ xa UnicastRemoteObject.exportObject(c);
  • Đăng ký đối tượng này với rmiregistry: Naming.bind("rmi://localhost/MyCalculator", c);
Muốn sử dụng UnicastRemoteObject, chúng ta phải khai báo import java.rmi.server.*. Ta sẽ đăng kí đối tượng này trong MyCalculator tại localhost. Chúng ta sử dụng phương thức rebind() để tránh lỗi trong trường hợp tên này đã tồn tại trong RMI Registry, ngược lại chúng ta cũng có thể sử dụng phương thức bind().

Cài đặt cho Client.
Để xây dựng được một chương trình trên Client để gọi hàm, đầu tiên chúng ta phải xác định được vị trí của đối tượng bên phía máy chủ Naming.lookup("rmi://localhost/MyCalculator"). Khi đã tìm thấy đối tượng cho phép truy xuất từ xa trong RMI Registry, Client sẽ gọi hàm như trên local: c.addNum(a, b).
CalculatorClient.java
import java.util.*;
import java.rmi.*;
public class CalculatorClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
System.out.println("Finding ...");
Calculator c=(Calculator)Naming.lookup("rmi://localhost/MyCalculator");
Scanner nhapvao = new Scanner(System.in);
System.out.print("a= ");
int a = nhapvao.nextInt();
System.out.print("b= ");
int b = nhapvao.nextInt();
System.out.println("Ket qua: " + c.addNum(a, b));
}
catch (Exception e) {
System.out.println("Loi "+ e);
}
}
}


Biên dịch và thực thi ứng dụng.
Bài trước s cũng đã hướng dẫn sơ về cách biên dịch một chương trình java. Hôm nay s sẽ cụ thể với một ví dụ. Đầu tiên cd vào thư mục chứa các file java đã viết. Chạy lệnh dưới để biên dịch tất cả các file *.java thành *.class
javac *.java
Đăng kí với RMI Registry và khởi động Registry bằng lệnh sau
rmic CalculatorImpl
start rmiregistry
Sau đó start Server
java CalculatorServer
Gọi Client để thực thi.
java CalculatorClient

Cách tốt nhất bạn nên viết tất cả các lệnh trên vào một file .bat hoặc .cmd để tiện lợi thực hiện sau này. Sau khi chạy file .bat bên dưới sẽ sinh ra 2 file Server.bat Client.bat, khi cần chạy file server trước, sau đó đến client.
MyCalculator.bat
@ECHO OFF
echo Compliled ...
javac *.java
echo RMI registry ...
rmic CalculatorImpl
echo Start rmiregistry ...
start rmiregistry
echo Creating Server.bat and Client.bat
echo @ECHO OFF >Server.bat
echo Server is starting...
echo java CalculatorServer >>Server.bat
echo @ECHO OFF > Client.bat
echo java CalculatorClient >> Client.bat
echo pause >> Client.bat