我是否需要客户端,服务器和注册表上的所有类才能使用RMI? [英] Do I need all classes on the client, server and registry for RMI to work?

查看:89
本文介绍了我是否需要客户端,服务器和注册表上的所有类才能使用RMI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用RMI做我的第一步,我有一个简单的问题。

I'm doing my first steps with RMI, and I have a simple question.

我有一个.jar文件,它有一个来自a的几个方法的实现图书馆。
我想使用RMI在.jar文件中调用此方法。

I have a .jar file which has the implementation of several methods from a library. I want to call this methods in the .jar file using RMI.

我正在尝试创建一种包装器去做。

What I'm trying is to create a kind of a wrapper to do it.

所以,我正在做类似这样的事情:

So, I'm working on something like this:

接口类:这个接口有远程对象实现的方法。

Interface class: This interface has the methods to be implemented by the remote object.

实现类:这个类,有接口方法的实现,每个实现调用.jar文件中的相应方法。例如,jar文件有一个名为getDetails()的方法,它返回一个ResponseDetail对象。 ResponseDetail是我在.jar中的响应类。

Implementation class: This class, has the implementation of the interface methods, each implementation calls the corresponding method in the .jar file. E.g., the jar file has a method called getDetails(), and it returns a "ResponseDetail" object. ResponseDetail is a response class I have in the .jar.

服务器类:它将方法绑定到rmiregistry

Server class: it binds the methods to the rmiregistry

客户端类:它将使用实现中实现的方法。

Client class: it will consume the methods implemented in implementation.

到现在为止还挺好? :)

So far so good? :)

现在,我有一个lib文件夹,其中包含.jar文件。

Now, I have a lib folder where resides the .jar file.

server machine我已经部署了Interface,Implementation和Server类。我已经生成了存根,我成功地运行了rmiregistry,但是,有了这些细节:

In the server machine I have deployed the Interface, Implementation and Server classes. I've generated the stub, and I ran the rmiregistry successfully, but, with these details:

要启动rmiregistry,我必须在命令行中设置类路径引用.jar文件,否则我得到java.lang.NoClassDefFoundError。我用这个.sh文件做了:

To start the rmiregistry, I had to set the classpath in the command line to reference the .jar files, otherwise I get the java.lang.NoClassDefFoundError. I did it with this .sh file:

THE_CLASSPATH=
for i in `ls ./lib/*.jar`
do
    THE_CLASSPATH=${THE_CLASSPATH}:${i}
done

rmiregistry -J-classpath -J".:${THE_CLASSPATH}" 

要启动服务器,我还必须设置类路径引用.jar文件,否则,我得到java.lang.NoClassDefFoundError。我使用过这样的东西:

To start the server, I had to set the classpath as well to reference the .jar files, otherwise, I get the java.lang.NoClassDefFoundError. I've used something like this:

THE_CLASSPATH=
for i in `ls ./lib/*.jar` do
  THE_CLASSPATH=${THE_CLASSPATH}:${i}
done

java -classpath ".:${THE_CLASSPATH}" Server

客户端计算机:
运行Client.class文件客户端机器,我不得不将.jar文件复制到它,并在类路径中引用它们,否则,它不会运行,我得到java.lang.NoClassDefFoundError。我不得不在客户机上使用它:

Client machine: To run the Client.class file from the client machine, I had to copy the .jar files to it, and make reference to them in the classpath, because otherwise, it does not run and I get the java.lang.NoClassDefFoundError. I had to use this on the client machine:

THE_CLASSPATH=
for i in `ls ./lib/*.jar`
do
   THE_CLASSPATH=${THE_CLASSPATH}:${i}
done

java -classpath ".:${THE_CLASSPATH}" HelloClient

这可以吗?我的意思是,我是否必须将.jar文件复制到客户端机器以通过RMI执行方法?

Is this ok? I mean, do I have to copy the .jar files to the client machine to execute methods through RMI?

推荐答案

在JDK之前v5必须使用 rmic RMI编译器)生成RMI存根。这是从JDK v5自动完成的。此外,您还可以从Java代码中启动RMI注册表。要从简单的RMI应用程序开始,您可能需要按照以下步骤操作:

Prior to JDK v5 one had to generate the RMI stubc using the rmic (RMI Compiler). This is done automatically from JDK v5 on. Moreover, you can start the RMI Registry from within the Java code as well. To start with a simple RMI application you may want to follow the following steps:



  1. 创建界面:

  1. Create the interface:

