Java RMI - Hızlı Kılavuz
RMI, Remote Method Invocation. Bir sistemde (JVM) bulunan bir nesnenin başka bir JVM'de çalışan bir nesneye erişmesine / bunu çağırmasına izin veren bir mekanizmadır.
RMI, dağıtılmış uygulamalar oluşturmak için kullanılır; Java programları arasında uzaktan iletişim sağlar. Pakette verilmektedir.java.rmi.
Bir RMI Uygulamasının Mimarisi
Bir RMI uygulamasında iki program yazıyoruz, bir server program (sunucuda bulunur) ve bir client program (müşteride bulunur).
Sunucu programının içinde, uzak bir nesne oluşturulur ve bu nesnenin referansı istemci için (kayıt defteri kullanılarak) sağlanır.
İstemci programı, sunucudaki uzak nesneleri ister ve yöntemlerini çağırmaya çalışır.
Aşağıdaki şema bir RMI uygulamasının mimarisini göstermektedir.
Şimdi bu mimarinin bileşenlerini tartışalım.
Transport Layer- Bu katman, istemciyi ve sunucuyu birbirine bağlar. Mevcut bağlantıyı yönetir ve ayrıca yeni bağlantılar kurar.
Stub- Saplama, uzak nesnenin istemcideki temsilidir (proxy). İstemci sisteminde bulunur; istemci programı için bir ağ geçidi görevi görür.
Skeleton - Bu, sunucu tarafında bulunan nesnedir. stub uzak nesneye istek iletmek için bu iskelet ile iletişim kurar.
RRL(Remote Reference Layer) - İstemci tarafından uzak nesneye yapılan referansları yöneten katmandır.
Bir RMI Uygulamasının Çalışması
Aşağıdaki noktalar, bir RMI uygulamasının nasıl çalıştığını özetlemektedir -
İstemci uzak nesneye bir çağrı yaptığında, saplama tarafından alınır ve sonunda bu isteği RRL'ye iletir.
İstemci tarafı RRL isteği aldığında, adı verilen bir yöntemi çağırır. invoke() nesnenin remoteRef. İsteği sunucu tarafında RRL'ye iletir.
Sunucu tarafındaki RRL, isteği nihayet sunucuda gerekli nesneyi çağıran Skeleton'a (sunucudaki proxy) iletir.
Sonuç, müşteriye geri gönderilir.
Marshalling ve Unmarshalling
Bir istemci uzak bir nesnede parametreleri kabul eden bir yöntemi çağırdığında, parametreler ağ üzerinden gönderilmeden önce bir mesajda paketlenir. Bu parametreler ilkel tipte veya nesnelerde olabilir. İlkel tip durumunda, parametreler bir araya getirilir ve ona bir başlık eklenir. Parametrelerin nesne olması durumunda, bunlar serileştirilir. Bu süreç olarak bilinirmarshalling.
Sunucu tarafında, paketlenmiş parametreler ayrılır ve ardından gerekli yöntem çağrılır. Bu süreç olarak bilinirunmarshalling.
RMI Kaydı
RMI kayıt defteri, tüm sunucu nesnelerinin yerleştirildiği bir ad alanıdır. Sunucu her nesne oluşturduğunda, bu nesneyi RMIregistry ile kaydeder (bind() veya reBind()yöntemler). Bunlar, olarak bilinen benzersiz bir ad kullanılarak kaydedilir.bind name.
Uzak bir nesneyi çağırmak için, istemcinin o nesnenin bir başvurusuna ihtiyacı vardır. O sırada istemci, bağlama adını kullanarak nesneyi kayıt defterinden alır (lookup() yöntem).
Aşağıdaki çizim tüm süreci açıklamaktadır -
RMI'nin Hedefleri
RMI'nin hedefleri şunlardır -
- Uygulamanın karmaşıklığını en aza indirmek için.
- Tip güvenliğini korumak için.
- Dağıtılmış çöp toplama.
- Yerel ve uzak nesnelerle çalışma arasındaki farkı en aza indirin.
Bir RMI Java uygulaması yazmak için aşağıda verilen adımları izlemeniz gerekir -
- Uzak arabirimi tanımlayın
- Uygulama sınıfını (uzak nesne) geliştirin
- Sunucu programını geliştirin
- Müşteri programını geliştirin
- Uygulamayı derleyin
- Uygulamayı yürütün
Uzak Arayüzü Tanımlama
Uzak arabirim, belirli bir uzak nesnenin tüm yöntemlerinin açıklamasını sağlar. İstemci, bu uzak arabirimle iletişim kurar.
Uzak arabirim oluşturmak için -
Önceden tanımlanmış arayüzü genişleten bir arayüz oluşturun Remote hangi pakete aittir.
Bu arayüzde müşteri tarafından çağrılabilecek tüm iş yöntemlerini bildirin.
Uzaktan aramalar sırasında ağ sorunları yaşanma ihtimali olduğundan, RemoteExceptionoluşabilir; at onu.
Aşağıda bir uzak arayüz örneği verilmiştir. Burada adıyla bir arayüz tanımladıkHello ve adı verilen bir yöntemi vardır printMsg().
import java.rmi.Remote;
import java.rmi.RemoteException;
// Creating Remote interface for our application
public interface Hello extends Remote {
void printMsg() throws RemoteException;
}
Uygulama Sınıfını Geliştirme (Uzak Nesne)
Önceki adımda oluşturulan uzak arabirimi uygulamamız gerekiyor. (Bir uygulama sınıfını ayrı ayrı yazabiliriz veya sunucu programının bu arayüzü doğrudan uygulamasını sağlayabiliriz.)
Bir uygulama sınıfı geliştirmek için -
- Önceki adımda oluşturulan arayüzü uygulayın.
- Uzak arabirimin tüm soyut yöntemlerine uygulama sağlayın.
Aşağıda bir uygulama sınıfı verilmiştir. Burada adında bir sınıf oluşturdukImplExample ve arayüzü uyguladı Hello önceki adımda oluşturulmuş ve sağlanan body bir mesaj yazdıran bu yöntem için.
// Implementing the remote interface
public class ImplExample implements Hello {
// Implementing the interface method
public void printMsg() {
System.out.println("This is an example RMI program");
}
}
Sunucu Programının Geliştirilmesi
Bir RMI sunucu programı uzak arabirimi uygulamalı veya uygulama sınıfını genişletmelidir. Burada, uzak bir nesne oluşturmalı ve onuRMIregistry.
Bir sunucu programı geliştirmek için -
Uzak nesneyi çağırmak istediğiniz yerden bir istemci sınıfı oluşturun.
Create a remote object aşağıda gösterildiği gibi uygulama sınıfını örnekleyerek.
Yöntemi kullanarak uzak nesneyi dışa aktarın exportObject() sınıfın adı UnicastRemoteObject hangisi pakete ait java.rmi.server.
Kullanarak RMI kaydını edinin getRegistry() yöntemi LocateRegistry pakete ait sınıf java.rmi.registry.
Oluşturulan uzak nesneyi kayıt defterine bağlayın. bind() adlı sınıfın yöntemi Registry. Bu yönteme, bağlama adını ve dışa aktarılan nesneyi parametreler olarak temsil eden bir dize geçirin.
Aşağıda bir RMI sunucu programı örneği verilmiştir.
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends ImplExample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation class
ImplExample obj = new ImplExample();
// Exporting the object of implementation class
// (here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Müşteri Programının Geliştirilmesi
İçine bir istemci programı yazın, uzak nesneyi alın ve bu nesneyi kullanarak gerekli yöntemi çağırın.
Bir müşteri programı geliştirmek için -
Uzak nesneyi çağırmayı amaçladığınız yerden bir istemci sınıfı oluşturun.
Kullanarak RMI kaydını edinin getRegistry() yöntemi LocateRegistry pakete ait sınıf java.rmi.registry.
Yöntemi kullanarak nesneyi kayıt defterinden alın lookup() sınıfın Registry hangisi pakete ait java.rmi.registry.
Bu yönteme, bağlama adını bir parametre olarak temsil eden bir dize değeri iletmeniz gerekir. Bu size uzak nesneyi döndürür.
Lookup (), remote türünde bir nesne döndürür ve onu Hello türüne çevirir.
Son olarak, elde edilen uzak nesneyi kullanarak gerekli yöntemi çağırın.
Aşağıda bir RMI istemci programı örneği verilmiştir.
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
private Client() {}
public static void main(String[] args) {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null);
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello");
// Calling the remote method using the obtained object
stub.printMsg();
// System.out.println("Remote method invoked");
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
Uygulamayı Derlemek
Uygulamayı derlemek için -
- Uzak arabirimi derleyin.
- Uygulama sınıfını derleyin.
- Sunucu programını derleyin.
- İstemci programını derleyin.
Veya,
Tüm programları kaydettiğiniz klasörü açın ve tüm Java dosyalarını aşağıda gösterildiği gibi derleyin.
Javac *.java
Başvurunun Yürütülmesi
Step 1 - Başlat rmi aşağıdaki komutu kullanarak kayıt defteri.
start rmiregistry
Bu bir başlayacak rmi aşağıda gösterildiği gibi ayrı bir pencerede kayıt.
Step 2 - Sunucu sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
Java Server
Step 3 - İstemci sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
java Client
Verification - İstemciyi başlatır başlatmaz, sunucuda aşağıdaki çıktıyı görürsünüz.
Önceki bölümde, örnek bir RMI uygulaması oluşturduk. Bu bölümde, bir istemcinin GUI penceresi (JavaFX) görüntüleyen bir yöntemi çağırdığı bir RMI uygulamasının nasıl oluşturulacağını açıklayacağız.
Uzak Arayüzü Tanımlama
Burada, adında bir uzak arabirim tanımlıyoruz Hello adlı bir yöntemle animation() içinde.
import java.rmi.Remote;
import java.rmi.RemoteException;
// Creating Remote interface for our application
public interface Hello extends Remote {
void animation() throws RemoteException;
}
Uygulama Sınıfının Geliştirilmesi
Bu uygulamanın Implementation sınıfında (Remote Object), JavaFX kullanarak GUI içeriğini gösteren bir pencere oluşturmaya çalışıyoruz.
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
// Implementing the remote interface
public class FxSample extends Application implements Hello {
@Override
public void start(Stage stage) {
// Drawing a Box
Box box = new Box();
// Setting the properties of the Box
box.setWidth(150.0);
box.setHeight(150.0);
box.setDepth(100.0);
// Setting the position of the box
box.setTranslateX(350);
box.setTranslateY(150);
box.setTranslateZ(50);
// Setting the text
Text text = new Text(
"Type any letter to rotate the box, and click on the box to stop the rotation");
// Setting the font of the text
text.setFont(Font.font(null, FontWeight.BOLD, 15));
// Setting the color of the text
text.setFill(Color.CRIMSON);
// Setting the position of the text
text.setX(20);
text.setY(50);
// Setting the material of the box
PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.DARKSLATEBLUE);
// Setting the diffuse color material to box
box.setMaterial(material);
// Setting the rotation animation to the box
RotateTransition rotateTransition = new RotateTransition();
// Setting the duration for the transition
rotateTransition.setDuration(Duration.millis(1000));
// Setting the node for the transition
rotateTransition.setNode(box);
// Setting the axis of the rotation
rotateTransition.setAxis(Rotate.Y_AXIS);
// Setting the angle of the rotation
rotateTransition.setByAngle(360);
// Setting the cycle count for the transition
rotateTransition.setCycleCount(50);
// Setting auto reverse value to false
rotateTransition.setAutoReverse(false);
// Creating a text filed
TextField textField = new TextField();
// Setting the position of the text field
textField.setLayoutX(50);
textField.setLayoutY(100);
// Handling the key typed event
EventHandler<KeyEvent> eventHandlerTextField = new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
// Playing the animation
rotateTransition.play();
}
};
// Adding an event handler to the text feld
textField.addEventHandler(KeyEvent.KEY_TYPED, eventHandlerTextField);
// Handling the mouse clicked event(on box)
EventHandler<javafx.scene.input.MouseEvent> eventHandlerBox =
new EventHandler<javafx.scene.input.MouseEvent>() {
@Override
public void handle(javafx.scene.input.MouseEvent e) {
rotateTransition.stop();
}
};
// Adding the event handler to the box
box.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandlerBox);
// Creating a Group object
Group root = new Group(box, textField, text);
// Creating a scene object
Scene scene = new Scene(root, 600, 300);
// Setting camera
PerspectiveCamera camera = new PerspectiveCamera(false);
camera.setTranslateX(0);
camera.setTranslateY(0);
camera.setTranslateZ(0);
scene.setCamera(camera);
// Setting title to the Stage
stage.setTitle("Event Handlers Example");
// Adding scene to the stage
stage.setScene(scene);
// Displaying the contents of the stage
stage.show();
}
// Implementing the interface method
public void animation() {
launch();
}
}
Sunucu Programı
Bir RMI sunucu programı uzak arabirimi uygulamalı veya uygulama sınıfını genişletmelidir. Burada, uzak bir nesne oluşturmalı ve onuRMIregistry.
Bu uygulamanın sunucu programı aşağıdadır. Burada, yukarıda oluşturulan sınıfı genişleteceğiz, uzak bir nesne oluşturacağız ve onu bağlama adıyla RMI kayıt defterine kaydedeceğiz.hello.
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends FxSample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation class
FxSample obj = new FxSample();
// Exporting the object of implementation class
// (here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Müşteri Programı
Bu uygulamanın istemci programı aşağıdadır. Burada, uzak nesneyi getiriyoruz ve adlandırılmış yöntemini çağırıyoruzanimation().
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
private Client() {}
public static void main(String[] args) {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null);
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello");
// Calling the remote method using the obtained object
stub.animation();
System.out.println("Remote method invoked");
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
Örneği Çalıştırmak için Adımlar
RMI Örneğimizi çalıştırmak için gereken adımlar aşağıdadır.
Step 1 - Tüm programları kaydettiğiniz klasörü açın ve tüm Java dosyalarını aşağıda gösterildiği gibi derleyin.
Javac *.java
Step 2 - Başlat rmi aşağıdaki komutu kullanarak kayıt defteri.
start rmiregistry
Bu bir başlayacak rmi aşağıda gösterildiği gibi ayrı bir pencerede kayıt.
Step 3 - Sunucu sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
Java Server
Step 4 - İstemci sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
java Client
Verification - İstemciyi başlatır başlatmaz, sunucuda aşağıdaki çıktıyı görürsünüz.
Önceki bölümde, bir istemcinin GUI penceresini (JavaFX) görüntüleyen bir yöntemi çağırdığı örnek bir RMI uygulaması oluşturduk.
Bu bölümde, bir istemci programının sunucuda bulunan MySQL veritabanındaki bir tablonun kayıtlarını nasıl alabileceğini görmek için bir örnek alacağız.
Adında bir tablomuz olduğunu varsayalım student_data veritabanında details Aşağıda gösterildiği gibi.
+----+--------+--------+------------+---------------------+
| ID | NAME | BRANCH | PERCENTAGE | EMAIL |
+----+--------+--------+------------+---------------------+
| 1 | Ram | IT | 85 | [email protected] |
| 2 | Rahim | EEE | 95 | [email protected] |
| 3 | Robert | ECE | 90 | [email protected] |
+----+--------+--------+------------+---------------------+
Kullanıcının adını varsayalım myuser ve şifresi password.
Öğrenci Sınıfı Oluşturmak
Oluşturmak Student ile sınıf setter ve getter aşağıda gösterildiği gibi yöntemler.
public class Student implements java.io.Serializable {
private int id, percent;
private String name, branch, email;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getBranch() {
return branch;
}
public int getPercent() {
return percent;
}
public String getEmail() {
return email;
}
public void setID(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setBranch(String branch) {
this.branch = branch;
}
public void setPercent(int percent) {
this.percent = percent;
}
public void setEmail(String email) {
this.email = email;
}
}
Uzak Arayüzü Tanımlama
Uzak arabirimi tanımlayın. Burada, adında bir uzak arabirim tanımlıyoruzHello adlı bir yöntemle getStudents ()içinde. Bu yöntem, sınıfın nesnesini içeren bir liste döndürürStudent.
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.*;
// Creating Remote interface for our application
public interface Hello extends Remote {
public List<Student> getStudents() throws Exception;
}
Uygulama Sınıfının Geliştirilmesi
Bir sınıf oluşturun ve yukarıda oluşturulanları uygulayın interface.
İşte biz uyguluyoruz getStudents() yöntemi Remote interface. Bu yöntemi çağırdığınızda, adlı bir tablonun kayıtlarını alır.student_data. Ayarlayıcı yöntemlerini kullanarak bu değerleri Öğrenci sınıfına ayarlar, bir liste nesnesine ekler ve bu listeyi döndürür.
import java.sql.*;
import java.util.*;
// Implementing the remote interface
public class ImplExample implements Hello {
// Implementing the interface method
public List<Student> getStudents() throws Exception {
List<Student> list = new ArrayList<Student>();
// JDBC driver name and database URL
String JDBC_DRIVER = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost:3306/details";
// Database credentials
String USER = "myuser";
String PASS = "password";
Connection conn = null;
Statement stmt = null;
//Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//Open a connection
System.out.println("Connecting to a selected database...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("Connected database successfully...");
//Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "SELECT * FROM student_data";
ResultSet rs = stmt.executeQuery(sql);
//Extract data from result set
while(rs.next()) {
// Retrieve by column name
int id = rs.getInt("id");
String name = rs.getString("name");
String branch = rs.getString("branch");
int percent = rs.getInt("percentage");
String email = rs.getString("email");
// Setting the values
Student student = new Student();
student.setID(id);
student.setName(name);
student.setBranch(branch);
student.setPercent(percent);
student.setEmail(email);
list.add(student);
}
rs.close();
return list;
}
}
Sunucu Programı
Bir RMI sunucu programı uzak arabirimi uygulamalı veya uygulama sınıfını genişletmelidir. Burada, uzak bir nesne oluşturmalı ve onuRMI registry.
Bu uygulamanın sunucu programı aşağıdadır. Burada, yukarıda oluşturulan sınıfı genişleteceğiz, uzak bir nesne oluşturacağız ve onu bağlama adıyla RMI kayıt defterine kaydedeceğiz.hello.
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends ImplExample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation class
ImplExample obj = new ImplExample();
// Exporting the object of implementation class (
here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Müşteri Programı
Bu uygulamanın istemci programı aşağıdadır. Burada, uzak nesneyi getiriyoruz ve adlı yöntemi çağırıyoruz.getStudents(). Liste nesnesinden tablonun kayıtlarını alır ve görüntüler.
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.*;
public class Client {
private Client() {}
public static void main(String[] args)throws Exception {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null);
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello");
// Calling the remote method using the obtained object
List<Student> list = (List)stub.getStudents();
for (Student s:list)v {
// System.out.println("bc "+s.getBranch());
System.out.println("ID: " + s.getId());
System.out.println("name: " + s.getName());
System.out.println("branch: " + s.getBranch());
System.out.println("percent: " + s.getPercent());
System.out.println("email: " + s.getEmail());
}
// System.out.println(list);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
Örneği Çalıştırmak için Adımlar
RMI Örneğimizi çalıştırmak için gereken adımlar aşağıdadır.
Step 1 - Tüm programları kaydettiğiniz klasörü açın ve tüm Java dosyalarını aşağıda gösterildiği gibi derleyin.
Javac *.java
Step 2 - Başlat rmi aşağıdaki komutu kullanarak kayıt defteri.
start rmiregistry
Bu bir başlayacak rmi aşağıda gösterildiği gibi ayrı bir pencerede kayıt.
Step 3 - Sunucu sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
Java Server
Step 4 - İstemci sınıfı dosyasını aşağıda gösterildiği gibi çalıştırın.
java Client