旗下导航:搜·么
当前位置:网站首页 > JAVA教程 > 正文

Java RMI图文详解(附示例)【JAVA教程】,Java

作者:搜教程发布时间:2019-12-25分类:JAVA教程浏览:45评论:0


导读:JavaRMI:Java长途要领挪用,即JavaRMI(JavaRemoteMethodInvocation)是Java编程言语里,一种用于完成长途历程挪用的运用...

Java RMI:Java长途要领挪用,即Java RMI(Java Remote Method Invocation)是Java编程言语里,一种用于完成长途历程挪用的运用顺序编程接口。

它使客户机上运转的顺序可以挪用长途效劳器上的对象。长途要领挪用特征使Java编程职员可以在收集环境中散布操纵。RMI悉数的主旨就是尽量简化长途接口对象的运用。

我们晓得长途历程挪用(Remote Procedure Call, RPC)可以用于一个历程挪用另一个历程(很可能在另一个长途主机上)中的历程,从而供应了历程的散布才能。Java 的 RMI 则在 RPC 的基础上向前又迈进了一步,即供应散布式对象间的通讯。

RMI(Remote Method Invocation)为长途要领挪用,是许可运转在一个Java假造机的对象挪用运转在另一个Java假造机上的对象的要领。

这两个假造机可所以运转在雷同盘算机上的差别历程中,也可所以运转在收集上的差别盘算机中。

【JavaRMI】

一、事情道理

RMI能让一个Java顺序去挪用收集中另一台盘算机的Java对象的要领,那末挪用的效果就像是在本机上挪用一样。浅显的讲:A机械上面有一个class,经由过程长途挪用,B机械挪用这个class 中的要领。

RMI,长途要领挪用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是竖立散布式Java运用顺序的轻易门路。RMI是非常轻易运用的,然则它非常的壮大。

RMI的基础是接口,RMI构架基于一个重要的道理:定义接口和定义接口的细致完成是离开的。下面我们经由过程细致的例子,竖立一个简朴的长途盘算效劳和运用它的客户顺序

二、RMI包含部份:

1、长途效劳的接口定义

2、长途效劳接口的细致完成

3、桩(Stub)和框架(Skeleton)文件

4、一个运转长途效劳的效劳器

5、一个RMI定名效劳,它许可客户端去发明这个长途效劳

6、类文件的供应者(一个HTTP或许FTP效劳器)

7、一个须要这个长途效劳的客户端顺序

三、RMI的用处?

RMI的用处是为散布式Java运用顺序之间的长途通讯供应效劳,供应散布式效劳。

现在重要运用时封装在各个J2EE项目框架中,比方Spring,EJB(Spring和EJB均封装了RMI手艺)

在Spring中完成RMI:

①在效劳器端定义效劳的接口,定义特定的类完成这些接口;

②在效劳器端运用org.springframework.remoting.rmi.RmiServiceExporter类来注册效劳;

③在客户端运用org.springframework.remoting.rmi.RmiProxyFactoryBean来完成长途效劳的代办功用;

④在客户端定义接见与效劳器端效劳接口雷同的类

四、RMI的范围?

RMI现在运用Java长途音讯交流协定JRMP(Java Remote Messaging Protocol)举行通讯。JRMP是专为Java的长途对象制订的协定,因为JRMP是专为Java对象制订的,因而,RMI关于用非Java言语开发的运用体系的支撑不足。

不能与用非Java言语誊写的对象举行通讯(意义是只支撑客户端和效劳器端都是Java顺序的代码的长途挪用)。

五、RMI的运用范围?

因为客户机和效劳器都是运用Java编写的,两者平台兼容性的要求仅仅是两边都运转在版本兼容的Java假造机上。

六、RMI挪用长途要领的参数和返回值

当挪用长途对象上的要领时,客户机除了可以将原始范例的数据作为参数一外,还可以将对象作为参数来通报,与之相对应的是返回值,可以返回原始范例或对象,这些都是经由过程Java的对象序列化(serialization)手艺来完成的。(换而言之:参数或许返回值假如是对象的话必需完成Serializable接口)

七、 RMI运用顺序的基础模子

八、RMI体系构造

