RMIを使用する理由
このプロジェクトでは、リッチ クライアント アプリケーションに取り組んでいたため、クライアントとサーバー間の通信方法をさまざまに考えましたが、その中で最終的に RMI と Java ソケットの間のテクノロジを選択しました。RMI は柔軟性が高くありません。クライアントとサーバーの両方を Java で記述する必要がありますが、Java ソケットを使用するとより柔軟ですが、サーバーとクライアント間の通信プロトコルを定義する必要があります。かなり面倒だったので、何度か検討した結果、サーバーとクライアントの通信には RMI を選択しました。
ファイルアップロードの問題
java-rmi を使用するプロセスでは、必然的にファイルのアップロードの問題が発生します。rmi ではファイル ストリームを送信できないため (たとえば、rmi のメソッド パラメータを FileInputStream などにすることはできません)、妥協策を選択する必要があります。最善の方法は、まず FileInputStream を使用してファイルを Byte 配列に読み取り、次にこの Byte 配列をパラメータとして RMI メソッドに渡し、次に Byte 配列をサーバー側の OutputStream に復元することです。 RMIを通過ファイルを転送しましょう
これには、送信されたデータの正確性を検証できないという欠点もあります。
以下に例を挙げて説明しましょう。
ファイルクライアント
次のようにコードをコピーします。
パッケージ rmiupload;
インポートjava.io.BufferedInputStream;
java.io.ファイルをインポートします。
java.io.FileInputStreamをインポートします。
インポート java.io.FileNotFoundException;
インポート java.io.IOException;
インポート java.net.MalformedURLException;
java.rmi.Namingをインポートします。
インポート java.rmi.NotBoundException;
インポート java.rmi.RemoteException;
パブリック クラス FileClient {
public FileClient() {
// TODO 自動生成されたコンストラクター スタブ
}
public static void main(String[] args) {
試す {
FileDataService fileDataService = (FileDataService) Naming.lookup("rmi://localhost:9001/FileDataService");
fileDataService.upload("/Users/NeverDie/Documents/test.mp4", new FileClient().fileToByte("/Users/NeverDie/Music/test.mp4"));
catch (MalformedURLException | RemoteException | NotBoundException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
//このメソッドの方が重要です。このメソッドを通じて、filename という名前のファイルがバイト配列に変換されます。
private byte[] fileToByte(String filename){
byte[] b = null;
試す {
ファイル file = 新しいファイル(ファイル名);
b = 新しいバイト[(int) file.length()];
BufferedInputStream は = new BufferedInputStream(new FileInputStream(file));
is.read(b);
} catch (FileNotFoundException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} キャッチ (IOException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
bを返します。
}
}
ファイルデータサービス
パッケージ rmiupload;
java.net.URLをインポートします。
java.rmi.Remoteをインポートします。
インポート java.rmi.RemoteException;
パブリック インターフェイス FileDataService は Remote{ を拡張します
//ここでのファイル名は、ファイルがサーバー側に保存されているアドレスである必要があります
public void Upload(String filename, byte[] file) は RemoteException をスローします。
}
FileDataService_imp
次のようにコードをコピーします。
パッケージ rmiupload;
インポート java.io.BufferedOutputStream;
java.io.ファイルをインポートします。
インポート java.io.FileNotFoundException;
java.io.FileOutputStreamをインポートします。
インポート java.io.IOException;
java.net.URLをインポートします。
インポート java.rmi.RemoteException;
インポート java.rmi.server.RMIClientSocketFactory;
インポート java.rmi.server.RMIServerSocketFactory;
インポート java.rmi.server.UnicastRemoteObject;
public class FileDataService_imp extends UnicastRemoteObjectimplemented FileDataService{
public FileDataService_imp() は RemoteException をスローします {
}
@オーバーライド
public void Upload(String filename, byte[] fileContent) throws RemoteException{
ファイル file = 新しいファイル(ファイル名);
試す {
if (!file.exists())
file.createNewFile();
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
os.write(fileContent);
} catch (FileNotFoundException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} キャッチ (IOException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
; }
}
ファイルサーバー
次のようにコードをコピーします。
パッケージ rmiupload;
インポート java.net.MalformedURLException;
java.rmi.Namingをインポートします。
インポート java.rmi.RemoteException;
インポート java.rmi.registry.LocateRegistry;
パブリック クラス ファイルサーバー {
ファイルデータサービスファイルデータサービス;
public FileServer() {
試す {
fileDataService = 新しい FileDataService_imp();
LocateRegistry.createRegistry(9001);
Naming.rebind("rmi://localhost:9001/FileDataService", fileDataService);
} catch (RemoteException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
/**
* @param 引数
*/
public static void main(String[] args) {
新しいファイルサーバー();
}
}