我在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升级时有任何其他示例?上面显示的示例是否正确?