我正在使用java servlet开发Web应用程序,这是我的方案:
servlet1: Has the application's interface and main logic
servlet2: Suplies values to servlet1 on ajax request from servlet1
servlet1可以请求250个值。但是在servlet2中计算这些值需要花费时间(因为它涉及向其他服务器发出GET请求以获取值)。因此,根据请求计算这些值会使客户端等待很长时间。
那么有没有办法让servlet2在首次调用servlet1时开始预先计算值(因此可以根据请求快速发送值)?
有关如何实现这一点的任何帮助吗?
P.S。无法使用数据库或文件系统。
答案 0 :(得分:1)
我将尝试对servlet1进行过滤,启动异步操作以计算所需的值,然后在servlet2的逻辑中检索它们。
所以基本上你拦截servlet1请求(带有过滤器),当servlet1第一次被调用时触发,并且在过滤器内部开始预先计算值,并且servlet2根据servlet1的请求检索值。
答案 1 :(得分:1)
servlet2是否需要servlet1中的某些值来开始计算值?如果没有,您可以将计算代码移动到与两个servlet分开的类中。然后,ServletContextListener可以在ServletContext初始化之前,在任何请求进入之前触发,这可以开始计算。完成后,它可以将这些结果存储在ServletContext
中 然后,Servlet2可以检查是否已经计算了这些结果(是否在ServletContext中?),如果是,则使用它。否则它可以计算个别价值。理想情况下,您的单独类将知道如何计算所有值(用于预计算)或单个值(用于尚未完成完整列表的时间)。
答案 2 :(得分:1)
如果servlet2
需要预先计算的数据不依赖于servlet1
输入,并且只需要计算一次,请在ServletContextListener.contextInitialized()
或GenericServlet.init()
中急切计算。然而,计算需要一些时间,您最好将其移动到某个后台线程以避免长时间的应用程序启动时间(这些方法阻止部署直到它们完成)。
这是一个简单的例子:
public class Servlet2 extends HttpServlet {
private final ExecutorService threadPool = Executors.newSingleThreadExecutor();
private Future<String> calculationResult;
@Override
public void init() throws ServletException {
calculationResult = threadPool.submit(new PreComputingTask());
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final String slowResponse = calculationResult.get();
//...
}
}
class PreComputingTask implements Callable<String> {
@Override
public String call() throws Exception {
//Call external systems, whatever...
return "slow response";
}
}
如您所见,当servlet2
启动时,它会在单独的线程中启动预计算任务。然后在doGet()
中检索结果,如果尚未完成则可能等待它。
如果预计算取决于servlet1
中的输入(例如,在调用外部系统时需要使用servlet1
的请求参数),则更具挑战性和趣味性。
我至少看到两个选项:
启动Future
中的servlet1
任务,并在servlet2
中检索该未来(希望已经完成)。你需要以某种方式在servlet之间传递它,例如将其放在ServletContext
从servlet1
向jms队列发送消息。消息侦听器将处理请求,预先计算结果并将结果放入一些临时的唯一队列中。然后servlet2
可以从该队列接收消息(您必须以某种方式同意某些命名方案),或稍等一下。