RMI开发 Step By Step

本文详细介绍Java RMI(远程方法调用)的实现过程,包括接口定义、服务端实现、客户端开发等步骤,帮助读者理解RMI的工作原理。

 

    RMI(Remote Method Invocation)RMI是分布式对象软件包,它简化了在多台计算机上的JAVA应用之间的通信。RMI从JDK1.1以后开始支持。    
    RMI系统采用类似CORBA的对象请求代理机制,桩(Stub)是远程对象在客户端的代理,客户程序中的远程对象引用其实是对本地脏的引用。桩负责将远程调用请求通过远程引用层和传输层转发给服务端的框架(skeleton),再由框架将请求分派给服务程序中的对象实现。
    远程引用层分为客户端与服务端两个相互协作的组件,负责完成远程调用的语义。
    传输层也分为客户端与服务器两部分,负责建立与管理连接,跟踪远程对象,以及将调用请求分派给合适的对象实现实例。在服务端,传输层将调用请求向上转发给远程引用层,远程引用层作相应处理后转发给框架,由框架向上调用服务程序中的对象实现,对象实现执行真正的方法调用任务。远程调用返回结果送回客户程序的路线与调用请求的传送路线刚好相反,首先经过服务端的框架、远程引用层和传输层,再向上经过客户端的传输层、远程引用层和桩。
    RMI体系结构图


    RMI在桩/框架层利用了两种关键技术。一种是java语言志用的对象串行化(object serialization)技术,该技术支持将对象的类型与值信息转为平坦的字节流形式,并可利用这种串行化表示重建与原对象状态相同的同类型对象,从而实现对象状态的持久性或网络传输,桩和框架利用这一技术对远程调用的参数与返回值进行打包与解包。另一种技术是动态类装载(dynamic class loading),用于在程序动态远行时装载客户程序所需的框,并支持java语言内建的类型检查与类型转换机制。

    第一步,定义接口,继承java.rmi.Remote

 程序代码
package zizz.rmi;

/**
* 定义一个问候者的接口.
* @author ZIZZ
* @Company manbuchina
* Create-Time:2007-8-16 下午11:06:48
*/

public interface Greeter extends java.rmi.Remote{
    
    String greetByName(String name) throws java.rmi.RemoteException;
    
}


    第二步,定义实现,继承UnicastRemoteObject

 程序代码
package zizz.rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
* 问候者的实现.
* @author ZIZZ
* @Company manbuchina
* Create-Time:2007-8-16 下午11:08:46
*/

public class GreeterImpl extends UnicastRemoteObject implements Greeter {

    /**
     * serialVersionUID
     */

    private static final long serialVersionUID = -5870885426008943753L;
    
    /**
     *
     * @throws RemoteException
     */

    public GreeterImpl() throws RemoteException {
        //继承了UnicastRemoteObject,必须实现相应的构造器
        super();
    }

    public String greetByName(String name) throws RemoteException {
        return "您好," + name;
    }

}


    第三步,开发服务器端

 程序代码
package zizz.rmi;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;

/**
* 服务程序
* @author ZIZZ
* @Company manbuchina
* Create-Time:2007-8-16 下午11:10:54
*/

public class GreeterServer {
    
    public static void main(String[] args){
        try {
            GreeterImpl greeterImpl = new GreeterImpl();
            //绑定服务对象
            try {
                Naming.bind("SayHello", greeterImpl);
            } catch (AlreadyBoundException e) {
                e.printStackTrace();
            }
            System.out.println("系统已经成功绑定服务对象.");
        } catch (RemoteException e) {
            System.out.println("错误信息为:" + e.getMessage());
            e.printStackTrace();
        } catch (MalformedURLException e) {
            System.out.println("错误信息为:" + e.getMessage());
            e.printStackTrace();
        }
    }
}


    第四步,使用rmic产生客户端桩
    rmic zizz.rmi.GreeterImpl
    使用rmic将会产生一个GreeterImpl_Stub.class的新文件
    第五步,将产生的客户端桩及接口copy到客户端
    将GreeterImpl_Stub.class,Greeter.class这两个文件,使用jar命令打个包,取名叫rmiclient.jar
    命令如下:
    jar cvf rmiclient.jar zizz/rmi/GreeterImpl_Stub.class zizz/rmi/Greeter.class
    第六步,编写客户端

 程序代码
