0

RMI を (本から) 書くことにしました。コードも本から取りました。rmic でスタブを作成し、rmiregistry を開始しましたが、Java Start Server を作成することを決めたときに問題が発生しました。実際に直面した問題は次のとおりです。 java -classpath D:\RMI AddServer Exception:java.rmi.ServerException: RemoteExceptionサーバースレッドで発生しました。n ested exception は次のとおりです。 java.rmi.UnmarshalException: error unmarshalling arguments; ネストされた例外は次のとおりです: java.lang.ClassNotFoundException: AddServerImpl_Stubお願いし ます助けが必要です。

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

}

AddServer

   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 を使用してデータベースにアクセスしている場合は、クライアントにも jar を配置します。Hibernate は元のクラスを「変更」し、クライアントはそれをデシリアライズするためにこれを必要とします。
  5. サーバー側でも Spring を使用している場合、Spring -ormおよびspring-data-jpa jar をクライアントに含めることができます。
  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

簡単な答え: レジストリのクラスパスにスタブが必要です。

長い答え: rmic を使用していない過去 10 年間の 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 に答える