JAVA Web Servlet中的异步处理 (2) – Servlet3.1中的Non-blocking IO支持
在servlet 3.1中,新增了non-blocking IO支持。
在servlet 3.0中,引入了异步请求处理。在一个典型的程序中,使用ServletInputStream来循环读取。
但是如果输入的数据被阻塞或者流速很慢,则服务线程必须等待数据进来。ServletOutputStream也存在这样的问题。
示例:
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ServletInputStream input = request.getInputStream();
byte[] b = new byte[1024];
int len = -1;
while ((len = input.read(b)) != -1) {
// do something
}
}
}
在servlet 3.1中,引入了JSR 340,添加non-blocking IO处理。
添加修改了几个新的接口和类,如IO的事件监听器 -ReadListener WriteListener.
修改了ServletInputStream、ServletOutputStream。
通过ServletInputStream.setReadListener和ServletOutputStream.setWriteListener可以注册监听器。监听器中提供了一些回调方法,在数据可以读写时进行触发调用。
新增加的ServletInputStream.isReady方法和ServletInputStream.isFinished方法用于检测非阻塞I/O的读取状态,而ServletOutputStream.canWrite方法用于检测数据是否能够无阻塞地写入。
改进后的doGet方法一般如下所示:
AsyncContext context = request.startAsync();
ServletInputStream input = request.getInputStream();
input.setReadListener(new MyReadListener(input, context));
示例实现
@Override
public void onDataAvailable() {
try {
StringBuilder sb = new StringBuilder();
int len = -1;
byte b[] = new byte[1024];
while (input.isReady() && (len = input.read(b)) != -1) {
String data = new String(b, 0, len);
System.out.println("--> " + data);
// do something
}
} catch (IOException ex) {
// log it
}
}
@Override
public void onAllDataRead() {
// do something
context.complete();
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
context.complete();
}
上述实现有三处回调:
– onDataAvailable方法在数据可以无阻塞读取的时候进行调用。
– onAllDataRead方法在当前请求已经完全读取完毕的时候调用。
– onError方法在处理请求出错的时候调用。

本文介绍 Servlet 3.1 中新增的非阻塞 I/O 支持,通过 JSR 340 规范引入 ReadListener 和 WriteListener 接口,实现了异步请求处理,避免了服务线程因等待数据读写而被阻塞。
654

被折叠的 条评论
为什么被折叠?