桩/框架(Stub/Skeleton)层:客户端的桩和效劳器端的框架;

长途援用(remote reference)层:处置惩罚长途援用行动

传送层(transport):衔接的竖立和治理,以及长途对象的跟踪

九、 RMI类和接口(完成一个简朴RMI须要用到的类)。

(一) Remote接口:是一个不定义要领的标记接口

Public interface Remote{}

在RMI中,长途接口声清楚明了可以从长途Java假造机中挪用的要领集。长途接口满足以下要求:

1、长途接口必需直接或间接扩大Java.rmi.Remote接口,且必需声明为public,除非客户端于长途接口在统一包中

2、在长途接口中的要领在声明时,除了要抛出与运用顺序有关的一场以外,还必需包含RemoteException(或它的超类,IOExcepion或Exception)非常

3、在长途要领声明中,作为参数或返回值声明的长途对象必需声明为长途接口,而非该接口的完成类。

(二) RemoteObject抽象类完成了Remote接口和序列化Serializable接口,它和它的子类供应RMI效劳器函数。

(三) LocateRegistry final()类用于获得特定主机的指导长途对象注册效劳器顺序的援用(即建立stub),或许建立能在特定端口吸收挪用的长途对象注册效劳顺序。

效劳器端:向其他客户机供应长途对象效劳

SomeService servcie=……;//长途对象效劳

1、Registry registry=LocateRegisty.getRegistry();//Registry是个接口,他继续了Remote,此要领返回当地主机在默许注册表端口 1099 上对长途对象 Registry 的援用。

2、getRegistry(int port) 返回当地主机在指定 port 上对长途对象 Registry 的援用;

3、getRegistry(String host) 返回指定 host 在默许注册表端口 1099 上对长途对象 Registry 的援用;

4、getRegistry(String host, int port) 返回指定的 host 和 port 上对长途对象 Registry 的援用

5、registry.bind(“I serve”,service);// bind(String name,Remote obj) 绑定对此注册表中指定 name 的长途援用。name : 与该长途援用相干的称号 obj : 对长途对象(通常是一个 stub)的援用

6、unbind(String name)移除注册表中指定name的绑定。

7、rebind(String name,Remote obj)从新绑定,假如name已存在,然则Remote不一样则替代,假如Remote一样则抛弃现有的绑定

8、lookup(String name) 返回注册表中绑定到指定 name 的长途援用,返回Remote

9、String[] list() 返回在此注册表中绑定的称号的数组。该数组将包含一个此注册表中挪用此要领时绑定的称号快照。

客户机端:向效劳器供应响应的效劳要求。

Registry registry=LocateRegisty.getRegistry();
SomeService servcie=(SomeService)registry.lookup(“I serve”);
Servcie.requestService();

(四) Naming类和Registry类相似。

客户端:

Naming.lookup(String url)
url 花样以下"rmi://localhost/"+长途对象援用

效劳器端:

Registry registry=LocateRegistry.createRegistry(int port);
Naming.rebind(“service”,service);

(五) RMISecurityManager类

在RMI援用顺序中,假如没有设置平安治理器,则只能从当地类途径加载stub和类,这可以确保运用顺序不受由长途要领挪用所下载的代码损害

在从长途主机下载代码之前必需实行以下代码来装置RMISecurityManager:

System.setSecurityManager(new RMISecurityManager());

十、demo开发

为了编写一个demo,我们分为两部份,一部份是server端的代码,一部份是client端的代码,client端的代码重要是为了运用server端的代码。固然这个代码是非常简朴的,只是为了申明问题,实际的运用会使比较复杂的。

(一) 我们的目标

竖立一个server端的java project,包含长途端的代码,定义接口,定义接口完成,然后在竖立一个client端的java project,经由过程RMI运用远端效劳中的要领。

(二) 我们的代码构造

(三) 长途效劳代码

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,完成implements Serializable序列化接口。也就是可以在client和server端举行传输的可序列化对象。

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. 定义server端的主顺序进口。

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");
        }
}

(四) client端代码

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图文详解(附示例)的细致内容,更多请关注ki4网别的相干文章!

标签:Java


欢迎 发表评论: