【问题标题】:How to make a servlet to pre-compute the values when other servlet is accessed?当访问其他 servlet 时,如何使 servlet 预先计算值?
【发布时间】:2012-08-12 23:22:14
【问题描述】:

我正在使用 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 时开始预先计算值(以便它可以根据请求快速发送值)?
关于如何实现这一点的任何帮助?

附:无法使用数据库或文件系统。

【问题讨论】:

    标签: java ajax web-applications servlets implementation


    【解决方案1】:

    我将尝试对 servlet1 进行过滤,该过滤器启动异步操作以计算您需要的值,然后在 servlet2 的逻辑中检索它们。

    所以基本上你拦截了 servlet1 请求(使用过滤器),该请求在第一次调用 servlet1 时触发,并且在过滤器内开始预先计算值,并且它们 servlet2 根据请求从 servlet1 检索值。

    【讨论】:

    • 有关如何使用过滤器的任何参考?
    • Here是jee 5的oracle教程
    【解决方案2】:

    servlet2 是否需要 servlet1 中的一些值才能开始计算这些值?如果没有,您可以将计算代码移到与两个 servlet 分开的类中。 ServletContextListener 可以在 ServletContext 初始化时触发,在任何请求进入之前,这可以开始计算。完成后,它可以将这些结果存储在 ServletContext 中

    Servlet2 然后可以检查这些结果是否已经计算(是否在 ServletContext 中?),如果是,则使用它。否则它可以计算单个值。理想情况下,您的单独班级将知道如何计算所有值(用于预计算)或单个值(用于尚未完成完整列表时)。

    【讨论】:

    • 关于如何调用类开始执行的任何参考?
    • 这里的第一个答案会加载一些配置并将其存储在上下文中,因此您可以执行类似的操作,但改为进行预计算 - stackoverflow.com/questions/3153739/…
    • 您对 contextInitialized 方法(您将在其中触发预计算)、使用 web.xml 配置侦听器以及展示如何从将上下文放入您的 servlet 之一
    【解决方案3】:

    如果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的请求参数),则更具挑战性和趣味性。

    我看到至少两个选项:

    • servlet1 中启动Future 任务并在servlet2 中检索该未来(希望已经完成)。您需要以某种方式在 servlet 之间传递它,例如把它放在ServletContext

    • servlet1 队列发送消息。消息侦听器将处理请求,预先计算结果并将结果放入某个临时的、唯一的队列中。 servlet2 稍后可以从该队列接收消息(您必须以某种方式就某种命名方案达成一致),或者稍等片刻。

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 1970-01-01
      • 2014-12-11
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多