分布式系统大作业
姓名:
班级:
题目:
学号:
日期:
袁康益
硕 8058
RMI
3118105279
2019.4.12
题目一:基于 RMI 技术的远程词典应用
1.RMI 介绍
RMI(即 Remote Method Invoke 远程方法调用)。在 Java 中,只要一个类
extends 了 java.rmi.Remote 接口,即可成为存在于服务器端的远程对象,供客户
端访问并提供一定的服务。JavaDoc 描述:Remote 接口用于标识其方法可以从非
本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在
“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。
同时,远程对象必须实现 java.rmi.server.UniCastRemoteObject 类,这样才能
保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以 Socket
的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端
本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,
用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户
端的请求之后调用远程方法来响应客户端的请求。
2.实验过程及代码
首先创建接口 Translator:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Translator extends Remote {
public String translate(String str) throws RemoteException;
}
使用 serviceimpl 实现接口的方法,因为题目要求,使用
Map 存储了少量的英文词汇对应表,并放在构造函数中:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
public class ServiceImpl extends UnicastRemoteObject implements
Translator {
private static final long serialVersionUID = 1L;
private Map vocabulary=new HashMap();
protected ServiceImpl() throws RemoteException {
vocabulary.put("success", "成功");
vocabulary.put("is","是");
vocabulary.put("happy","幸福");
vocabulary.put("want","想要");
vocabulary.put("he","他");
vocabulary.put("she","她");
vocabulary.put("it","它");
// TODO Auto-generated constructor stub
}
@Override
public String translate(String str) {
// TODO Auto-generated method stub
return vocabulary.get(str);
}}
Server 服务器,实现 translate 的注册:
import javax.naming.Context;
import javax.naming.InitialContext;
public class Server {
public static void main(String[] args) {
try {
Translator TranService=new ServiceImpl();
Context namingcontext=new InitialContext();
namingcontext.rebind("rmi://localhost/TranService",
TranService);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("服务器向命名表注册了一个远程服务对象");
}
}
Client 客户端程序,调用服务器端的方法,实现单词的查询:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Client extends JFrame{
private static final long serialVersionUID = 1L;
String url="rmi://localhost/";
public void ui(){
JTextField word=new JTextField();
JButton search=new JButton("search");
JPanel p1=new JPanel();
search.setBounds(0, 0, 50, 50);
p1.add(search);
JTextField result=new JTextField();
add(word,BorderLayout.NORTH);
add(p1,BorderLayout.CENTER);
add(result,BorderLayout.SOUTH);
setTitle("Client");
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
search.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
try{
Context namingcontext=new InitialContext();
Translator
TranService=(Translator)namingcontext.lookup(url+"TranService");
result.setText(TranService.translate(word.getText()));
}catch(Exception e){
e.printStackTrace();
}
}
});
}
public static void main(String[] args) {
Client au=new Client();
au.ui(); }}
3.实验结果:
首先在命令行下找到 class 所在的目录,设置 classpath 指向该目录,然后启
动 rmiregistry,接着启动服务器,运行客户端实现查找。
图 1 设置 classpath
图 2 启动 rmiregistry
图 3 启动 Server,实现服务注册
图 4 客户端实现查询