我正在编写一个我想用来执行FTP任务(下载)的Web应用程序
我在Tomcat中安装了Apache FTPS服务器,并准备好Java客户端来启动传输。
Servlet将调用客户端。
例如:
http://laptop:8080/MyServlet?action=download&from=desktop&file=C:/home/fred/file.xml
告诉笔记本电脑上的实例从我的桌面下载 file.xml 。
修改: 道歉,我从来没有说清楚。
此过程的两端都有一台FTP服务器。 1在我的远程笔记本电脑上,1在我的本地桌面上。所以简而言之,我向远程端的Servlet提交了一个FTP'get'请求。然后,Servlet启动FTP进程以将文件拉过来。
我的Servlet已设置为接收GET参数并完成工作。
如果文件很大,那么每个请求都需要很长时间才能完成。我希望尽快释放Servlet资源。
理想情况下,我希望发生以下事情:
此时我并不太关心Servlet对线程成功的了解,我只是需要它来启动它而忘记它。对于任何问题,FTP进程将在其他位置单独记录。
我感兴趣的是在WebApp中创建Threadpool并从那里获取线程的概念,但是我发现的所有示例都很旧,并不能满足我的理解水平。
在StackOverflow上有一些类似的问题,这与我要求的最相似,但它只暗示了我之前不知道的ExecutorService。我如何在WebApp中进行设置? What is recommended way for spawning threads from a servlet in Tomcat
有关信息, 我研究了这个问题,发现了很多不完整的例子,需要比我现在更好的理解,或暗示需要什么。 我读过的很多例子都是几年前的,没有最新的。我希望可能会有一个神奇的单行代码去做我需要的一切(可疑)在去年左右出现:) 我是Java的线程概念的新手,我理解一般的线程,所以感谢你能给我提供的任何帮助。
特雷弗
答案 0 :(得分:0)
我不确定我是否真的明白你想要的东西......
client server
send request (via HTTP) and wait for
HTTP response
analyse request and find file to send
... (processing)
send HTTP response (1) with ?
opens FTP connection (could not open it before)
receive FTP request (command connection)
send file (data connection)
file is received and saved locally
如果客户端是浏览器,则响应(1)应该足够重定向到ftp://host/path/to/file
之类的URL,因为所有主流浏览器都知道FTP协议并能够使用它下载文件。
问题不在服务器端,你可以很容易地产生一个可以作为FTP客户端的线程或者(可能更难)作为FTP服务器,但我无法想象比客户端的重定向更好:客户端已打开HTTP连接不能用于FTP传输,必须为FTP请求打开新连接。由于它是一个新连接,您希望如何通过上一步启动的线程处理它?在FTP中没有会话概念,也没有简单的方法来识别正确的请求。
根据评论编辑:
好的,我似乎只是想在请求完成后在服务器上进行 deferred 处理。你有两种方法:
使用简单线程并在会话中存储状态的示例:
public class ThreadedServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
String fileName = null;
// preliminary work ...
Worker worker = new Worker(fileName);
final HttpSession session = hsr.getSession();
synchronized (session) {
List<Status> statuses = (List<Status>) session.getAttribute("statuses");
if (statuses == null) {
statuses = new ArrayList<Status>();
}
statuses.add(new Status(fileName));
}
Thread thr = new Thread(worker);
thr.start();
// write the response either directly or by forwarding to a JSP
}
public static class Status implements Serializable {
private String fileName;
private WStatus status;
public Status(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public WStatus getStatus() {
return status;
}
public void setStatus(WStatus status) {
this.status = status;
}
}
public enum WStatus {
STARTED,
RUNNING,
COMPLETED
}
private static class Worker implements Runnable {
private String fileName;
private Status status;
public Worker(String fileName) {
this.fileName = fileName;
}
@Override
public void run() {
status.setStatus(WStatus.RUNNING);
// do your stuff ...
status.setStatus(WStatus.COMPLETED);
}
}
}