package zizz.rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
* RMI客户端
* @author ZIZZ
* @Company manbuchina
* Create-Time:2007-8-16 下午11:25:29
*/

public class GreeterClient {
    
    public static void main(String[] args){
        try {
            //如果是其它服务器,则查找 rmi://server_name/SayHello
            Greeter greeter = (Greeter)Naming.lookup("rmi://127.0.0.1/SayHello");
            System.out.println(greeter.greetByName("ZIZZ"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (NotBoundException e) {
            e.printStackTrace();
        }
    }

}


    第七步,使用rmiregistry起用服务,监听1099端口
    在命令行下打入rmiregistry,启用RMI注册表。
    注意,运行该注册表必须进入工程的Classpath下,也就是说,跟第八步运行服务器端必须在同一个路径
    第八步,启用服务器端,将服务对象绑定到rmigegistry当中
    java zizz.rmi.GreeterServer
    第九步,运行客户端,查看结果
    java zizz.rmi.GreeterClient

    其实RMI开发是非常简单的,关键就是要把原理搞清楚,把开发顺序搞清楚就可以了。如果返回的结果是一个对象,那该对象必须实现串行化接口,不然,程序在运行期间将会报错。

> Task :kaptGenerateStubsDebugKotlin FAILED e: java.lang.IllegalStateException: Error during writing proto for descriptor: public interface IRemoteAnimationRunner : android.os.IInterface defined in android.view in file IRemoteAnimationRunner.java Source file: D:\base\libs\WindowManager\Shell\build\generated\aidl_source_output_dir\debug\out\android\view\IRemoteAnimationRunner.java at org.jetbrains.kotlin.incremental.JavaClassesTrackerImplKt.convertToProto(JavaClassesTrackerImpl.kt:99) at org.jetbrains.kotlin.incremental.JavaClassesTrackerImpl$onCompletedAnalysis$2.invoke(JavaClassesTrackerImpl.kt:70) at org.jetbrains.kotlin.incremental.JavaClassesTrackerImpl$onCompletedAnalysis$2.invoke(JavaClassesTrackerImpl.kt:69) at org.jetbrains.kotlin.util.PerformanceCounter.time(PerformanceCounter.kt:90) at org.jetbrains.kotlin.incremental.JavaClassesTrackerImpl.onCompletedAnalysis(JavaClassesTrackerImpl.kt:69) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:102) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:77) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:256) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:247) at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:115) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:247) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:87) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:43) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:165) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:50) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:463) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:62) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:477) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:400) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:281) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:125) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:657) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:105) at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1624) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.lang.UnsupportedOperationException: Null should not appear in annotation arguments at org.jetbrains.kotlin.serialization.AnnotationSerializer$valueProto$1$1.visitNullValue(AnnotationSerializer.kt:145) at org.jetbrains.kotlin.serialization.AnnotationSerializer$valueProto$1$1.visitNullValue(AnnotationSerializer.kt:56) at org.jetbrains.kotlin.resolve.constants.NullValue.accept(constantValues.kt:250) at org.jetbrains.kotlin.serialization.AnnotationSerializer.valueProto(AnnotationSerializer.kt:56) at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:41) at org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase.serializeFunction(SerializerExtensionBase.kt:63) at org.jetbrains.kotlin.incremental.JavaClassesSerializerExtension.serializeFunction(JavaClassesSerializerExtension.kt:64) at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:375) at org.jetbrains.kotlin.serialization.DescriptorSerializer.classProto(DescriptorSerializer.kt:136) at org.jetbrains.kotlin.incremental.JavaClassesTrackerImplKt.convertToProto(JavaClassesTrackerImpl.kt:97) ... 42 more FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':kaptGenerateStubsDebugKotlin'. > A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction > Internal compiler error. See log for more details * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. For more on this, please refer to https://docs.gradle.org/8.7/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation. BUILD FAILED in 1m 12s 52 actionable tasks: 44 executed, 8 up-to-date
09-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值