基于RMI技术的远程词典应用

场景描述:

假设有一台应用服务器以RMI(或Socket编程)的方式向客户端提供英汉互译词典的服务。请尝试完成服务器端程序编码和一个客户端应用,并分别部署到两台计算机上进行测试。服务接口声明见附录。说明: 不考虑服务器端词典的容量,用数据库或使用Map在内存中保存少量的英汉词汇对应表。

源代码:

1、远程接口定义

定义翻译接口:

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

public interface Translator extends Remote{

    /**
     *
     * @param str 需要被翻译的单词
     * @return 英汉互译后的内容,如果词典中不包含此单词则返回null
     * @throws RemoteException
     */
    public String translate(String str) throws RemoteException;
}

2、服务器端实现

翻译接口的具体实现,同时继承了UnicastRemoteObject类。

在本次实验中,由于不考虑服务器端词典的容量,仅用Map构造了一个字典来存储少量的英汉词汇对应表。然后将实现的TranslatorImpl类使用RMI的命名空间绑定服务器的地址(这里使用的是本机测试地址),以便于客户端实现远程调用。

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;

public class TranslatorImpl extends UnicastRemoteObject implements Translator {

    private static final long serialVersionUID = 1L;

    private HashMap<String, String> dict = new HashMap<>();

    protected TranslatorImpl() throws RemoteException {
        super();
    }

    @Override
    public String translate(String str) throws RemoteException {
        dict.put("曲奇", "cookie");
        dict.put("奶酪", "cheese");
        dict.put("牛奶", "milk");
        dict.put("奶酪曲奇牛奶", "cheese cookie milk");
        dict.put("cookie", "曲奇");
        dict.put("cheese", "奶酪");
        dict.put("milk", "牛奶");
        dict.put("cheese cookie milk", "奶酪曲奇牛奶");
        return dict.get(str);
    }

    public static void main(String[] args) throws RemoteException {
        //java.rmi.registry.LocateRegistry.createRegistry(1099);
        System.setSecurityManager(new SecurityManager());
        try {
            TranslatorImpl tran = new TranslatorImpl();
            Naming.rebind("//127.0.0.1/TranslatorImpl", tran);
            System.out.println("词典服务器端已启动!");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
}

3、客户端实现

客户端SearchDictionary类首先使用RMI的命名空间找到服务器端定义的服务TranslatorImpl,然后输入要翻译的单词,便自动调用服务器端的词典功能,给出翻译结果。

import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.util.Scanner;

public class SearchDictionary {

    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        System.setSecurityManager(new RMISecurityManager());
        try {
            Translator tran = (Translator) Naming.lookup("//127.0.0.1/TranslatorImpl");
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入要翻译词语(输入quit退出):");
            String word = sc.nextLine();
            while (!word.equals("quit")) {
                System.out.println(word + "的意思是" + tran.translate(word));
                word = sc.nextLine();
            }

        } catch(Exception e) {
            e.printStackTrace();
        }

    }
}

4、创建policy文件

定义一个安全管理器配置文件,给定所有权限。

grant{
    permission java.security.AllPermission "","";
};

测试结果

1、启动RMI Registry服务

在命令行输入:

start rmiregistry

RMI注册服务启动成功后为下图所示界面,这样就能够创建注册表,在注册表中存储远程对象信息。

image-20220524230758195

2、编译服务器端和客户端代码

服务器端(命令行):

javac –classpath . -d . Translator.java
javac –classpath . -d . TranslatorImpl.java

客户端(命令行):

javac –classpath . -d . SearchDictionary.java

image-20220524231106167

3、启动服务器

Java –Djava.security.policy=policy.txt –classpath . TranslatorImpl

image-20220524231114181

4、启动客户端

Java –Djava.security.policy=policy.txt –classpath . SearchDictionary

5、效果展示

image-20220524231131109

posted @ 2022-05-24 23:14  Leventseleveil  阅读(250)  评论(0编辑  收藏  举报