Java RMI: Java 원격 메소드 호출 또는 Java RMI(Java 원격 메소드 호출)는 Java 프로그래밍 언어로 원격 프로시저 호출을 구현하는 데 사용되는 애플리케이션 프로그래밍 인터페이스입니다.
클라이언트에서 실행되는 프로그램이 원격 서버의 개체를 호출할 수 있게 해줍니다. 원격 메소드 호출 기능을 사용하면 Java 프로그래머가 네트워크 환경에서 작업을 분산할 수 있습니다. RMI의 전체 목적은 원격 인터페이스 개체의 사용을 최대한 단순화하는 것입니다.
우리는 한 프로세스에서 RPC(원격 프로시저 호출)를 사용하여 다른 프로세스(아마도 다른 원격 호스트)의 프로세스를 호출하여 프로세스 배포 기능을 제공할 수 있다는 것을 알고 있습니다. Java의 RMI는 RPC를 기반으로 한 단계 더 발전했습니다. 즉, 분산 객체 간의 통신을 제공합니다.
RMI(Remote Method Invocation)는 하나의 Java 가상 머신에서 실행 중인 객체가 다른 Java 가상 머신에서 실행 중인 객체의 메소드를 호출할 수 있도록 하는 원격 메소드 호출입니다.
이 두 가상 머신은 동일한 컴퓨터의 서로 다른 프로세스에서 실행될 수도 있고 네트워크의 서로 다른 컴퓨터에서 실행될 수도 있습니다.
【JavaRMI】
1. 작동 원리
RMI를 사용하면 Java 프로그램이 네트워크의 다른 컴퓨터에 있는 Java 개체의 메서드를 호출할 수 있으며 호출 효과는 네트워크에서 호출하는 것과 같습니다. 로컬 머신. 평신도의 관점에서 말하면: 머신 A에는 클래스가 있고 원격 호출을 통해 머신 B는 이 클래스의 메서드를 호출합니다.
RMI, 원격 메소드 호출(Remote Method Invocation)은 Enterprise JavaBeans의 백본이며 분산 Java 애플리케이션을 구축하는 편리한 방법입니다. RMI는 사용하기 매우 쉽지만 매우 강력합니다.
RMI의 기초는 인터페이스입니다. RMI 아키텍처는 인터페이스 정의와 인터페이스의 특정 구현 정의가 별개라는 중요한 원칙을 기반으로 합니다. 아래에서는 간단한 원격 컴퓨팅 서비스와 이를 사용하는 클라이언트 프로그램을 구축하기 위한 구체적인 예를 사용합니다.
2. RMI에는 다음이 포함됩니다.
1. 원격 서비스 인터페이스 정의
2. . 스텁 및 스켈레톤 파일
4. 원격 서비스를 실행하는 서버
5. 클라이언트가 원격 서비스를 검색할 수 있는 RMI 이름 지정 서비스
6. 클래스 파일 제공자(HTTP 또는 FTP 서버) 7. 이 원격 서비스가 필요한 클라이언트 프로그램
3. RMI의 목적은?RMI의 목적은 분산 Java 애플리케이션 간의 원격 통신을 위한 서비스를 제공하는 것입니다. 현재 주요 애플리케이션은 Spring, EJB 등 다양한 J2EE 프로젝트 프레임워크에 캡슐화되어 있습니다(Spring과 EJB 모두 RMI 기술을 캡슐화합니다).
Spring에서 RMI 구현:
① 서버 측에서 서비스 인터페이스를 정의하고 특정 정의를 정의합니다. 클래스는 이러한 인터페이스를 구현합니다.
② 서비스를 등록하려면 서버 측에서 org.springframework.remoting.rmi.RmiServiceExporter 클래스를 사용하세요.
3 프록시 기능을 구현하려면 클라이언트 측에서 org.springframework.remoting.rmi.RmiProxyFactoryBean을 사용하세요.
4 서버와 동일한 서비스 인터페이스에 액세스하기 위해 클라이언트에 클래스를 정의합니다.
4. RMI의 한계는 무엇입니까? JRMP는 Java 원격 개체용으로 특별히 개발된 프로토콜입니다. JRMP는 Java 개체용으로 특별히 개발되었으므로 RMI는 Java 이외의 언어로 개발된 응용 프로그램 시스템에 대한 지원이 충분하지 않습니다. Java 이외의 언어로 작성된 개체와 통신할 수 없습니다. 즉, 클라이언트와 서버가 모두 Java 프로그램인 경우 원격 코드 호출만 지원됩니다.5. RMI 사용 시 제한 사항은 무엇입니까?
클라이언트와 서버가 모두 Java로 작성되었으므로 플랫폼 호환성에 대한 요구 사항은 두 당사자가 호환 가능한 버전의 Java 가상 머신에서 실행된다는 것입니다.6. 원격 메소드에 대한 RMI 호출의 매개변수 및 반환 값
원격 객체에 대한 메소드를 호출할 때, 클라이언트는 원래의 데이터 유형을 매개변수 1로 전달할 수도 있습니다. 이에 대응하는 반환값은 기본형이나 객체를 반환할 수 있으며 이는 Java의 객체 직렬화(직렬화) 기술을 통해 구현됩니다. (즉, 매개변수나 반환 값이 객체인 경우 직렬화 가능 인터페이스를 구현해야 합니다)7. RMI 애플리케이션의 기본 모델
8. RMI 아키텍처
스테이크/프레임워크(스텁/스켈레톤) 레이어: 클라이언트 측 스텁 및 서버 측 프레임워크 원격 참조 계층: 원격 참조 동작 처리 전송 계층: 연결 설정 및 관리, 원격 객체 추적 # 🎜🎜#9. 및 인터페이스(간단한 RMI를 완성하는 데 필요한 클래스). 3. 원격 메소드 선언에서 매개변수나 반환값으로 선언된 원격 객체는 인터페이스의 구현 클래스가 아닌 원격 인터페이스로 선언되어야 합니다. (2) RemoteObject 추상 클래스는 원격 인터페이스와 직렬화된 직렬화 가능 인터페이스를 구현합니다. 이 클래스와 해당 하위 클래스는 RMI 서버 기능을 제공합니다. (3) LocateRegistry final() 클래스는 특정 호스트의 부팅 원격 객체 등록 서버 프로그램에 대한 참조를 얻거나(즉, 스텁 생성) 원격 객체를 생성하는 데 사용됩니다. 특정 포트로 전화를 받을 수 있는 등록 서비스 프로그램입니다. 서버측: 다른 클라이언트에 원격 개체 서비스 제공 1. Registry Registry=LocateRegisty.getRegistry(); //Registry는 인터페이스이며 Remote를 상속합니다. 이 메서드는 기본 레지스트리 포트 1099의 원격 개체 레지스트리에 대한 로컬 호스트의 참조를 반환합니다. 2. getRegistry(int port) 지정된 포트의 원격 개체 레지스트리에 대한 참조를 반환합니다. 3 getRegistry(String 호스트) 지정된 호스트 등록 테이블 포트 1099의 원격 개체 레지스트리에 대한 참조 4. getRegistry(String 호스트, int 포트)는 지정된 호스트 및 포트#🎜의 원격 개체 레지스트리에 대한 참조를 반환합니다. 🎜# #🎜 🎜#8, lookup(String name) 레지스트리의 지정된 이름에 바인딩된 원격 참조를 반환하고 Remote 9, String[] list() 이 레지스트리 배열에 바인딩된 이름을 반환합니다. . 이 배열에는 이 메서드가 호출될 때 바인딩된 이 레지스트리에 있는 이름의 스냅샷이 포함됩니다. 클라이언트 측: 해당 서비스 요청을 서버에 제공합니다. Registry Registry=LocateRegisty.getRegistry(); Servcie.requestService();#🎜🎜 # (4) Naming 클래스는 Registry 클래스와 유사합니다. SomeService servcie=……;//远程对象服务
Client: Naming.lookup(String url)
url 格式如下"rmi://localhost/"+远程对象引用
Registry registry=LocateRegistry.createRegistry(int port); Naming.rebind(“service”,service);(5) RMI 참조 프로그램의 RMISecurityManager 클래스 , if 보안 관리자가 설정되지 않고 스텁과 클래스는 로컬 클래스 경로에서만 로드될 수 있으므로 원격 메서드 호출로 다운로드한 코드로 애플리케이션이 손상되지 않습니다원격 호스트에서 코드를 다운로드할 때 다음 RMISecurityManager:System.setSecurityManager(new RMISecurityManager());
10을 설치하기 전에 코드를 실행해야 합니다.
#🎜🎜 #데모를 작성하기 위해 두 부분으로 나누어서 하나는 서버 측 코드이고 다른 하나는 클라이언트 측 코드는 주로 서버 측에서 사용하는 코드입니다. 암호. 물론 이 코드는 문제를 설명하기 위해 매우 간단합니다. 실제 사용은 더 복잡합니다.
(1) 우리의 목적리모트 측 코드를 포함한 서버 측 Java 프로젝트를 빌드하고, 인터페이스를 정의하고, 인터페이스 구현을 정의한 후 클라이언트를 빌드합니다. -side java 프로젝트, RMI를 통해 원격 서비스에서 메소드를 사용합니다.
(2) 코드 구조
(3) 원격 서비스 코드1 . 원격 서비스의 인터페이스 정의첫 번째 단계는 서비스 인터페이스의 Java 코드를 설정하고 컴파일하는 것입니다. 이 인터페이스는 원격 서비스를 제공하기 위한 모든 기능을 정의합니다. 소스 프로그램은 다음과 같습니다.
UserManagerInterface.java
package cn.com.tt.rmiserver.stub; import java.rmi.Remote; import java.rmi.RemoteException; import cn.com.tt.rmiserver.bean.Account; public interface UserManagerInterface extends Remote{ public String getUserName() throws RemoteException; public Account getAdminAccount() throws RemoteException; }
인터페이스는 Remote 클래스를 상속해야 하며, 정의된 각 메서드는 RemoteException 예외 객체를 발생시킵니다.
2. 인터페이스의 구체적인 구현
두 번째 단계는 위의 인터페이스를 구현하는 것입니다.
UserManagerImp.java
package cn.com.tt.rmiserver; import java.rmi.RemoteException; import cn.com.tt.rmiserver.stub.UserManagerInterface; import cn.com.tt.rmiserver.bean.Account; public class UserManagerImp implements UserManagerInterface { public UserManagerImp() throws RemoteException { } private static final long serialVersionUID = -3111492742628447261L; public String getUserName() throws RemoteException{ return "TT"; } public Account getAdminAccount() throws RemoteException{ Account account=new Account(); account.setUsername("TT"); account.setPassword("123456"); return account; } }# 🎜🎜#3. 직렬화 가능 직렬화 인터페이스를 구현하는 Bean을 정의합니다. 즉, 클라이언트와 서버 간에 전송될 수 있는 직렬화 가능한 개체입니다. Account.java
package cn.com.tt.rmiserver.bean; import java.io.Serializable; public class Account implements Serializable,Cloneable{ private static final long serialVersionUID = -1858518369668584532L; private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }4. 서버 측에서 기본 프로그램 입구를 정의합니다. Entry.java
package cn.com.tt.rmiserver.entry; import java.rmi.AlreadyBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import cn.com.tt.rmiserver.UserManagerImp; import cn.com.tt.rmiserver.stub.UserManagerInterface; public class Entry { public static void main(String []args) throws AlreadyBoundException, RemoteException{ UserManagerImp userManager=new UserManagerImp(); UserManagerInterface userManagerI=(UserManagerInterface)UnicastRemoteObject.exportObject(userManager,0); // Bind the remote object's stub in the registry Registry registry = LocateRegistry.createRegistry(2002); registry.rebind("userManager", userManagerI); System.out.println("server is ready"); } }(4) 클라이언트 코드
1、把Server端的Account类和接口UserManagerInterface 导出Export成jar包,命名为:RmiServerInterface.jar。导入到client中。
2、项目——右键——Export——java——jar file——next——选择Account类和接口UserManagerInterface——命名为:RmiServerInterface.jar如下图:
3. 新建一个java Project,导入jar包,编写客户端代码。
4. 代码
ClientEntry.java
package weiblog.rmi; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import cn.com.tt.rmiserver.stub.UserManagerInterface; public class ClientEntry { public static void main(String []args){ try { Registry registry = LocateRegistry.getRegistry("localhost",2004); UserManagerInterface userManager = (UserManagerInterface)registry.lookup("userManager"); System.out.println("用户名是"+userManager.getAdminAccount().getUsername() +"密码"+userManager.getAdminAccount().getPassword()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NotBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
5. 先运行服务器端代码, 然后运行客户端代码,就会显示运行结果,客户端可以运行多次,每次都可以取得服务器端的对象。如果要再次运行客户端代码就需要更改端口号,如果不更改就会显示端口号被占用。
更多java知识请关注java基础教程栏目。
위 내용은 Java RMI에 대한 자세한 그래픽 설명(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!