Spring Remoting- Spring và RMI (Remote Method Invocation)(P.1)

 

Trong loạt bài giới thiệu về Spring và Remoting, tôi đã giới thiệu phần trước sử dụng Spring và JMS thông qua thư viện ActiveMQ. Hôm nay, tôi giới thiệu sử dụng Spring và RMI, cách thức cài đặt một ứng dụng RMI được hỗ trợ bởi Spring như thế nào, nó mang lại những lợi ích gì.

Và để tránh những bối rối cho những ai chưa làm quen nhiều với RMI, tôi nhắc lại một vài khái niệm cơ bản về RMI.

Trong bài này tôi trình bày 2 phần.

RMI cơ bản : trình bày một cái nhìn tổng quan về RMI, sau khi kết thúc, chúng ta sẽ hiểu RMI là gì, thực hiện viết một chương trình thuần túy RMI, biên dịch trên commanline và kết nối gọi phương thức từ Client- máy Linux(Ubuntu) về Server-máy Windows(XP).

RMI và Spring : RMI với sự hỗ trợ của Spring, và tại sao chúng ta lựa chọn sự kết hợp này.

Phần 1: Giới thiệu về RMI

RMI là gì?

RMI là một cơ chế gọi phương thức từ xa giữa 2 máy cài đặt máy ảo Java, dùng để gọi một phương thức trên một đối tượng từ xa giống như trên máy cục bộ.

RMI hoạt động như thế nào:

RMI hoạt động dựa trên cơ chế stub/skeleton nghĩa là phát sinh bộ khung sườn của đối tượng remote, đặt trên máy remote và máy local. Bộ khung sườn này đóng vai trò như những nhà ngoại giao, nhờ đó 1 công việc được lREMOTELY thì bây giờ có tính LOCALLY.

Stubs hoạt động phía client và Sekeleton hoạt động phía server, trong đặc tả mới hiện nay, khi viết code không cần tạo ra Skeleton nữa, chúng ta chỉ cần tạo ra stub cho client là đủ, phần còn lại, RMI sẽ lo liệu cho chúng ta.

Stub và Skeleton sẽ có nhiệm vụ trao đổi dữ liệu cho nhau, khi có một yêu cầu dưới client, stub có nhiệm vụ Serialize mọi tham số (là object) và truyền lên Server, sau đó Skeleton sẽ deSerialize đối tượng này và xử lý, sau đó là một quá trình ngược lại với quá trình trên, dữ liệu được trả về cho Client.

Chúng ta hiểu nôm na là client sẽ chép một tài liệu lên server nhờ sự hỗ trợ của stub, sau đó Skeleton sẽ mở file đó ra và đọc thông tin trong đó, sau khi đọc xong tài liệu anh ta sẽ chuyển cho cấp trên (server) xử lý, sau khi nhận được kết quả anh ta sẽ tạo ra một tài liệu khác và chép về máy phía Client, Stub phía Client sẽ mở tài liệu ra đọc và trao trả lại cho cấp trên của mình, sau đó là phần xử lý kết quả đó của cấp trên ở Client. Và như vậy, trong chương trình sẽ có sự đóng góp của 4 người, 1 phụ tá và sếp trên server (service và Skeleton), 1 phụ tá và khách hàng dưới client (customer và Stub).

Trước đây phát triển một ứng dụng RMI chúng ta trải qua những bước sau:

  • Biên dịch các class trên server.
  • Tạo Stub and Skeleton (qua rmic)
  • Khởi động bộ đăng ký rmi (rmiregistry)
  • Sử dụng dịch vụ.

Và với cách phát triển mới, mọi chuyện sẽ đơn giản hơn

 

Trước tiên, chúng ta sẽ tạo ra một Interface sử dụng cho cả Client và Server:

Interface này làm nhiệm vụ "Giữ chỗ" cho Object trên server dưới client.

ReceiveMessageInterface.java

package rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface ReceiveMessageInterface extends Remote {
    void receiveMessage(String x) throws RemoteException;
}

 

Và tiếp theo, chúng ta tạo một lớp cài đặt lại interface này, lớp này là lớp dịch vụ, thực hiện các nghiệp vụ bussiness logic.

Phía Server:

RmiServer.java

package rmi;

import java.net.InetAddress; import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RmiServer extends java.rmi.server.UnicastRemoteObject

implements ReceiveMessageInterface

