通过RMI下载UNIX系统上的文件

[size=large][b]Server端:[/b][/size]
1. 定义远程通讯的接口和与接口相关的类(这里只有RemoteFileInfo.java)。该接口必须继承接口Remote,它里面的方法都要抛出RemoteException异常。
[size=medium]FileManager.java[/size]

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface FileManager extends Remote {

/**
* 从远程服务器获取文件信息
*
* @param path
* @param fileName
* @return
* @throws RemoteException
*/
public RemoteFileInfo getRemoteFile(String path, String fileName)
throws RemoteException;

}

[size=medium]RemoteFileInfo.java[/size]
import java.io.Serializable;
import java.util.List;

/**
* 文件实体类
*/
public class RemoteFileInfo implements Serializable{
private String fileName; // 文件名
// private byte[] content;
private List content; // 文件内容 (每1024个字节的内容作为列表的一个元素)


public RemoteFileInfo(String fileName, List content) {
this.fileName = fileName;
this.content = content;
}


public List getContent() {
return content;
}

public void setContent(List content) {
this.content = content;
}


public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

}

2. 实现接口,根据RMI规范,接口实现类的名应以“接口文件名+Impl.java”命名。此类不仅要实现远程接口,还要继承UnicastRemoteObject类,声明构造函数(构造函数也要抛出RemoteException异常)
[size=medium]FileManagerImpl.java[/size]
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* 文件操作实现类
*/
public class FileManagerImpl extends UnicastRemoteObject implements FileManager {
private static final Log log = LogFactory.getLog(FileManagerImpl.class);

public FileManagerImpl() throws RemoteException {
super();
}

public RemoteFileInfo getRemoteFile(String path, String fileName)
throws RemoteException {
try {
RemoteFileInfo remoteFile;
List content = new ArrayList();
File file = new File(path + fileName);
BufferedInputStream in = new BufferedInputStream(
new FileInputStream(file));

// 处理大文件时,每次读取1024个字节存到centent对象
byte[] bufContent = new byte[1024];
while(in.read(bufContent) !=-1){
content.add(bufContent);
bufContent = new byte[1024];
}

/*
// 只能用到内容少的文件,遇到大文件会出现内容溢出错误
byte[] content = new byte[(int)file.length()];

in.read(content);
*/
remoteFile = new RemoteFileInfo(fileName,content);
log.info("Getting ["+fileName+"] is successful");

return remoteFile;
} catch (IOException e) {
log.error("Failed to get ["+fileName+"] ...");
e.printStackTrace();
return null;
}
}

3. 生成Stub类(JDK为5.0或以上可以忽略此步),作此步时要先生成了实现类的class文件.
使用javac命令生成.class文件。(e.g. Unix下:javac -classpath .:./lib/commons-logging.jar:
./lib/log4j-1.2.15.jar package1/package2/FileManagerImpl.java)
 在命令行中运行 rmic –v1.2 FileManagerImpl,若实现类被打包要加上包名(e.g. rmic –v1.2 packageA.packageB.packageC. FileManagerImpl).
 若执行成功则会生成一个FileManagerImpl_Stub.class的类文件.
4. 实现RMI应用布署程序
[size=medium]FileServer.java[/size]
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* 布署应用
*/
public class FileServer {
private static final Log log = LogFactory.getLog(FileServer.class);
public static final String CONFIG_FILE_PATH = "/conf/config.properties";

/**
* 获取配置信息
* @return URL
*/
public static Map getURL(){
try{
String url, port;
Map configs = new HashMap();
Properties prop = new Properties();
InputStream in = FileServer.class.getResourceAsStream(CONFIG_FILE_PATH);

prop.load(in);
url = prop.getProperty("server.interface");
port = prop.getProperty("server.port");
configs.put("url", url);
configs.put("port", port);

return configs;
} catch (IOException e){
System.out.println("读取配置信息失败!");
e.printStackTrace();
return null;
}
}

public static void main(String[] args){
try {
Map configs = getURL();
if(configs != null){
String port = configs.get("port").toString();
String url = configs.get("url").toString();

// 根据端口号开启一个RMI服务.也可以不指定,默认为1099
LocateRegistry.createRegistry(Integer.parseInt(port));
FileManagerImpl fileMng = new FileManagerImpl();

log.info("Binding URL:"+url);

// 注册一个RMI应用
// e.g. url: //127.0.0.1:20002/FILE_MNG
Naming.rebind(url, fileMng);
log.info("Deploy Remote File Server successfully!");
}
else{
log.error("Binding Remote File Server failed...");
}

} catch (RemoteException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

}

5. 为了便于维护,最好将以上程序打到一个JAR包中,在META-INF下的MANIFEST.MF文件中指定运行JAR包需要的Main方法所在的类等信息,像这样:
Manifest-Version: 1.0
Main-Class: package1.package2..FileServer
Class-Path: webapp-server.jar commons-logging.jar log4j-1.2.15.jar
在Unix中用nohup命令在后台启动这个JAR包:
nohup java -jar lib/webapp-server.jar >> $HOME/nohupout/fileserver_log.out &
用ps –ef|grep webapp查看此进程。
如没有进程启动,查看日志文件的错误信息。

[size=large][b]客户端[/b][/size]1. 客户端需要的文件类有: 远程接口FileManager.java及其相关类,Stub类.
业务类
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import nantian.fxjk.web.util.AccessRemoteServer;

/**
* 后台文件操作业务类
*/
public class FileClient {

/**
* 获取远程服务器上的文件信息
*
* @param path 文件路径
* @param fileName 文件名
* @return
*/
public RemoteFileInfo getRemoteFile(String path, String fileName){
try{
Map configs = getConfig();

if (configs != null) {
String url = configs.get("url").toString();
String defaultPath = configs.get("abs_path").toString();

// 查找一个已布署的远程服务
// e.g. url: //128.128.96.2:20002/FILE_MNG
FileManager fileMng = (FileManager) Naming.lookup(url);

RemoteFileInfo file = fileMng.getRemoteFile(
defaultPath + path, fileName);

return file;
}
else{
System.out.println("读取配置信息失败.");
return null;
}
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (RemoteException e) {
e.printStackTrace();
return null;
} catch (NotBoundException e) {
e.printStackTrace();
return null;
}
}

/**
* 将远程服务器上的文件取到本地
*
* @param fileInfo
* @return
*/
public boolean getRemoteFileToLocal(RemoteFileInfo fileInfo,
String downloadPath) {
File path = new File(downloadPath);

if (!path.exists()) {
path.mkdirs();
}
try {
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(downloadPath + fileInfo.getFileName()));
List content = fileInfo.getContent();

for(int i=0; i out.write((byte[])content.get(i));
}
out.close();

return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}

/**
* 获取访问远程对象的相关配置信息
*
* @return 配置信息
*/
public Map getConfig() {
try {
Map configs = new HashMap();
Properties prop = new Properties();
InputStream in = FileClient.class
.getResourceAsStream(AccessRemoteServer.CONFIG_FILE_PATH);

prop.load(in);
configs.put("url", prop.getProperty("server.interface"));
configs.put("abs_path", prop.getProperty("server.path"));
configs.put("down_path", prop.getProperty("download.path"));

return configs;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}

2. 编写响应请求的Servlet类
[size=medium]DownloadSysFileAction.java[/size]
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* 下载后台文件的请求响应类
*/
public class DownloadSysFileAction extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

PrintWriter out;
OutputStream outStream;
FileClient fc = new FileClient();
String fileLocation = request.getParameter("file");
fileLocation = fileLocation.trim();
String path = getPath(fileLocation);
String fileName = getFileName(fileLocation);


RemoteFileInfo file = fc.getRemoteFile(path, fileName);

if(file != null){
List content = file.getContent();
outStream = response.getOutputStream();
response.reset();
response.setContentType("application/x-msdownload"); // 纯下载方式
response.setHeader("content-disposition", "attachment; filename="+file.getFileName());

for(int i=0; i outStream.write((byte[]) content.get(i));
}
response.flushBuffer();
outStream.close();
}
else{
response.setContentType("text/html;charset=UTF-8");
out = response.getWriter();
out.println("");
out.close();
return ;
}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
// … … …
}

3. 前台页面提供要下载的文件名和所在路径,再调用这个Servlet就可以下载远程服务器上的文件了

你可能感兴趣的:(java,Unix,Java,应用服务器,log4j,Apache)