import java.rmi.*;
public interface SomeInterface extends Remote {
  public String someMethod1() throws RemoteException;
  public int someMethod2(float someParameter) throws RemoteException;
  public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException;
}





  • 实施界面:

  • Implement the interface:

    
    import java.rmi.*;
    import java.rmi.server.*;
    public class SomeImpl extends UnicastRemoteObject implements SomeInterface {
      public SomeImpl() throws RemoteException {
        super();
      }
      public String someMethod1() throws RemoteException {
        return "Hello World!";
      }
      public int someMethod2( float f ) throws RemoteException {
        return (int)f + 1;
      }
      public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException {
        int i = someStruct.getInt();
        float f = someStruct.getFloat();
        someStruct.setInt(i + 1);
        someStruct.setFloat(f + 1.0F);
        return someStruct;
      }
    }
    





  • 实现在客户端和服务器之间传递的非原始可序列化对象:

  • Implement a non-primitive serializable object that is to be passed between a client and the server:

    
    import java.io.*;
    public class SomeStruct implements Serializable {
      private int i = 0;
      private float f = 0.0F;
      public SomeStruct(int i, float f) {
        this.i = i;
        this.f = f;
      }
      public int getInt() {
        return i;
      }
      public float getFloat() {
        return f;
      }
      public void setInt(int i) {
        this.i = i;
      }
      public void setFloat(float f) {
        this.f = f;
      }
    }
    





  • 实现服务器:

  • Implement the server:

    
    import java.rmi.*;
    import java.rmi.server.*;
    import java.rmi.registry.Registry;
    import java.rmi.registry.LocateRegistry;
    import java.net.*;
    import java.io.*;
    public class SomeServer  {
      public static void main(String args[]) {
        String portNum = "1234", registryURL;
        try{   
          SomeImpl exportedObj = new SomeImpl();
          startRegistry( Integer.parseInt(portNum) );
          // register the object under the name "some"
          registryURL = "rmi://localhost:" + portNum + "/some";
          Naming.rebind(registryURL, exportedObj);
          System.out.println("Some Server ready.");
        } catch (Exception re) {
          System.out.println("Exception in SomeServer.main: " + re);
        }
      }
      // This method starts a RMI registry on the local host, if it
      // does not already exist at the specified port number.
      private static void startRegistry(int rmiPortNum) throws RemoteException{
        try {
          Registry registry = LocateRegistry.getRegistry(rmiPortNum);
          registry.list( );  
          // The above call will throw an exception
          // if the registry does not already exist
        } catch (RemoteException ex) {
          // No valid registry at that port.
          System.out.println("RMI registry is not located at port " + rmiPortNum);
          Registry registry = LocateRegistry.createRegistry(rmiPortNum);
          System.out.println("RMI registry created at port " + rmiPortNum);
        }
      }
    }
    





  • 实现客户端:

  • Implement the client:

    
    import java.io.*;
    import java.rmi.*;
    import java.rmi.registry.Registry;
    import java.rmi.registry.LocateRegistry;
    public class SomeClient {
      public static void main(String args[]) {
        try {
          String hostName;
          String portNum = "1234";
          String registryURL = "rmi://localhost:" + portNum + "/some";
          SomeInterface h = (SomeInterface)Naming.lookup(registryURL);
          // invoke the remote method(s)
          String message = h.someMethod1();
          System.out.println(message);
          int i = h.someMethod2(12344);
          System.out.println(i);
          SomeStruct someStructOut = new SomeStruct(10, 100.0F);
          SomeStruct someStructIn  = new SomeStruct(0, 0.0F);
          someStructIn = h.someStructTest(someStructOut);
          System.out.println( someStructIn.getInt() );
          System.out.println( someStructIn.getFloat() );
        } catch (Exception ex) {
          ex.printStackTrace();
        }
      }
    }
    



  • 较大的客户端 - 服务器应用程序应分为三个模块: client server common (对于服务器和客户端代码之间共享的类,即本例中的远程接口和非基本对象)。然后,客户端应用程序将从类路径上的客户端 + 公共模块和 server + common 模块。

    A larger client-server application should be divided into three modules:client, server, and common (for classes shared between the server and client code, i.e. the remote interface and the non-primitive object in this example). The client application will then be created from client + common modules on the classpath and the server from server + common modules on the classpath.

    我用这个例子很多年了以前学习RMI的基础知识,它仍然有效。然而,它远非完美(使用默认的Java包,不正确的异常处理,主机名和端口参数是硬编码的,不可配置等)。

    I used this example many years ago to learn basics of RMI and it still works. However it is far from being perfect (default Java package used, incorrect exception handling, hostname and port parameters are hard-coded and not configurable, etc.)

    然而,它对初学者有好处。所有文件都可以放在一个目录中,并使用简单的 javac * .java 命令进行编译。然后可以使用 java SomeServer 启动服务器应用程序,通过启动 java SomeClient 命令启动客户端。

    Nevertheless, it is good for starters. All the files can be placed in one directory and compiled using the simple javac *.java command. The server application can then be started using the java SomeServer and the client one by launching the java SomeClient command.

    我希望这有助于理解Java RMI,事实上,它远比这复杂得多。

    I hope this helps to understand the Java RMI which is, in fact, far more complicated than just this.

    这篇关于我是否需要客户端,服务器和注册表上的所有类才能使用RMI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