一个RMI初学者写的小程序

说明:程序由7个文件组成
请将这7个文件放在d:\rmi目录下面,
然后用记事本打开compile and run.bat, 运行cmd, 逐条执行里面的命令,(若直接点击则不会启动客户端)

================================================
IServer.java RMI 远程服务接口
ServerImpl.java RMI 远程服务实现类
Client.java RMI 本地客户端
RmiUtil.java RMI 工具类
config.properties RMI配置参数
my.policy RMI安全授权
compile and run.bat cmd编译和运行命令
================================================


IServer.java :

package rmi;

/**
 * RMI 远程服务接口
 * 
 * @author [email protected]
 * @since 1.6
 * @version %I%, %G%
 */
public interface IServer extends java.rmi.Remote {

	/**
	 * 响应反馈字符串
	 * 
	 * @param num 反馈字符串重复的次数
	 * @return 反馈字符串
	 */
	public String response(int num) throws java.rmi.RemoteException;

	/**
	 * 动态调用方法
	 * 
	 * @param method 要调用的方法名(空参)
	 * @return 反馈字符串
	 */
	public String request(String method) throws java.rmi.RemoteException;

}




ServerImpl.java :

package rmi;

import java.lang.reflect.Method;
import java.net.URL;
import java.util.Map;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.RMIClassLoader;
import java.rmi.registry.*;
import rmi.RmiUtil;

/**
 * RMI 远程服务实现类
 * 
 * @author [email protected]
 * @since 1.6
 * @version %I%, %G%
 */
public class ServerImpl extends UnicastRemoteObject implements IServer {
	
	/**
	 * 版本序列号
	 */
	public static final long serialVersionUID = 1L;

	/**
	 * 无参的构造方法
	 */
	public ServerImpl() throws java.rmi.RemoteException {
		super();
	}

	/**
	 * 响应反馈字符串
	 * 
	 * @param num 反馈字符串重复的次数
	 * @return 反馈字符串
	 */
	public String response(int num) throws RemoteException {
		// 获取配置参数
		Map<String, String> map = RmiUtil.getConfig();
		String response = "";
		for (int i = 0; i < num; i++) {
			response += "[" + (i + 1) + "]" + map.get("response") + "\n";
		}

		return response;
	}

	/**
	 * 动态调用方法
	 * 
	 * @param method 要调用的方法名(空参)
	 * @return 反馈字符串
	 */
	public String request(String method) throws RemoteException {

		try {

			// 获取class
			// Class<?> c = Class.forName("rmi.ServerImpl");
			Class<?> c = this.getClass();
			// 获取method指定的方法
			Method m = c.getMethod(method);
			// 获取所有 定义了的方法
			Method ms[] = c.getDeclaredMethods();
			System.out.println("\nThe methods of rmi.ServerImpl :\n ");
			for (int i = 0; i < ms.length; i++) {
				System.out.println(ms[i].toString());
			}
			// 动态执行方法
			// return (String) m.invoke(c.newInstance());
			return (String) m.invoke(this);

		} catch (Exception e) {
			e.printStackTrace();
			return "Error: Cannot Invoke The Method: " + method;
		}

	}

	/**
	 * 响应反馈字符串
	 * 
	 * @return 反馈字符串
	 */
	public String feedback() throws RemoteException {
		// 获取配置参数
		Map<String, String> map = RmiUtil.getConfig();		
		
		try {
			// 远程类的字节码codebase
			URL base=new URL("http://" + map.get("host") + "/");
			// 远程类的全限定名称
			String name = "rmi.Client";
			// RMI 进行动态类加载
			RMIClassLoader.loadClass(base,name); 
			// 加载远程类字节码后调用函数
			Client.remoteCall();
			
		} catch (Exception e) {
			e.printStackTrace();
		}	
		
		return map.get("request");
	}

