使用HTML5 Server事件和Java Servlet时如何防止net :: ERR_INCOMPLETE_CHUNKED_ENCODING?

我刚开始玩服务器事件,我遇到了一个我想了解的chrome错误信息.我快速搜索网页但没有找到解释所以我想我可能会做一些非常错误的事情.

在服务器端,我有一个简单的servlet接受请求并创建一个虚拟事件创建者任务:

private Executor executor = Executors.newSingleThreadExecutor();

public void doGet(final HttpServletRequest request,final HttpServletResponse response)
{
  final AsyncContext asynCtx = request.startAsync(request,response);

  response.setHeader("Cache-Control","no-cache");
  response.setContentType("text/event-stream");
  response.setCharacterEncoding("utf-8");

  executor.execute(() -> {
    boolean run = true;
    try
    {
      while (run)
      {
        final ServletResponse resp = asynCtx.getResponse();
        run = resp != null;

        if (resp != null)
        {
          System.out.println("pushing a server event.");
          final PrintWriter writer = asynCtx.getResponse().getWriter();
          writer.println("data: {time: " + System.currentTimeMillis() + "}\n");
          writer.flush();
        }
        else
        {
          System.out.println("stopping beeper,no response object available anymore.");
          break; // do not run anymore,we got no response
        }

        Thread.sleep(2000);
      }
    }
    catch (final Exception e)
    {
      e.printstacktrace();
    }
  });

}

在客户端我简单地说:

$(document).ready(function ()
{

   var source = new EventSource("/events");
   source.onmessage = function (event)
   {
     console.log("received event: " + JSON.stringify(event));
     document.getElementById("eventContainer").innerHTML += event.data + "<br/>";
   };

   console.log("start to receive events...")
});

当我加载HTML文件时,它工作正常,事件被接收并写入控制台.但是30秒后我收到一条错误消息:

GET [HttpOfLocalhost] / events net :: ERR_INCOMPLETE_CHUNKED_ENCODING

为什么?

请求被杀死并立即启动一个新的,所以它不会杀死应用程序,但控制台上的错误消息并不好.

我的开发者控制台截图:

请求/ resposne详细信息:

时间,这表明它总是在30秒后发生:

谢谢!

解决方法

好吧,所以我不能停滞不前,仔细看看发生了什么.

AsyncContext对象具有setTimeout(…)方法.认情况下,我的tomcat版本(Tomcat嵌入式8)的值设置为30,000毫秒(30秒).这正是我在chrome控制台中遇到net :: ERR_INCOMPLETE_CHUNKED_ENCODING错误后的持续时间.

我检查使用:

System.out.println("Current Timeout is: " + asynCtx.getTimeout() + " ms");

显示

Current Timeout is: 30000 ms

所以为了避免net:ERR消息,有人可以将超时设置为0.但是比事件线程永远运行(不幸的是).
我使用的另一种解决方案是将AsyncListener添加AsyncContext并在onTimeout()方法调用complete()方法.

来自complete()方法api文档

Completes the asynchronous operation that was started on the request
that was used to initialze this AsyncContext,closing the response
that was used to initialize this AsyncContext. Any listeners of type
AsyncListener that were registered with the ServletRequest for which
this AsyncContext was created will be invoked at their onComplete
method.

我的听众的源代码

asynCtx.addListener(new AsyncListener()
{
  @Override
  public void onComplete(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onComplete(...)");
  }

  @Override
  public void onTimeout(AsyncEvent asyncEvent) throws IOException
  {
    // this will close the request and the context gracefully
    // and the net:ERR is gone.
    asyncEvent.getAsyncContext().complete();
    System.out.println("onTimeout(...)");
  }

  @Override
  public void onError(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onError(...)");
  }

  @Override
  public void onStartAsync(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onStart(...)");
  }
});

是的,这是由于缺乏知识.我希望这对某人有帮助.

相关文章

HTML5和CSS3实现3D展示商品信息的代码
利用HTML5中的Canvas绘制笑脸的代码
Html5剪切板功能的实现
如何通过HTML5触摸事件实现移动端简易进度条
Html5移动端获奖无缝滚动动画实现
关于HTML5和CSS3实现机器猫的代码