0

我决定写 RMI(从书中)也从书中获取代码。我用 rmic 创建了存根,并启动了 rmiregistry,但是当我致力于编写 java Start Server 时,我遇到了问题,实际上这是我面临的问题: java -classpath D:\RMI AddServer Exception:java.rmi.ServerException: RemoteException发生在服务器线程中;估计的异常是:java.rmi.UnmarshalException: error unmarshalling arguments; 嵌套的异常是: java.lang.ClassNotFoundException: AddServerImpl_Stub PLease 我需要帮助,因此我浪费了很多时间 :(

AddServerIntf.java

package rmi.app;
import java.rmi.*;
 public interface AddServerIntf extends Remote {
  double add(double d1,double d2) throws RemoteException;}

AddServerImpl

package rmi.app;
import java.rmi.*;
import java.rmi.server.*;
public class AddServerImpl  extends UnicastRemoteObject implements AddServerIntf {

public AddServerImpl() throws RemoteException {}

public double add(double d1, double d2) throws RemoteException {
        return d1+d2;
    }

}

添加服务器

   package rmi.app;
    import java.net.*;
  import java.rmi.*;
   public class AddServer {
public static void main(String[] args) {

    try {

    AddServerImpl addServerImpl = new AddServerImpl();
    Naming.rebind("AddServer", addServerImpl);      
    }
    catch (Exception e){
        System.out.println("Exception:"+e);
    }

}

  }

添加客户端

   package rmi.app;
   import java.rmi.Naming;
    public class AddClient {
public static void main(String[] args) {

    try{
        String addServerURL= "rmi://"+args[0]+ "/AddServer";
        AddServerIntf addServer =(AddServerIntf)Naming.lookup(addServerURL);
        System.out.println("The first number is:"+args[1]);
        double d1= Double.valueOf(args[1]).doubleValue();
        System.out.println("The second number is:"+args[2]);
        double d2= Double.valueOf(args[2]).doubleValue();
        System.out.println("the sum is:"+ addServer.add(d1,d2));

    }
    catch(Exception e){
        System.out.println("Exception : "+ e);
    }

}

     }
4

4 回答 4

2

我也在编写一个 Java RMI 应用程序,在使它工作之前我经历了很多。经过大量的研究和尝试和错误,我得到了这个“食谱”:

  1. 不要安装 SecurityManager;
  2. 不要使用策略文件;
  3. 确保您从一个 VM 移动到另一个 VM 的类在客户端和服务器类路径中(或在同一个 jar/war 中)。
  4. 如果您使用休眠进行数据库访问,请将罐子也放在客户端中。Hibernate“更改”了原始类,客户端将需要它来反序列化它;
  5. 如果您还在服务器端使用 Spring,您可能会在客户端中包含spring-ormspring-data-jpa jar,如果您遇到 ClassNotFoundException,然后是 JpaObjectRetrievalFailureException;
  6. 我没有在 jar 之外运行任何东西(根本没有 rmi 服务);
  7. 我没有在使用 Java 6 时创建存根。

我的服务器纯粹是这样做的:

try {
        try {
            LocateRegistry.createRegistry(SERVER_PORT);
        } catch (RemoteException e) {
            LocateRegistry.getRegistry(SERVER_PORT);
            e.printStackTrace();
        }
        System.setProperty("java.rmi.server.hostname", SERVER_HOST);
        connectionRequestHandler = new ConnectionRequestHandlerImpl();
        dataRequestHandler = new DataRequestHandlerImpl();
        String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/";
        Naming.rebind(rmiUrl + "ConnectionRequestHandler", connectionRequestHandler);
        Naming.rebind(rmiUrl + "DataRequestHandler", dataRequestHandler);
    } catch (RemoteException e1) {
        e1.printStackTrace();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

然后在客户端我正在做:

String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/";
    try {
        connectionRequestHandler = (ConnectionRequestHandler)Naming.lookup(rmiUrl + "ConnectionRequestHandler");
        dataRequestHandler = (DataRequestHandler)Naming.lookup(rmiUrl + "DataRequestHandler");
    } catch (MalformedURLException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (RemoteException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (NotBoundException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (Exception e ){
        e.printStackTrace();
        return;
    }

这就是它为我工作的方式。与第一次设置相比,您可能遇到的任何其他问题都很容易解决。

于 2013-03-22T17:54:53.107 回答
1

简短的回答:注册表需要在其类路径上有存根。

长答案:在过去 10 年内找到一个使用 rmic 的 rmi 教程,因为你不需要长时间做所有这些。

于 2013-03-22T17:46:26.773 回答
1

将 AddServerImpl 构造函数更改为调用 super(0)。然后你甚至不需要生成存根,更不用说部署它了。请参阅 UnicastRemoteObject 的 Javadoc 的序言。

于 2013-03-22T23:54:01.267 回答
0

从服务器代码目录启动 rmiregistry。(或)使用 -j 选项执行 请参阅如何设置 rmiregistry 使用的类路径?和 javadoc 参考[这里]

于 2015-09-26T22:28:47.083 回答