【发布时间】:2013-12-08 02:17:57
【问题描述】:
见下方更新
我被难住了,并尝试在论坛中搜索可能的解决方案。我确信那里有解决方案,但也许我还不知道正确的术语。
所以这是我的问题: 我有一个 java 应用程序,它执行非常复杂的数值计算,根据环境中的内核数量等很好地扩展......但是,我现在正试图将这个计算暴露给互联网接口。
第一次尝试:我试着把它放在一个 servlet 中,但意识到这是一个非常不受欢迎的解决方案,特别是考虑到多个 servlet 可以称为产生多个实例。我只希望这个计算的一个实例在后台运行,因为多个用户只会使用相同的数据集。
我想要的: 1. 用户向“启动”此计算的 servlet 发出请求。此计算需要几分钟才能运行。 2.“开始”请求被返回,所以现在使用ajax,我可以查询进度。 3. 如果计算已经在运行并且另一个用户尝试开始计算,它不会。
我之前的搜索结果是这样的,我试图模仿这个设计:Status of the process triggered by request in java
谢谢!
更新: 好的,所以我找到了一个简单的例子,它包含了我想要的 95%:AJAX (prototype/java) getting partial status updates during execution
package main;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Main extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Found post request!");
processPostRequest(request, response);
}
/**
* Handles http get requests by mapping them to processRequest()
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Found get request!");
processPostRequest(request, response);
}
public void processPostRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
LongProcess longProcess = null;
if(request.getSession().getAttribute("longProcess") != null) {
longProcess = (LongProcess) request.getSession().getAttribute("longProcess");
System.out.println("Found longProcess object in JVM!");
response.getWriter().write(String.valueOf(longProcess.getProgress()) + "%");
}
else {
longProcess = new LongProcess();
//longProcess.setDaemon(true);
longProcess.start();
request.getSession().setAttribute("longProcess", longProcess);
response.getWriter().write("The long process has started!");
}
}
}
class LongProcess extends Thread {
private int progress;
public void run() {
while (progress < 100) {
try { sleep(1000); } catch (InterruptedException ignore) {}
progress++;
}
}
public int getProgress() {
return progress;
}
}
我现在的问题是:我将单独的线程对象“longProcess”存储在请求的上下文中。虽然这适用于定期查询进程的状态,即(我会得到 1%....5%....9%.. 一直到 100%),但当我开始请求时从一个浏览器,然后从另一个浏览器发出请求,我运行了两个单独的实例。我认为这是因为将其存储在请求的上下文中。
有没有办法将线程对象存储在 JVM 中,以便来自各地的请求可以访问同一个对象?我知道我需要同步等......但我希望能够从不同的请求上下文中看到同一个对象。
我尝试查看 System.setProperty() 但这似乎只适用于字符串。是否有相当于: request.getSession().setAttribute("longProcess", longProcess); 而是将其存储在 JVM 中以供所有请求访问?
【问题讨论】:
-
你可以考虑使用 Spring MVC。将控制器包裹在这些东西上并使用 AutoConfig 运行嵌入式 Web 服务器非常容易。