定义接口
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
*
* MyRemote.java
*
* 功 能: TODO
* 类 名: MyRemote.java
*
* ver 変更日 角色 担当者 変更内容
* ──────────────────────────────────────────────
* V1.00 2013-3-19 模块 苏若年 初版
*
* Copyright (c) 2013 dennisit corporation All Rights Reserved.
*
* Email:发送邮件
*
*
* Remote是个标记性的接口,意味着没有方法,然而它对RMI有特殊的意义,所以必须遵守这项规则,
* 注意这里用的是extends,接口是可以继承其他接口的
*
*/
public interface MyRemote extends Remote{
/**
* 远程的接口定义了客户端可以远程调用的方法,它是作为服务的多态化类,也就是说,客户端会
* 调动有实现此接口的stub,而此stub因为会执行网络和输入/输出工作,所以可能会发生各种
* 问题,客户端鼻息处理或声明异常来认知这一类风险,如果该方法在接口中声明异常,调用该方
* 法的所有程序都必须处理或再声明此异常.
*
* 远程方法的参数和返回值必须是primitive或serializable的.任何远程方法的参数都会被
* 打包通过网络传送,而这时通过序列化完成的,返回值也是一样.所以,如果使用的是自定义类型
* 时,必须对其序列化
* @return
* @throws RemoteException
* 所有接口中的方法都必须声明RemoteException
*/
public String sayHello() throws RemoteException;
}
业务实现
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
*
* MyRemoteImpl.java
*
* 功 能: TODO
* 类 名: MyRemoteImpl.java
*
* ver 変更日 角色 担当者 変更内容
* ──────────────────────────────────────────────
* V1.00 2013-3-19 模块 苏若年 初版
*
* Copyright (c) 2013 dennisit corporation All Rights Reserved.
*
* Email:发送邮件
*
* 为了要成为远程服务对象,对象必须要有与远程有关的功能,其中最简单的方法就是继承UnicastRemoteObject
* (来自java.rmi.server)以让这个父类处理这些工作
*
*/
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
/**
* 父类的构造函数声明了异常,所有你必须写出构造函数,因为它代表你的构造函数会调用有风险的程序代码
*
* UnicastRemoteObject有个小问题,它的构造函数会抛出RemoteException.处理它的唯一方式就是
* 对自己的实现声明一个构造,如此才会有地方可以声明出RemoteException.当类被初始化的时候,父类
* 的构造函数一定会被调用,如果父类的构造函数抛出异常,我们也必须声明的自定义的构造函数会抛出异常
* @throws RemoteException
*/
protected MyRemoteImpl() throws RemoteException {
}
/**
* 实现出接口所有的方法,但无需声明RemoteException
*/
@Override
public String sayHello(){
return "server says, rmi hello world !";
}
public static void main(String[] args) {
try {
/**
* 我们已经有了远程服务,还必须要让远程用户存取,这可以通过将它初始化并加进RMI Registry
* (它一定要运行起来,不然此程序就会失败).当注册对象时,RMI系统会把stub加到registry中,
* 因为这是客户端所需要的.使用java.rmi.Naming的rebind()来注册服务
*/
MyRemote service = new MyRemoteImpl();
/**
* 创建出远程对象,然后使用静态的Naming.rebind()来产生关联,所注册的名称会提供客户端查询
*/
Naming.rebind("Remote Hello World", service);
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端代码
import java.rmi.Naming;
/**
*
* MyRemoteClient.java
*
* 功 能: TODO
* 类 名: MyRemoteClient.java
*
* ver 変更日 角色 担当者 変更内容
* ──────────────────────────────────────────────
* V1.00 2013-3-19 模块 苏若年 初版
*
* Copyright (c) 2013 dennisit corporation All Rights Reserved.
*
* Email:发送邮件
*
*/
public class MyRemoteClient {
public void exec(){
try {
/**
* 客户端必须取得stub对象,因为客户端必须要调用它的方法.这就得靠RMI registry了.客户端会像查询电话
* 簿一样地搜索,找出上面有相符的名称的服务.
* 客户端查询RMIRegistry,返回stub对象
* Naming.lookup("rmi://127.0.0.1/Remote Hello World");
* 参数说明
* rmi://127.0.0.1/Remote Hello World
* 127.0.0.1表示主机名称或主机IP地址
* Remote Hello World必须要跟注册的名称一样
*
*/
MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/Remote Hello World");
String tmp = service.sayHello();
System.out.println(tmp);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyRemoteClient().exec();
}
}
对实现出的类(不是remote接口)执行rmic