使用非阻塞Servlet 3.1 API进行全双工HTTP升级

时间:2014-04-08 19:14:12

标签: java http servlets nonblocking wildfly

我在wildfly-dev邮件列表上的Servlet 3.1中询问了有关HTTP升级处理的问题,如何开发简单的双向全双工回声协议。经过几天的讨论,我们得出结论,以下示例有点正确:

@WebServlet(urlPatterns = "/upgrade")
public class AsyncEchoUpgradeServlet extends HttpServlet {
  private static final long serialVersionUID = -6955518532146927509L;

  @Override
  protected void doGet(final HttpServletRequest req,
      final HttpServletResponse resp) throws ServletException, IOException {
    req.upgrade(Handler.class);
  }

  public static class Handler implements HttpUpgradeHandler {
    @Override
    public void init(final WebConnection wc) {
      Listener listener = new Listener(wc);
      try {
        // we have to set the write listener before the read listener
        // otherwise the output stream could be written to before it is
        // in async mode
        wc.getOutputStream().setWriteListener(listener);
        wc.getInputStream().setReadListener(listener);
      } catch (IOException e) {
        throw new IllegalArgumentException(e);
      }
    }

    @Override
    public void destroy() {
    }
  }

  private static class Listener implements WriteListener, ReadListener {
    private final WebConnection connection;
    private final Queue<String> queue = new ArrayDeque<String>();

    private Listener(final WebConnection connection) {
      this.connection = connection;
    }

    @Override
    publicvoid onDataAvailable() throws IOException {
      byte[] data = new byte[100];
      while (connection.getInputStream().isReady()) {
        int read;
        if ((read = connection.getInputStream().read(data)) != -1) {
          queue.add(new String(data, 0, read));
        }
        onWritePossible();
      }
    }

    @Override
    public void onAllDataRead() throws IOException {
    }

    @Override
    public void onWritePossible() throws IOException {
      while (!queue.isEmpty() && connection.getOutputStream().isReady()) {
        String data = queue.poll();
        connection.getOutputStream().write(data.getBytes());
      }
    }

    @Override
    public void onError(final Throwable t) {
    }
  }
}

它实际上是有效的,它是我们讨论过程中交换的唯一示例,它运行良好,我们不必创建任何额外的线程来处理输入和输出。

在这个例子中让我烦恼的是我们在onDataAvailable()中明确地调用了onWritePossible()。

有没有人在使用Servlet 3.1 API进行HTTP升级时有任何其他示例?上面显示的示例是否正确?

0 个答案:

没有答案