如何在访问其他servlet时使servlet预先计算值?

时间:2012-08-16 15:00:00

标签: java ajax web-applications servlets implementation

我正在使用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。无法使用数据库或文件系统。

3 个答案:

答案 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队列发送消息。消息侦听器将处理请求,预先计算结果并将结果放入一些临时的唯一队列中。然后servlet2可以从该队列接收消息(您必须以某种方式同意某些命名方案),或稍等一下。