`
yuancihang
  • 浏览: 145042 次
  • 性别: Icon_minigender_1
  • 来自: 洛阳
社区版块
存档分类
最新评论

一个基于RMI的小巧好用的框架

    博客分类:
  • java
阅读更多

最近有用到rmi技术,需要实现Remote接口,需要抛出RemoteException异常,极其不爽,遂封装之,封装之后只需普通

POJO对象即可!

该框架核心有三个类,一个服务端类RMIEndpoint,一个客户端类RMIProxyFactory,一个通用接口GenericRmiService

 

先看一下用法:

 

服务端用法:

RMIEndpoint.addService(User.class, new UserImpl());
		try {
			RMIEndpoint.publish(8888);
		} catch (Exception e) {
			e.printStackTrace();
		}
 

 

 

客户端用法:

try {
			User user = RMIProxyFactory.getProxy(User.class, "localhost", 8888);
			System.out.println(user.say("11111"));
			System.out.println(user.say("11111"));
			System.out.println(user.say("11111"));
		} catch (Exception e) {
			e.printStackTrace();
		}
 

 

 

用起来简单吧!User是普通的接口,UserImpl是普通的POJO对象.

 

 

下面来看看三个核心类内部。

服务端点类:

package com.yuan.common.rmi;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yuan.common.util.ReflectUtil;

public class RMIEndpoint {

	private static final Logger LOG = LoggerFactory.getLogger(RMIEndpoint.class);
			
	private static ConcurrentMap<String, Object> serviceMap = new ConcurrentHashMap<String, Object>();
	private static String HOSTNAME;
	
	public static void addService(Object service){
		serviceMap.put(service.getClass().getName(), service);
	}
	public static void addService(Class<?> iface, Object service){
		serviceMap.put(iface.getName(), service);
	}
	
	/**
	 * 服务端多个IP则必须设置
	 * @param hostName
	 */
	public static void setHostName(String hostName){
		System.setProperty("java.rmi.server.hostname" , hostName); 
		HOSTNAME = hostName;
	}
	
	public static void publish() throws RemoteException, MalformedURLException, UnknownHostException{
		publish(1099);
	}
	public static void publish(int port) throws RemoteException, MalformedURLException, UnknownHostException{
		LocateRegistry.createRegistry(port); //注册端口
		
		GenericRmiService rmiService = new GenericRmiService(){
			private static final long serialVersionUID = 1L;

			public Object doService(String serviceName, String methodName, Object[] args) throws RemoteException {
				if(serviceMap.containsKey(serviceName)){
					Object service = serviceMap.get(serviceName);
					try {
						return ReflectUtil.execMethod(service, methodName, args);
					} catch (Exception e) {
						LOG.warn(e.getMessage(), e);
						throw new RemoteException(e.getMessage(), e);
					}
				}
				LOG.warn("RMI服务" + serviceName + "不存在!");
				throw new RemoteException("RMI服务" + serviceName + "不存在!");
			}
		};
		UnicastRemoteObject.exportObject(rmiService, 0); //随机通信端口
		if(HOSTNAME == null){
			HOSTNAME = InetAddress.getLocalHost().getHostAddress();
		}
		Naming.rebind("rmi://"+HOSTNAME+":"+port+"/GenericRmiService", rmiService);
	}
	
}
 

 

客户端代理工厂类:

package com.yuan.common.rmi;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.Naming;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class RMIProxyFactory {

	private static final ConcurrentMap<String, Object> proxyCache = new ConcurrentHashMap<String, Object>();
	
	public static void clearProxyCache(){
		proxyCache.clear();
	}
	
	public static <T> T getProxy(Class<T> iface, String host, int port) throws Exception{
		final String serviceName = getServiceName(iface);
		if(proxyCache.containsKey(serviceName)){
			return (T)proxyCache.get(serviceName);
		}
		
		final GenericRmiService rmiService = (GenericRmiService)Naming.lookup("rmi://"+host+":"+port+"/GenericRmiService");
		
		InvocationHandler h = new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
				try {
					Object r = rmiService.doService(serviceName, method.getName(), args);
					return r;
				} catch (Exception e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}
		};
		
		Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[]{iface}, h);
		proxyCache.put(serviceName, proxy);
		return (T) proxy;
	}
	
	private static <T> String getServiceName(Class<T> iface) throws IllegalArgumentException, IllegalAccessException{
		Field[] fs = iface.getFields();
		for(Field f : fs){
			if(f.getName().equals("SERVICENAME")){
				return (String)f.get(null);
			}
		}
		
		return iface.getName();
	}
}
 

 

 

RMI通用接口:

package com.yuan.common.rmi;

import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface GenericRmiService extends Remote, Serializable {

	public Object doService(String serviceName, String methodName, Object[] args)throws RemoteException;
	
}
 

 

 

User接口:

package tmp.rmi;

public interface User {

	public String say(String msg);
	
}
 

 

 

UserImpl对象:

 

package tmp.rmi;

public class UserImpl implements User {

	@Override
	public String say(String msg) {
		System.out.println("=== " + msg);
		System.out.println("=== " + Thread.currentThread());
		return "qqqqqqqqq";
	}

}
 

 

注意RMI支持并发访问,所以UserImpl必须是线程安全的!

 

附件中是完整源代码!

 

 

  • rmi.zip (7.4 KB)
  • 下载次数: 104
分享到:
评论

相关推荐

    基于RMI的网络聊天室

    我们实现的聊天工具采用传统的C/S模式,其功能类似于WEB聊天室,用户可以在聊天室中...客户端软件提供用户登录服务器,发送信息的功能,服务器程序则负责接收用户登录请求转发聊天信息并提供一个界面对服务器进行管理。

    rmi程序框架示例

    RMI(Remote Method Invocation)是Java平台上的一个关键特性,它允许Java对象在不同的 JVM(Java虚拟机)之间进行通信,实现分布式计算。这个“rmi程序框架示例”提供了有关如何构建和运行RMI应用程序的基本知识。 ...

    基于rmi的远程控制

    RMI的工作原理基于对象的分布式计算模型,它允许一个Java对象调用位于另一台机器上的对象的方法。这一过程对程序员来说透明,使得编写分布式应用变得相对简单。以下是关于RMI的关键知识点: 1. **注册表(Registry...

    (转)通用JAVA RMI服务器框架

    本资源分享的是一个通用的RMI服务器框架,它为开发者提供了一个基础平台,用于快速搭建和实现自己的RMI服务。 首先,我们来理解RMI的基本概念。RMI是一种Java平台上的机制,它允许Java对象在不同的JVM之间进行通信...

    基于RMI的远程控制器(JAVA版)

    【基于RMI的远程控制器(JAVA版)】是一款利用Java的...总之,基于RMI的远程控制器(JAVA版)利用了Java的强大特性,提供了跨网络的远程控制功能,对于学习RMI和分布式系统开发的开发者来说,是一个有价值的实践案例。

    基于RMI 的分布式议程服务

    在本项目中,我们构建了一个基于RMI的分布式议程服务,旨在提供一个跨网络的会议管理平台,让不同客户端可以共享和操作会议议程。 首先,我们需要理解RMI的核心概念。RMI系统由两部分组成:远程接口和远程对象。...

    基于RMI分布计算实例

    1. **RMI概念**:RMI是Java平台提供的一个标准API,它允许开发者在Java应用中调用远程对象的方法,就像调用本地对象一样。RMI的核心组件包括远程接口、远程对象、注册表和客户机。 2. **远程接口**:远程接口定义了...

    基于RMI和Socket的带数据库的java聊天软件 客户端和服务器端

    RMI是Java平台内建的一种远程对象调用技术,它允许一个Java对象调用另一个在不同JVM上的对象的方法,非常适合分布式系统中的组件交互。Socket则是Internet协议的基础,它提供了进程间通信的能力,让运行在不同设备上...

    Java开发基于rmi的数据库中间件设计源码.zip

    分布式对象技术课程实践:基于rmi的数据库中间件设计,并利用中间件建立一个数据库应用(Java web项目)。 需求分析 数据库操作中间件: 提供数据库连接接口。该接口可使“数据库操作中间件”连接当前主流的数据库...

    如何在Spring框架中使用RMI技术.zip

    RMI是Java提供的一种机制,使得一个Java对象能够调用运行在不同JVM上的另一个Java对象的方法。这涉及到三个关键组成部分:远程接口、远程实现和RMIServer。远程接口定义了可供远程访问的方法,远程实现实现了这些...

    基于JAVA RMI的聊天室

    **基于JAVA RMI的聊天室** ...综上所述,这个基于JAVA RMI的聊天室项目展示了如何利用RMI进行分布式编程,实现跨网络的实时通信。通过进一步开发和扩展,它可以成为一个功能丰富的多用户交流平台。

    分布式Java RMI实现的学生成绩管理系统

    分布式Java RMI(Remote Method Invocation)技术是一种在Java平台中实现分布式计算的重要工具,它允许一个对象调用在不同 JVM(Java Virtual Machine)上的另一个对象的方法。在这个项目中,我们利用RMI构建了一个...

    RMI-IIOP 基于SUN

    1. 客户端通过RMI调用远程对象的一个方法,这个调用会被转换为一个RMI调用请求。 2. RMI stub(桩)接收到请求后,会将RMI调用转换为IIOP消息。 3. IIOP消息通过网络发送到服务器端的ORB。 4. 服务器端ORB接收到IIOP...

    基于RMI的分布式消息传送模型

    RMI允许Java对象在不同的JVM之间进行交互,仿佛它们是在同一个进程中一样。这种模型常用于构建复杂的分布式系统,如电力系统中的各个模块之间的通信。 在本文档中提到的RMI平台,由两个主要部分组成:消息传送模块...

    一种基于RMI得分布式架构设计

    基于RMI的分布式架构设计,详细描述了如何架构RMI分布式系统,并阐述了原理实现

    一个java RMI应用实例 构建简单的RMI应用

    定义一个扩展远程接口(Remote)的接口,这个接口方法将供给客户端调用,该接口中的每...如果客户端和服务端不在同一台电脑上,则需要对刚才定义的服务类采用rmic 编译一个客户端的框架类_stub并拷贝到客户端的类路径下

    基于RMI分布式会议系统

    【基于RMI分布式会议系统】是一种使用Java Remote Method Invocation(远程方法调用)技术构建的分布式应用程序,旨在模拟和管理虚拟会议。RMI是Java提供的一种机制,它允许在不同的Java虚拟机(JVM)之间透明地调用...

Global site tag (gtag.js) - Google Analytics