Hướng dẫn gọi phương thức từ xa với Java RMI
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Giới thiệu

RMI là một cách để bạn có thể gọi method từ xa, chẳng hạn gọi method đang chạy trên một máy tính B. Và nhận kết quả trả về. Như vậy máy B giống như một máy chủ cung cấp dịch vụ.

2- Tạo project

Tạo mới Project RMITutorial
Đây là mô hình các class được đóng gói dành cho Client và Server
Đây là mô hình làm việc của RMI. Server sẽ đăng ký đối tượng lên trên bộ đăng ký (Registry). Client sẽ tìm kiếm bộ đăng ký theo địa chỉ IP và cổng (Host + Port) để có thể gọi các method từ các đối tượng tại Server.
  • Constants.java
package org.o7planning.tutorial.rmi;

public class Constants {

    // Địa điểm Hà Nội
    public static final String LOCATION_HANOI = "HaNoi";    
    public static final String LOCATION_TOKYO = "Tokyo";
    public static final String LOCATION_CHICAGO = "Chicago";
    
    
    // Thời tiết mưa
    public static final String WEATHER_RAIN ="rain";
    
    // Thời tiết nắng.
    public static final String WEATHER_SUNNY ="sunny";

}
  • WeatherData.java
package org.o7planning.tutorial.rmi;

import java.io.Serializable;
import java.util.Date;

public class WeatherData implements Serializable {

    private static final long serialVersionUID = 1L;

    private Date date;
    private String location;
    private String weather;

    public WeatherData(Date date, String location, String weather) {
        this.date = date;
        this.location = location;
        this.weather = weather;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

}
  • WeatherService.java
package org.o7planning.tutorial.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Date;



public interface WeatherService extends Remote {

  // Method lấy về đối tượng thông tin thời tiết.
  // Tham số truyền vào ngày & địa điểm.
  public WeatherData getWeather(Date date, String location)
          throws RemoteException;
}
  • WeatherServiceImpl.java
package org.o7planning.tutorial.rmi.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Calendar;
import java.util.Date;

import org.o7planning.tutorial.rmi.Constants;
import org.o7planning.tutorial.rmi.WeatherData;
import org.o7planning.tutorial.rmi.WeatherService;

public class WeatherServiceImpl extends UnicastRemoteObject implements
       WeatherService {
   private static final long serialVersionUID = 1L;

   public WeatherServiceImpl() throws RemoteException {
       super();
   }

   @Override
   public synchronized WeatherData getWeather(Date date, String location)
           throws RemoteException {
       Calendar c = Calendar.getInstance();
       c.setTime(date);

       int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

       // Sunday, Monday
       if (dayOfWeek == 1 || dayOfWeek == 2) {
           if (location.equals(Constants.LOCATION_CHICAGO)) {
               // Rain
               return new WeatherData(date, location, Constants.WEATHER_RAIN);
           } else if (location.equals(Constants.LOCATION_HANOI)) {
               // Sunny
               return new WeatherData(date, location, Constants.WEATHER_SUNNY);
           } else if (location.equals(Constants.LOCATION_TOKYO)) {
               // Sunny
               return new WeatherData(date, location, Constants.WEATHER_SUNNY);
           }
           return new WeatherData(date, location, Constants.WEATHER_SUNNY);
       } else {
           return new WeatherData(date, location, Constants.WEATHER_SUNNY);
       }

   }
}
  • Client.java
package org.o7planning.tutorial.rmi.client;

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

import org.o7planning.tutorial.rmi.Constants;
import org.o7planning.tutorial.rmi.WeatherData;
import org.o7planning.tutorial.rmi.WeatherService;

public class Client {

    // Host or IP of Server
    private static final String HOST = "localhost";
    private static final int PORT = 1099;
    private static Registry registry;

    public static void main(String[] args) throws Exception {

        // Search the registry in the specific Host, Port.
        registry = LocateRegistry.getRegistry(HOST, PORT);

        // Lookup WeatherService in the Registry.
        WeatherService service = (WeatherService) registry
                .lookup(WeatherService.class.getSimpleName());

        Date today = new Date();

        // Get Chicago weather info:
        WeatherData chicagoWeather = service.getWeather(today,
                Constants.LOCATION_CHICAGO);

        System.out.println("Chicago weather today: "
                + chicagoWeather.getWeather());
        
        // Get Hanoi weather info:
        WeatherData hanoiWeather = service.getWeather(today,
                Constants.LOCATION_HANOI);

        System.out.println("Hanoi weather today: " + hanoiWeather.getWeather());

    }
}
  • Server.java
package org.o7planning.tutorial.rmi.server;

import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import org.o7planning.tutorial.rmi.WeatherService;

public class Server {
    private static final int PORT = 1099;
    private static Registry registry;

    public static void startRegistry() throws RemoteException {

        // Tạo một bộ đăng ký (Registry) tại Server.
        registry =  LocateRegistry.createRegistry(PORT);
    }

    public static void registerObject(String name, Remote remoteObj)
            throws RemoteException, AlreadyBoundException {
        // Đăng ký đối tượng vào bộ đăng ký.
        // Nó được gắn với cái tên nào đó.
        // Client sẽ tìm trên bộ đăng ký với tên này để có thể gọi đối tượng.

 
        registry.bind(name, remoteObj);
        System.out.println("Registered: " + name + " -> "
                + remoteObj.getClass().getName() + "[" + remoteObj + "]");
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Server starting...");
        startRegistry();
        registerObject(WeatherService.class.getSimpleName(), new WeatherServiceImpl());

        // Server đã được start, và đang lắng nghe các request từ Client.
        System.out.println("Server started!");
    }
}

3- Chạy ứng dụng

Để chạy được ứng dụng trên bạn cần đóng gói project thành 2 file jar. File jar 1 gồm các class dùng để chạy ứng dụng tại client. Và file jar 2 bao gồm các class để chạy ứng dụng tại server.
Đây là hình minh họa:
Tuy nhiên bạn có thể chạy Demo trên Eclipse:
Trước hết chạy class Server:
Server đang được chạy, nó đã đăng ký các Remote Object lên bộ đăng ký (Registry). Bước tiếp theo chạy class tại Client. Chạy class Client: