openplanning

Hướng dẫn gọi phương thức từ xa với Java RMI

  1. Giới thiệu
  2. Tạo project
  3. Chạy ứng dụng

1. Giới thiệu

RMI là một cách để bạn có thể gọi phương thức (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 một project có tên RMITutorial
Đây là mô hình các class được đóng gói dành cho ClientServer
Đâ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 các phương thứ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 thử (demo) trên Eclipse:
Trước hết chạy class Server:
Server starting...
Registered: WeatherService -> org.o7planning.tutorial.rmi.server.WeatherServiceImpl[WeatherServiceImpl[UnicastServerRef [liveRef: [endpoint:[192.168.0.102:64865](local),objID:[6aadac58:179707abf4c:-7fff, -728182817779393915]]]]]
Server started!
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:
Chicago weather today: sunny
Hanoi weather today: sunny

Java cơ bản

Show More