2010-03-02 77 views
6

我有一种似乎适合异步Servlet 3.0/Comet情况的情况,但我需要做的是在接受传入参数后返回200响应代码(或其他)。完成HttpServletResponse,但继续处理

有没有办法让HttpServlet完成http请求/响应握手并继续处理?

喜欢的东西...

doPost(req, response) { 
    // verify input params... 
    response.setStatus(SC_OK); 
    response.close(); 
    // execute long query 
}  

编辑:纵观javax.servlet包 - 适当的措辞我的问题是

如何犯下的反应?

在Servlet.isCommitted()

+0

“承诺”是指响应流中的某些部分已经被发送到客户端。它不能被收回或修改。理论上,只要您设置标题或写入响应,它就会发生,但通常是容器缓冲区,所以稍后会发生。 我认为这与你无关。不要关闭响应流。只需设置状态,按照其他答案启动线程,让doPost()完成。 – 2010-03-05 12:15:35

+0

我试着使用response.sendError(SC_OK),但它仍然没有刷新对请求者的响应。看起来,关闭servlet请求的唯一方法是从doPost()返回。 – Stevko 2010-03-05 17:49:51

回答

6

这里是我是如何处理这种情况:

  1. 当应用程序启动时,创建一个ExecutorServiceExecutors.newFixedThreadPool(numThreads)(还有其他类型的执行者,但我建议先从这一个)
  2. doPost(),创建Runnable一个实例将执行所需的处理 - 你的任务 - 它提交给ExecutorService像这样:executor.execute(task)
  3. 最后,你应该返回的HTTP状态202 Accepted,而且,如果可能的话,一个Location标题指示客户端将能够检查处理状态的位置。

强烈建议您阅读Java Concurrency in Practice,这是一个梦幻般的,非常实用的书。

+0

虽然我同意所有的答案,但这个答案涉及的复杂度最小。感谢pajton,beny23和avi供您参考。 – Stevko 2010-03-05 17:48:01

+0

我该如何做到这一点,如果我想使用executor.submit()而不是.execute?我想使用.submit,以便我可以掌握“未来”,并知道所有任务何时完成(基于哪些我必须执行某些处理?)。 – Tintin 2017-01-27 16:10:42

3

您可以继续在一个单独的线程处理。

doPost()方法返回后,提交响应。

+0

我正在运行URL提取服务5秒超时,请求源自Google应用引擎的完美请求。 App Engine请求程序不需要阻止等待可能需要很长时间才能完成处理的确定响应。 – Stevko 2010-03-02 23:35:48

+0

好吧,所有你需要的只是后台线程:)。 – pajton 2010-03-02 23:37:35

3

关于您的servlet接受后台处理请求的可能性,是让servlet将处理交给单独的线程,然后在后台执行。

使用Spring,可以使用a TaskExecutor调用单独的线程。使用Spring比标准JDK 5 java.util.concurrent.Executor的优势在于,如果您使用的是需要使用托管线程(IBM websphere或Oracle weblogic)的应用程序服务器,则可以使用WorkManagerTaskExecutor挂接到CommonJ工作管理器。

另一种选择是将长查询逻辑移动到消息驱动Bean或消息驱动POJO(Spring JMS可以在这里帮助),并让servlet简单地在JMS队列上发布消息。这样做的好处是,如果由于长时间运行的查询而导致Web容器上的负载变得太大,则可以轻松地将MDB移动到不同的(专用)系统上。

0

这个例子可以帮助

void doPost(){ 
    // do something 
    final ExecutorService executor = Executors.newSingleThreadExecutor(); 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       // processing after response 
      } 
     });} 
+1

你能介绍一下吗? – 2015-04-06 18:44:05

+0

最好不要在每次servlet获取请求时实例化一个ExecutorService,否则您将开始创建大量永不死亡的线程,至少每个newSingleThreadExecutor()文档都是如此。 – 2018-03-06 19:54:08