为什么要用RMI
在这次的项目中,对于客户端与服务器之间的通信,想了许多办法,由于做的是富客户端应用,最终将技术选定在了RMI和Java-sockets两种之间,其中RMI的灵活性不高,客户端和服务器端都必须是java编写,但使用比较方便,反观java-sockets,虽然比较灵活,但需要自己规定服务器端和客户端之间的通信协议。比较麻烦,几经权衡,最终还是选择RMI来进行服务器-客户端通信
文件上传问题
在使用java-rmi的过程中,必然会遇到一个文件上传的问题,由于在rmi中无法传输文件流(比如rmi中的方法参数不能是FileInputStream之类的),那么我们只好选择一种折中的办法,就是先用FileInputStream将文件读到一个Byte数组中,然后把这个Byte数组作为参数传进RMI的方法中,然后在服务器端将Byte数组还原为outputStream,这样就能通过RMI来传输文件了
这样做也有缺点,就是无法检验传输过来的数据的准确性,汗。。。
下面我就一个实例来讲解一下
文件结构
FileClient
packagermiupload; importjava.io.BufferedInputStream; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.IOException; importjava.net.MalformedURLException; importjava.rmi.Naming; importjava.rmi.NotBoundException; importjava.rmi.RemoteException; publicclassFileClient{ publicFileClient(){ //TODOAuto-generatedconstructorstub } publicstaticvoidmain(String[]args){ try{ FileDataServicefileDataService=(FileDataService)Naming.lookup("rmi://localhost:9001/FileDataService"); fileDataService.upload("/Users/NeverDie/Documents/test.mp4",newFileClient().fileToByte("/Users/NeverDie/Music/test.mp4")); }catch(MalformedURLException|RemoteException|NotBoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } //这个方法比较重要,通过这个方法把一个名为filename的文件转化为一个byte数组 privatebyte[]fileToByte(Stringfilename){ byte[]b=null; try{ Filefile=newFile(filename); b=newbyte[(int)file.length()]; BufferedInputStreamis=newBufferedInputStream(newFileInputStream(file)); is.read(b); }catch(FileNotFoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnb; } }
FileDataService
packagermiupload; importjava.net.URL; importjava.rmi.Remote; importjava.rmi.RemoteException; publicinterfaceFileDataServiceextendsRemote{ //这里的filename应该是该文件存放在服务器端的地址 publicvoidupload(Stringfilename,byte[]file)throwsRemoteException; }
FileDataService_imp
packagermiupload; importjava.io.BufferedOutputStream; importjava.io.File; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.IOException; importjava.net.URL; importjava.rmi.RemoteException; importjava.rmi.server.RMIClientSocketFactory; importjava.rmi.server.RMIServerSocketFactory; importjava.rmi.server.UnicastRemoteObject; publicclassFileDataService_impextendsUnicastRemoteObjectimplementsFileDataService{ publicFileDataService_imp()throwsRemoteException{ } @Override publicvoidupload(Stringfilename,byte[]fileContent)throwsRemoteException{ Filefile=newFile(filename); try{ if(!file.exists()) file.createNewFile(); BufferedOutputStreamos=newBufferedOutputStream(newFileOutputStream(file)); os.write(fileContent); }catch(FileNotFoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } ;} }
FileServer
packagermiupload; importjava.net.MalformedURLException; importjava.rmi.Naming; importjava.rmi.RemoteException; importjava.rmi.registry.LocateRegistry; publicclassFileServer{ FileDataServicefileDataService; publicFileServer(){ try{ fileDataService=newFileDataService_imp(); LocateRegistry.createRegistry(9001); Naming.rebind("rmi://localhost:9001/FileDataService",fileDataService); }catch(RemoteExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(MalformedURLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } /** *@paramargs */ publicstaticvoidmain(String[]args){ newFileServer(); } }
也不要说曾经失去,失去的不是永远失去,得到的不是永远拥有,