RMI(Remote Method Invocation)
다형성 기본 개념 이해하고 있어야한다..
다형성은 항상 상위(Super) 클래스의 멤버필드만 사용할수 있다..
(단 메서드는 상위 클래스의 메서드를 사용하나 재정의시에는 상속받은 클래스의 메서드를 사용한다..)
UnicastRemoteObject 같은 클래스에 이미 상속해 두었다..
가.원격 인터페이스 작성
1. 서버와 클라이언트에서 동시에 사용할 원격(Remote) 인터페이스를 생성한다...
인터페이스 작성규칙..
조건1. java.rmi.Remote를 상속받아야한다..
- 이 인터페이스에 있는 메서드는 로컬이 아닌 원격에서 사용할수 있어야 한다는 것을 명시하기 위해서이다..
조건2. 무조건 public 이어야한다..
- 원격은 클래스 내부에서의 접근만 허용하는 private 지정도 안될 것이고 상속의 관계에서 사용하는 protected지정도
안될것 이고 동일 package에서의 호출만 가능한 package지정도 안될 것이기 때문이다..
조건3. 메서드는 무조건 RemoteException 처리를 하여야한다..(예외발생처리)
ex) import java.rmi.*;
public interface Ex01 extends Remote {
public String Message() throws RemoteException; //인터넷상의 예외를 위해 반드시 처리..
//특정 메세지를 전송하기 위한 메서드..
public void printData() thorws RemoteException;
// 호출된 시간을 서버에 출력하는 메서드..
2. 서버에 바인딩될 클래스의 멤버 메서드를 재정의 한다..(클래스가 실제 요청이 있을경우 실행하는 부분..)
- 서버에서는 이 객체가 바인딩되어 있어야하고 클라이언트는 이 객체를 통해 서버의 내용을 실행할수 있다..
이 클래스는 외부 요청을 받기 위해 자신의 객체를 바인딩하기 때문에 직렬화가 되어있어야 하고 이전 단계에서 작성한
원격인터페이스를 구현해야한다..
나. 인터페이스를 구현한 실제 서버 클래스 작성
이 클래스는 인터페이스를 구현할 목적으로 만든 클래스로 원격으로 객체를 복사해서 통신할 수 있는 형태를 표현하기 위해
미리 만들어진 UnicastRemoteObject와 같은 계열의 클래스를 상속받아야 한다. 실제 서버 행동의 주체(동작되는)가 되는 클
래스이기도 하다..
구현 클래스의 규칙
조건1 : 무조건 public이어야 한다.
조건2 : 앞에서 만든 인터페이스를 상속받아 구현해 주어야한다.
(인터페이스를 상속받았으니 메서드를 재정의하는것은 당연..)
조건3 : UnicastRemoteObject 계열의 통신 클래스를 상속받아야한다.
(해당 통신의 하부 구조를 일부 구현해주고 객체의 직렬화를 만들어준다..)
조건4 : 이 클래스의 디폴트 생성자는 반드시 정의해야 한다. 또한 그 생성자는 RemoteException 처리.
(UnicastRemoteObject생성자에서 해당 예외를 발생시키기 때문)
ex)
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class Ex02 extends UnicastRemoteObject implements Ex01 {
public Ex02() throws RemoteException {
super();
}
public String Message() throws RemoteException {
printDate();
return "안녕하세요! 반갑습니다.";
}
public void printDate() throws RemoteException {
Date d = new Date();
System.out.println("Connect Date = " + d.toString());
}
}
다. 객체를 바인딩하는 Run 클래스 작성
이 클래스는 객체인 Ex02를 RMIRestry라는 데몬 서버에 바인딩시키는 역할을 한다. 여기에서 객체를 바인딩시키는
메서드는 Naming 클래스의 rebind()라는 매서드이다.. 객체의 이름은 임의로 apple로 정한다..
import java.rmi.*;
import java.net.*;
public class Ex03 {
public static void main(String[] args) {
try {
Ex02 sr = new Ex02();
System.out.println("Server Ready...");
Naming.rebind("apple", sr);
} catch (RemoteException ee) {
ee.printStackTrace();
} catch (MalformedURLException ee) {
ee.printStackTrace();
}
}
}
라. 클라이언트가 객체를 찾아 호출하는 클래스작성
클라이언트가 유일하게 작성하는 클래스를 서버의 객체를 복사해서 가지고 와서 사용할수 있도록한다.
이것의 실행조건은 당연히 1번에서 작성한 원격인터페이스가 동일한 폴더에 있어야 한다는 것이다.
그것을 통해 다형성의 개념으로 실행할 수 있기 때문이다. 객체를 찾는 방법으로 사용된 클래스는
Naming이라는 클래스의 static메서드인 lookup()이다.
import java.net.*;
import java.rmi.*;
public class Ex04 {
public static void main(String[] args) {
try {
Ex01 fr = (Ex01) Naming.lookup("rmi://원격시키고자 하는 서버 ip주소값/apple"); // 다형성...
String msg = fr.Message();
System.out.println("Message = " + msg);
} catch (RemoteException ee) {
ee.printStackTrace();
} catch (MalformedURLException ee) {
ee.printStackTrace();
} catch (NotBoundException ee) {
ee.printStackTrace();
}
}
}
< RMI 실행방법 (Dos화면에서)>
1. 네 개의 파일을 모두 컴파일한다..(시작->실행->cmd)
-> 관련파일경로 > java -d . *.java
2. 두번째 작성한 실제 서버 클래스를 RMI컴파일을 통해 스텁클래스(파일명_Stub.class)를 생성..
( 스텁클래스는 내부 통신의 통로 역할을 하게 된다..)
->관련파일경로 > rmic -d . Ex02
3.자바폴더의 bin폴더안에 rmiregistry.exe 파일을 실행하여 RMI서버를 가동한다.(새창이 생성됨)
( 보안경고창이 뜨면 차단해제 클릭~!) - 서버를 실행할수 있는 상태를 만든다..
4. 생성된 새창은 실행상태로 두고 기존에 컴파일시켰던 도스창으로 돌아와 세번쨰 예제인 서버 실행 클래스를
실행시킨다. 이것으로 RMI 서버에 객체를 바인딩할수 있다. - 서버실행상태
->관련파일경로 > java Ex03
(실행하면 "Server Ready..."라는 메세지가 뜬다.)
5. 마지막으로 또 하나의 Dos창을 열어 네번째 작성된 클래스를 통해 실행을 확인한다. 네번째 클래스는 다른 컴퓨터에
있어도 되지만 첫번째 예제로 작성된 Remote를 상속받은 interface와 함께 있어야 한다.
->관련파일경로 > java Ex04
(실행시 첫번째 도스창에 Date(날짜)값이 출력되고 입력창에는 "안녕하세요!반갑습니다"라는 메세지가 뜬다.)
출처 : http://shizuku.tistory.com/category/☆%20IT/JAVA