1. RMI 인터페이스
스터브(stub)라고도 하죠. 클라이언트에서는 lookup 후 가져온 Remote클래스를 여기서의 Stub로 캐스트하여 메소드를 호출합니다.package jo; import java.rmi.Remote; import java.rmi.RemoteException; public interface SampleRMI extends Remote { public int doSomething() throws RemoteException; }
2. RMI 구현 클래스
인터페이스를 구현한 클래스입니다. Skeleton이라고 합니다.package jo; import java.io.Serializable; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class SampleRMIObj extends UnicastRemoteObject implements SampleRMI, Serializable { private static final long serialVersionUID = 16308199599625625L; // stateful or stateless? private int counter; public SampleRMIObj() throws RemoteException { super(); } @Override public int doSomething() throws RemoteException { counter++; System.out.println("do something here. counter is " + counter); return counter; } }Stateful인지 Stateless인지 확인하기 위해 counter값을 변수로 두었습니다.
3. 등록하기
이제 오브젝트를 공개합니다. rmiregistry를 이용하는데요. rmiregistry.exe 를 실행하여 1099 포트를 listening합니다.package jo; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; public class RMIRegister { public static void main(String[] args) throws Exception { SampleRMI rmi = new SampleRMIObj(); int counter = rmi.doSomething(); System.out.println("server counter is " + counter); // Properties props = new Properties(); // props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); // props.put(Context.PROVIDER_URL, "rmi://localhost"); // // Context ctx = new InitialContext(props); // ctx.bind("sample", rmi); Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); //registry.rebind("sample", UnicastRemoteObject.exportObject(rmi, 0)); //任意ポート //registry.rebind("sample", UnicastRemoteObject.exportObject(rmi, 1099)); //1099ポート // SampleRMIObjが既にUnicastRemoteObjectを継承しているからこちらを使う。(UnicastRemoteObject.exportObjectは使用しない) // http://www.coderanch.com/t/210349/java/java/object-exported-exception-RMI registry.rebind("sample", rmi); System.out.println("ok. rmi object is registed."); } }위 샘플에서는 간단하게 Registry 클래스를 이용하였습니다.
4. 사용해보기
이제 분산환경의 여러대의 클라이언트에서 접속해보세요. 클라이언트에서 실행되는게 아니라 서버에서 CPU연산이 되므로 분산환경에서 고려해야할 排他制御등의 문제가 해결되었네요~~package jo; import java.rmi.Naming; import java.rmi.Remote; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; public class RMIClient { public static void main(String[] args) throws Exception { // Properties props = new Properties(); // props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); // props.put(Context.PROVIDER_URL, "rmi://localhost"); // // InitialContext ictx = new InitialContext(props); // SampleRMI rmi = (SampleRMI) ictx.lookup("sample"); Remote r = (Remote)Naming.lookup("sample"); SampleRMI rmi = (SampleRMI) r; int counter = rmi.doSomething(); System.out.println("client counter is " + counter); } }실행을 할때마다 counter 값이 증가하는걸 알 수 있습니다. 즉, Stateful 이죠. ]]>