Java RMI –分布式对象示例

分布式对象通信

图片来源: Wikimedia.org

Java RMI Hello World示例中,我们引入了Java远程方法调用,并在服务器-客户端之间进行了非常基本String-based通信。 在此示例中,我们将更进一步,并介绍使用分布式对象的服务器-客户端通信。

1.远程接口

首先,我们将开发包含服务器实现的所有方法的Remote InterfaceInterface必须始终是public并且必须扩展RemoteRemote Interface描述的所有方法必须在其throws子句中列出RemoteException

RMIInterface.java
package com.mkyong.rmiinterface;

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

public interface RMIInterface extends Remote {

    Book findBook(Book b) throws RemoteException;
    List<Book> allBooks() throws RemoteException;

}

2.分布式对象类

这是服务器和客户端将交换的Object的类,并且必须实现Serializable Interface 。 此类声明一个显式的serialVersionUID值以确保不同Java编译器实现之间的一致性也非常重要。

如果我们忽略了这一点,或者如果服务器的Distributed Object类声明了与Client的Distributed Object类不同的serialVersionUID ,则反序列化过程将导致InvalidClassException

在Eclipse IDE上,您可以生成如下的serialVersionUID:

java-rmi-分布式对象示例1
Book.java
package com.mkyong.rmiinterface;

import java.io.Serializable;

public class Book implements Serializable {

    private static final long serialVersionUID = 1190476516911661470L;
    private String title;
    private String isbn;
    private double cost;

    public Book(String isbn) {
        this.isbn = isbn;
    }

    public Book(String title, String isbn, double cost) {
        this.title = title;
        this.isbn = isbn;
        this.cost = cost;
    }

    public String getTitle() {
        return title;
    }

    public String getIsbn() {
        return isbn;
    }

    public double getCost() {
        return cost;
    }

    public String toString() {
        return "> " + this.title + " ($" + this.cost + ")";
    }

}

3.服务器

服务器扩展UnicastRemoteObject并实现RMIInterface 。 在主要方法中,我们将名称为“ MyBookstore”的服务器绑定在本地主机上。 为了简单起见,而不是使用数据库或File ,我们创建了initializeList()方法,该方法用代表我们Bookstore拥有的书的Book type Objects填充List (仅是5本书,但是5本书很棒!)。

我们还需要为服务器添加一个serialVersionUID ,但是由于我们在此示例中设计的服务器打算仅存在于一台计算机上,因此我们无需三思而后行,因此只需设置default serialVersionUID 。 但是,如果服务器类也已分发,则必须确保该类的serialVersionUID在实现该类的所有平台上都相同。

Bookstore.java
package com.mkyong.rmiserver;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import com.mkyong.rmiinterface.Book;
import com.mkyong.rmiinterface.RMIInterface;

public class Bookstore extends UnicastRemoteObject implements RMIInterface {

    private static final long serialVersionUID = 1L;
    private List<Book> bookList;

    protected Bookstore(List<Book> list) throws RemoteException {
        super();
        this.bookList = list;
    }

    //The client sends a Book object with the isbn information on it 
    //(note: it could be a string with the isbn too)
    
    //With this method the server searches in the List bookList 
    //for any book that has that isbn and returns the whole object
    @Override
    public Book findBook(Book book) throws RemoteException {
        Predicate<Book> predicate = x -> x.getIsbn().equals(book.getIsbn());
        return bookList.stream().filter(predicate).findFirst().get();
    }

    @Override
    public List<Book> allBooks() throws RemoteException {
        return bookList;
    }

    private static List<Book> initializeList() {
        List<Book> list = new ArrayList<>();
        list.add(new Book("Head First Java, 2nd Edition", "978-0596009205", 31.41));
        list.add(new Book("Java In A Nutshell", "978-0596007737", 10.90));
        list.add(new Book("Java: The Complete Reference", "978-0071808552", 40.18));
        list.add(new Book("Head First Servlets and JSP", "978-0596516680", 35.41));
        list.add(new Book("Java Puzzlers: Traps, Pitfalls, and Corner Cases", "978-0321336781", 39.99));
        return list;
    }

    public static void main(String[] args) {
        try {
            Naming.rebind("//localhost/MyBookstore", new Bookstore(initializeList()));
            System.err.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server exception: " + e.getMessage());
        }
    }

}

4.客户

客户端通过RMIInterface Object “查找”服务器,该RMIInterface Object “查找”对与我们作为参数传递的名称相关联的远程对象的引用。 我们刚刚描述的是Naming.lookup("//localhost/MyBookstore"); 做。

Client的其余代码仅是创建一个工作示例,您可以希望尝试一下。