	/**
	 * 主函数
	 * 
	 * @param args 主函数参数
	 */
	public static void main(String[] args) {
		// 设置RMI的安全策略
		RmiUtil.setSecurityManager();
		try {
			// 获取配置参数
			Map<String, String> map = RmiUtil.getConfig();
			// RMI服务对象
			ServerImpl obj = new ServerImpl();
			// 注册端口,并返回Registry对象
			Registry reg = RmiUtil.createRegistry(
				Integer.parseInt(map.get("port"))
			);
			// 绑定服务对象
			RmiUtil.rebind(reg, map.get("name"), obj);
			System.out.println("RmiServer Running...");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}





Client.java:

package rmi;

import rmi.RmiUtil;
import java.util.Map;

/**
 * RMI 本地客户端
 * 
 * @author [email protected]
 * @since 1.6
 * @version %I%, %G%
 */
public class Client {

	/**
	 * 加载远程类字节码后调用函数
	 */
	public static void remoteCall(){
		System.out.println("Remote Calling...");		
	} 
	
	/**
	 * 主函数
	 * 
	 * @param args 主函数参数
	 */
	public static void main(String args[]) {
		// 设置rmi安全策略
		RmiUtil.setSecurityManager();
		try {
			// 获取配置参数
			Map<String, String> map = RmiUtil.getConfig();
			// rmi服务主机名
			String host = map.get("host");
			// rmi服务端口
			String port = map.get("port");
			// rmi服务名
			String name = map.get("name");
			// 反馈字符串重复的次数
			int num = Integer.parseInt(map.get("num"));
			// 要动态调用的方法名
			String method = map.get("method");
			// rmi服务url地址
			String url = "rmi://" + host + ":" + port + "/" + name;
			// 通过RMI服务url地址,获取RMI服务对象
			IServer obj = (IServer) RmiUtil.lookup(url);
			// 响应反馈字符串,重复num次
			String response = obj.response(num);
			// 动态调用method方法
			String request = obj.request(method);

			System.out.println("RmiClient Running...");
			System.out.println("url: " + url);
			System.out.println(response);
			System.out.println(request);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}






RmiUtil.java :

package rmi;

import java.rmi.*;
import java.util.Map;
import java.util.HashMap;
import java.rmi.registry.*;
import java.io.*;
import java.util.Properties;

/**
 * RMI 工具类
 * 
 * @author [email protected]
 * @since 1.6
 * @version %I%, %G%
 */
public final class RmiUtil {

	/**
	 * 是否第一次打印出配置参数
	 * <p>
	 * <code>true</code> 第一次打印<br>
	 * <code>false</code> 非第一次打印(略过打印)<br>
	 */
	public static boolean isFirstPrint = false;

	/**
	 * 注册RMI端口,并返回Registr对象
	 * 
	 * @param port RMI端口
	 * @return Registr对象
	 */
	public static Registry createRegistry(int port) throws RemoteException {
		Registry reg = null;
		try {
			// 如果该端口未被注册,则抛异常
			reg = LocateRegistry.getRegistry(port);
			// 获取该端口注册的rmi对象
			reg.list();
		} catch (RemoteException e) {
			try {
				// 捕获异常,端口注册
				reg = LocateRegistry.createRegistry(port);
			} catch (RemoteException e2) {
				e2.printStackTrace();
			}
		}

		return reg;

	}

	/**
	 * 通过Registry对象, 绑定RMI服务
	 * 
	 * @param reg Registry对象
	 * @param name RMI服务名
	 * @param obj RMI服务对象
	 */
	public static void rebind(Registry reg, String name, Remote obj)
			throws Exception {
		try {
			reg.rebind(name, obj);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 直接通过Naming绑定RMI服务
	 * 
	 * @param name RMI服务名
	 * @param obj RMI服务对象
	 */
	public static void rebind(String name, Remote obj) throws Exception {
		try {
			Naming.rebind(name, obj);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 通过RMI服务url地址,获取RMI服务对象
	 * 
	 * @param url RMI服务url地址
	 * @return RMI服务对象
	 */
	public static Remote lookup(String url) throws Exception {

		try {
			return Naming.lookup(url);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 配置RMI安全策略
	 */
	public static void setSecurityManager() {
		System.setSecurityManager(new RMISecurityManager());
	}

	/**
	 * 从config.properties获取配置参数
	 * 
	 * @return 配置参数
	 */
	public static Map<String, String> getConfig() {

		Map<String, String> map = null;

		try {
			// RmiUtil类的上级目录的绝对地址
			String path = RmiUtil.class.getResource("").toString();
			// config.properties的绝对地址
			path += "config.properties";
			// windows下去掉file:/
			path = path.replace("file:/", "");
			// windows下将/替换为\
			path = path.replace("/", "\\");
			// 拿到config.properties的InputStream
			InputStream in = new BufferedInputStream(new FileInputStream(path));
			Properties p = new Properties();
			// 读取config.properties内容
			p.load(in);

			// 读取config.properties的显示字符集
			String encode = p.getProperty("encode");
			map = new HashMap<String, String>();
			// 逐个将配置参数转换为指定的字符集
			map.put("encode", new String(
				p.getProperty("encode").getBytes("ISO8859-1"), encode)
			);
			map.put("name", new String(
				p.getProperty("name").getBytes("ISO8859-1"), encode)
			);
			map.put("host", new String(
				p.getProperty("host").getBytes("ISO8859-1"), encode)
			);
			map.put("port", new String(
				p.getProperty("port").getBytes("ISO8859-1"), encode)
			);
			map.put("response", new String(
				p.getProperty("response").getBytes("ISO8859-1"), encode)
			);
			map.put("request", new String(
				p.getProperty("request").getBytes("ISO8859-1"), encode)
			);
			map.put("num", new String(
				p.getProperty("num").getBytes("ISO8859-1"), encode)
			);
			map.put("method", new String(
				p.getProperty("method").getBytes("ISO8859-1"), encode)
			);

			// 只有在第一次调用才打印配置参数
			if (!isFirstPrint) {
				isFirstPrint = true;
				System.out.println();
				System.out.println("============= config datas start ================");
				System.out.println("config path: " + path);
				System.out.println("encode: " + map.get("encode"));
				System.out.println("name: " + map.get("name"));
				System.out.println("host: " + map.get("host"));
				System.out.println("port: " + map.get("port"));
				System.out.println("response: " + map.get("response"));
				System.out.println("request: " + map.get("request"));
				System.out.println("num: " + map.get("num"));
				System.out.println("method: " + map.get("method"));
				System.out.println("============= config datas end ================");
				System.out.println();
			}

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

		return map;

	}

}





config.properties:

# RMI配置参数

# 配置文件的显示字符集
encode=gbk

# 远程RMI绑定的服务名
name=RmiServer

# 远程RMI的主机名
host=localhost

# 远程RMI的端口
port=8765

# 反馈字符串1
response=你好,rmi反馈成功

# 反馈字符串2
request=方法调用成功

# 反馈字符串重复的次数
num=10

# 要动态调用的方法名
method=feedback




my.policy :

grant{
	permission java.security.AllPermission;
};


compile and run.bat :


d:
cd d:\
cd rmi
java -d .. *.java
cd ../
rmic -d . rmi.ServerImpl

start rmiregistry
java -Djava.security.policy=d:\rmi\my.policy rmi.ServerImpl
java -Djava.security.policy=d:\rmi\my.policy rmi.Client


你可能感兴趣的:(java,rmi,远程过程调用)