本节书摘来异步社区《Java EE 7精粹》一书中的第2章,第2.4节,作者:【美】Arun Gupta,更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.4 异步支持
服务器端的资源是昂贵的,应谨慎使用。试想一个Servlet不得不等待的场景:连接池中提供一个有效的JDBC连接,接收JMS消息或从文件系统中读取资源。等待“长时间运行”的过程完全返回,阻塞了线程(等待,坐着,什么也不做),服务器资源没有得到最佳的使用。这正是异步处理的用武之地。服务器可以异步执行,在等待长时间运行的过程完成期间,控制(或线程)被返回到容器来执行其他任务。请求处理在长期运行的过程返回之后,在同一个线程继续执行,也可以将长期运行的过程分派给一个新的资源。一个典型长期运行的过程的用例是一个聊天应用程序。
异步行为需要在Servlet中显式启用。可以为@WebServlet注解添加asyncSupported属性来实现:
![9afa97da870df044974e14e00714a71a1f2a0442](https://yqfile.alicdn.com/9afa97da870df044974e14e00714a71a1f2a0442.png)
也可以在web.xml中通过设置元素为true,或者以编程方式在注册过程中调用ServletRegistration.setAsyncSupported(true)来启用异步行为。
然后就可以使用request的startAsync()方法,在一个单独的线程中启动异步处理。该方法返回类型是AsyncContext,代表异步请求执行的上下文。然后,可以通过(显式地)调用AsyncContext.complete()方法或者(隐式地)分派到另一个资源来完成异步请求。在后一种情况下,容器完成异步请求的调用。
比方说,长期运行的过程的实现如下:
![ab38a86e9d84e1189be700f304478eb6283f8c73](https://yqfile.alicdn.com/ab38a86e9d84e1189be700f304478eb6283f8c73.png)
该服务类可以在doGet()方法中调用:
![30ff1aced3f32d719e99cf20c95fd1c107c34ad3](https://yqfile.alicdn.com/30ff1aced3f32d719e99cf20c95fd1c107c34ad3.png)
在这段代码中,请求示例request置入异步模式。AsyncListener注册了监听事件,包括请求处理完成、请求处理已超时或者请求处理发生错误。长期运行的服务在一个单独的线程中被调用,该服务最终调用AsyncContext.complete()方法,发出请求处理完成的信号。
一个请求可以从一个异步的Servlet分派到一个同步的Servlet,但反之是非法的。
异步行为在Servlet的过滤器是可用的。