Customer.java
package com.mkyong.rmiclient;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.List;
import java.util.NoSuchElementException;

import javax.swing.JOptionPane;

import com.mkyong.rmiinterface.Book;
import com.mkyong.rmiinterface.RMIInterface;

public class Customer {

    private static RMIInterface look_up;

    public static void main(String[] args) throws
            MalformedURLException, RemoteException, NotBoundException {

        look_up = (RMIInterface) Naming.lookup("//localhost/MyBookstore");

        boolean findmore;
        do {

            String[] options = {"Show All", "Find a book", "Exit"};

            int choice = JOptionPane.showOptionDialog(null, "Choose an action", "Option dialog",
                    JOptionPane.DEFAULT_OPTION,
                    JOptionPane.INFORMATION_MESSAGE,
                    null, options, options[0]);

            switch (choice) {

                case 0:
                    List<Book> list = look_up.allBooks();
                    StringBuilder message = new StringBuilder();
                    list.forEach(x -> {
                        message.append(x.toString() + "\n");
                    });
                    JOptionPane.showMessageDialog(null, new String(message));
                    break;
                case 1:
                    String isbn = JOptionPane.showInputDialog("Type the isbn of the book you want to find.");
                    try {
                        Book response = look_up.findBook(new Book(isbn));
                        JOptionPane.showMessageDialog(null, "Title: " +
                                        response.getTitle() + "\n" + "Cost: $" +
                                        response.getCost(),
                                response.getIsbn(), JOptionPane.INFORMATION_MESSAGE);
                    } catch (NoSuchElementException ex) {
                        JOptionPane.showMessageDialog(null, "Not found");
                    }
                    break;
                default:
                    System.exit(0);
                    break;

            }
            findmore = (JOptionPane.showConfirmDialog(null, "Do you want to exit?", "Exit",
                    JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION);
        } while (findmore);
    }
}

5.如何运行

5.1用您喜欢的IDE创建四个Java文件或下载以下代码后,导航到您的源文件夹,如下所示。

java-rmi-distributed-objects-example-2

5.2我们需要做的第一件事就是编译源代码。 运行1. compileEverything.bat如果您下载了以下代码)或在目录中打开命令窗口并运行:

Terminal
$ javac src/com/mkyong/rmiinterface/RMIInterface.java src/com/mkyong/rmiinterface/Book.java src/com/mkyong/rmiserver/Bookstore.java src/com/mkyong/rmiclient/Customer.java

5.3通过访问各自的目录来确认您的源代码已编译:

java-rmi-distributed-objects-example-3

5.4接下来,我们需要启动rmiregistry。 再次运行2. startServer.bat或打开命令窗口并运行:

Terminal
$ cd src
$ start rmiregistry
$ java com.mkyong.rmiserver.Bookstore
java-rmi-distributed-objects-example-4

5.5如果RmiRegistry成功启动,将出现另一个窗口,如下所示:

java-rmi-distributed-objects-example-5

5.6现在我们可以运行我们的客户了:

打开一个新的命令提示符窗口(或从下载的文件中运行3. runClient.bat )并运行以下命令:

Terminal
$ cd src
$ java com.mkyong.rmiclient.Customer

5.6.1 Customer class运行并提示我们采取措施:

java-rmi-distributed-objects-example-6

5.6.2当我们单击“显示全部”按钮时:

java-rmi-distributed-objects-example-7

5.6.3单击“确定”按钮后:

java-rmi-distributed-objects-example-8

5.6.4因为我们不想退出,所以单击“否”按钮,将出现以下对话框。 我们输入一个ISBN(例如“ 978-0596009205”),然后单击“确定”。

java-rmi-distributed-objects-example-9

5.6.5如果在服务器列表中找到该书:

java-rmi-distributed-objects-example-10

5.6.6如果找不到:

java-rmi-distributed-objects-example-11

5.6.7该程序将继续询问以下人员:

java-rmi-distributed-objects-example-8

如果单击“是”按钮,程序将退出。 如果单击“否”,将使我们返回主菜单以选择一个动作,如5.6.1所示。

在关闭窗口之前,服务器将一直运行。 即使客户端关闭后,我们也可以打开一个新的甚至同时运行的多个客户端。

java-rmi-分布式对象示例12

下载源代码

下载– RMIObjects.zip (5 KB)

参考文献

  1. 可序列化的接口– Java API
  2. 远程– Java API
  3. UnicastRemoteObject – Java API
  4. Java RMI Hello World示例
  5. Wikipedia – Java远程方法调用
  6. 维基百科–分布式对象

翻译自: https://mkyong.com/java/java-rmi-distributed-objects-example/

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值