{
    private static final long serialVersionUID = 1L;
    int port = 123;
    String address;
    Registry registry; // rmi registry for lookup the remote objects.

    // This method is called from the remote client by the RMI.
    // This is the implementation of the ReceiveMessageInterface.
    public void receiveMessage(String x) throws RemoteException {
        System.out.println(x);
    }

    public RmiServer() throws RemoteException {
        try {
            // get the address of this host.
            address = (InetAddress.getLocalHost()).toString();
        } catch (Exception e) {
            throw new RemoteException("can't get inet address.");
        }
        System.out.println("this address=" + address + ",port=" + port);

        try {
            // create the registry and bind the name and object.
            registry = LocateRegistry.createRegistry(port);
            registry.rebind("rmiServer", this);
        } catch (RemoteException e) {
            throw e;
        }
    }

    static public void main(String args[]) {
        try {
            RmiServer s = new RmiServer();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

Trong ví dụ này, bussiness mà server thực hiện chỉ đơn giản là xuất ra Console thông điệp mà client gửi lên để yêu cầu.

Tại hàm khởi tạo của RmiServer.java, chúng ta tạo một bootstrap để đăng ký vào rmiregistry, sau đó đăng ký object này vào dịch vụ tên rmiServer bằng phương thức registry.rebind(args).

Phần cài đặt server bao gồm một interface bao gồm những phương thức sẽ cung cấp cho phía client, sau đó một class cài đặt sẽ có nhiệm vụ tạo dịch vụ này theo yêu cầu, cũng theo đó nó đăng ký dịch vụ vào rmiregistry-thao tác để client có thể nhìn thấy dịch vụ này.

Phía Client:

package rmi;

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

public class RmiClient {
    static public void main(String args[]) {
        ReceiveMessageInterface rmiServer;
        Registry registry;
        String serverAddress = args[0];
        String serverPort = args[1];
        String text = args[2];
        System.out.println("sending " + text + " to " + serverAddress + ":"
                + serverPort);
        try {
            // get the Registry
            registry = LocateRegistry.getRegistry(serverAddress, (new Integer(
                    serverPort)).intValue());
            // look up the remote object
            rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));
            // call the remote method
            rmiServer.receiveMessage(text);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (NotBoundException e) {
            e.printStackTrace();
        }
    }
}

Client tìm kiếm dịch vụ mang tên rmiServer đã được đăng ký, một class duy nhất làm nhiệm vụ này.

Để sử dụng chúng ta thực hiện theo cú pháp sau:

java rmi.RmiClient [địa chỉ server] [Port] [Message]

Chạy ứng dụng RMI:

Trước tiên chúng ta sẽ biên dịch các lớp đã viết.

(Lưu ý: không cần tạo stub và skeleton bằng RMIC nữa)

E:\Personal\Projects\SpringRemote\src>javac rmi/ReceiveMessageInterface.java

E:\Personal\Projects\SpringRemote\src>javac rmi/RmiServer.java

Và khởi động dịch vụ trên server:

E:\Personal\Projects\SpringRemote\src>java rmi.RmiServer
this address=spkt/192.168.1.33,port=123

rmiserver

(Hình 1: Dịch vụ được khởi tạo)

 

Biên dịch cho Client:

nangvang@nangvang:/workspace/SpringRemote/src$
nangvang@nangvang:/workspace/SpringRemote/src$ javac rmi/ReceiveMessageInterface.java
nangvang@nangvang:/workspace/SpringRemote/src$ javac rmi/RmiClient.java
nangvang@nangvang:/workspace/SpringRemote/src$

RmiClient

(Hình 2: Client  gọi phương thức trên máy chủ)

  • IP: 192.168.1.33
  • Port: 123
  • Message : Xin chao.

RmiResult

(Hình 3: Server đã nhận được lời gọi phương thức với tham số "Xin chao" và xử lý)

Dưới đây tôi đã giới thiệu viết một ứng dụng RMI một cách đơn giản nhất và cũng cơ bản nhất, bạn đã tạo một proxy là interface ReceiveMessageInterface và một cài đặt RmiServer, sau đó là đăng ký vào rmiRegistry.

Client sử dụng ReceiveMessageInterface để giữ chỗ và gọi phương thức trên server.

Mời bạn tiếp tục theo dõi phần 2 Spring và RMI.

Download demo RMI tutorial Hoặc Link2

About Langthang

This is a short description in the author block about the author. You edit it by entering text in the "Biographical Info" field in the user admin panel.
    Blogger Comment
    Facebook Comment

5 comments :

  1. Bai viet cua ban rat hay, thanks

    ReplyDelete
  2. Hy vong ban Post tiep Phan 2, va cho them vi du ve RMI nhe

    ReplyDelete
  3. minh` vẫn chưa hiểu lắm cách dùng RMI :(

    ReplyDelete
  4. Tuyệt vời. cám ơn nhiều nghe

    ReplyDelete