基于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注册服务启动成功后为下图所示界面,这样就能够创建注册表,在注册表中存储远程对象信息。
2、编译服务器端和客户端代码
服务器端(命令行):
javac –classpath . -d . Translator.java
javac –classpath . -d . TranslatorImpl.java
客户端(命令行):
javac –classpath . -d . SearchDictionary.java
3、启动服务器
Java –Djava.security.policy=policy.txt –classpath . TranslatorImpl
4、启动客户端
Java –Djava.security.policy=policy.txt –classpath . SearchDictionary