在JDK5.0以前的版本中,需要用rmic命令来为远程对象生成静态的代理类,而在JDK5.0中,RMI框架会在运行时自动为远程对象生成动态代理类,本人使用的JDK版本为“1.7.0_65”
例子中总共有四个文件,四个文件在同一个目录下
1. Calculator.java 接口文件,必须实现java.rmi.Remote接口,该接口定义了所有的提供远程服务的功能,每个定义的方法都必须抛出一个java.rmi.RemoteException异常
import java.rmi.*;
//该接口定义了所有的提供远程服务的功能,该接口继承自Remote,每个定义的方法都必须抛出一个RemoteException异常
public interface Calculator extends Remote{
public long add(long a,long b)throwsjava.rmi.RemoteException;
public long sub(long a,long b)throwsjava.rmi.RemoteException;
public long mul(long a,long b)throwsjava.rmi.RemoteException;
public long div(long a,long b)throwsjava.rmi.RemoteException;
}
2.CalculatorImpl.java类文件,该类为远程服务的具体实现类,使用java.rmi.server.UnicastRemoteObject类去连接RMI系统,并且远程类的构造方法必须声明抛出RemoteException.
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
//远程服务的具体实现类,使用UnicastRemoteObject类去连接RMI系统
public class CalculatorImpl extends UnicastRemoteObject implements Calculator{
protected CalculatorImpl() throws RemoteException {
super();//该调用激活UnicastRemoteObject中的代码完成RMI的连接和远程对象的初始化
// TODO Auto-generated constructor stub
}
@Override
public long add(long a, long b) throws RemoteException {
// TODO Auto-generated method stub
return a+b;
}
@Override
public long sub(long a, long b) throws RemoteException {
// TODO Auto-generated method stub
return a-b;
}
@Override
public long mul(long a, long b) throws RemoteException {
// TODO Auto-generated method stub
return a*b;
}
@Override
public long div(long a, long b) throws RemoteException {
// TODO Auto-generated method stub
return a/b;
}
}
3.CalculatorServer.java文件,服务器程序类,服务器程序的一大任务就是向rmiregistry注册表注册远程对象。从JDK1.3以上版本开始,RMI的命名服务API被整合到JNDI中。在JNDI中,javax.naming.Context接口声明了注册、查找、以及注销对象的方法。
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class CalculatorServer {
public CalculatorServer() throws NamingException{
try {
Calculator calculator=new CalculatorImpl();
//注册通讯端口,不注册会抛出异常
LocateRegistry.createRegistry(6600);
//注册通讯路径
Context context=new InitialContext();
context.rebind("rmi://211.69.205.40:6600/CalculatorService",calculator);
System.out.println("Service start");
}catch(RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws NamingException {
// TODO Auto-generated method stub
new CalculatorServer();
}
}
4. CalculatorClient.java客户端程序
public class CalculatorClient {
public static void main(String[] args) throws NamingException {
// TODO Auto-generated method stub
try {
Context context=new InitialContext();
Enumeration<NameClassPair>e=context.list("rmi://211.69.205.40:6600/");
Calculatorcalculator=(Calculator) Naming.lookup("rmi://211.69.205.40:6600/CalculatorService");
//////////////////////////测试//////////////////////////
Class class1=calculator.getClass();
//System.out.println(class1.getName());
Class[] classes=class1.getInterfaces();
System.out.println(classes.length);
for(int i=0;i<classes.length;i++)
System.out.println(classes[i].getName());
///////////////////////////////////////////////////////
System.out.println(calculator.add(5,6));
}catch(MalformedURLException | RemoteException | NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行,先运行CalculatorServer程序,结果如下:
运行CalculatorClient程序,结果如下:
更多细节,参考java网络编程精解 孙卫琴