RMIベースのコンパクトで使いやすいフレームです。


もっと読む
最近はrmiの技術があります。Remoteインターフェースを実現する必要があります。RemoteExceptionの異常を抛り出す必要があります。
POJO対象でOK
フレームの核心は三つの種類があります。一つはサービスエンド類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 serviceMap = new ConcurrentHashMap();
	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 proxyCache = new ConcurrentHashMap();
	
	public static void clearProxyCache(){
		proxyCache.clear();
	}
	
	public static  T getProxy(Class 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  String getServiceName(Class 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