在Grails 2.0中使用Servlet 3.0异步功能

上周,我与某人谈论了Grails 2中对Servlet 3.0异步功能的新支持,并意识到我对可用功能并不了解。 所以我想我会尝试一下并分享一些例子。 该文档对这个主题有些了解,因此首先介绍一些背景信息。
在3.0规范中进行异步工作的主要方式是javax.servlet.ServletRequest类中的新startAsync方法。 这将返回javax.servlet.AsyncContext接口的实例,该实例具有生命周期方法(例如dispatchcomplete ,为您提供了对请求和响应的挂钩,并允许您注册javax.servlet.AsyncListener 。 您调用传入Runnablestart方法来执行异步工作。 使用这种方法可以释放服务器资源而不是进行阻塞,这可以提高可伸缩性,因为您可以处理更多的并发请求。
为了使用此功能,处理请求的servlet必须支持异步,并且过滤器链中所有应用的过滤器也必须支持。 主Grails Servlet( GrailsDispatcherServlet )在web.xml模板的3.0版本中注册,并且async-supported属性设置为true。 Servlet3AsyncWebXmlProcessor生成后,<async-supported>true</async-supported>到web.xml中的所有过滤器声明中。 这样就为您覆盖了; 您没有必需的web.xml配置。
您还必须配置为使用Servlet API 3.0。 这很容易做到; 只需将grails.servlet.version的值grails.servlet.version为“ 3.0? 默认值“ 2.5”。 请注意,application.properties中有一个旧设置,名称为app.servlet.version ; 您应该从application.properties文件中删除此行,因为它的值在运行时会被BuildConfig.groovy中的值忽略并覆盖。
但是,您不会在控制器的请求上调用startAsync ; 直接在控制器上调用startAsync 。 此方法是作为控制器方法添加的(作为Controller的AST转换的一部分,从ControllersAsyncApi连接 (如果您感到好奇,可以通过ControllerAsyncTransformer连接 ))。 调用控制器的startAsync方法非常重要,因为它可以执行所有标准工作,而且还可以添加Grails集成。 这包括添加逻辑以集成所有已注册的PersistenceContextInterceptor实例,例如将Hibernate Session绑定到线程,完成后刷新等,并与Sitemesh集成。 这是通过返回的实例来实现的
GrailsAsyncContext为其余部分添加额外的行为并委托给容器提供的实际实例(例如Tomcat中的org.apache.catalina.core.AsyncContextImpl )。
请求中还有其他一些与异步相关的新方法。 它们包括boolean isAsyncStarted()AsyncContext getAsyncContext()
我已经附加了一个示例应用程序(请参阅下面的链接)以演示这些功能。 有两个部分: 一个异步查询股票价格的简单控制器,以及一个聊天应用程序。
StockController非常简单。 它只有一个动作,因此会暂停以查询所请求的股票报价器的当前股价。 它异步执行此操作,但通常速度非常快,因此您可能看不到与串行方法的真正区别。 但是,这种模式可以推广到执行更多耗时的任务。
调用http:// localhost:8080 / asynctest / stock / GOOG,http:// localhost:8080 / asynctest / stock / AAPL,http:// localhost:8080 / asynctest / stock / VMW等进行测试。
第二个示例涉及更多,并基于Java EE 6 SDK中的“ async-request-war”示例。 这实现了一个聊天应用程序(它以前是通过Comet实现的)。 SDK的示例是一个大servlet。 我将其拆分为一个控制器以执行标准请求工作,并将其ChatManagerChatManager类(在resources.groovy中注册为Spring Bean)来处理客户端注册,消息排队和调度以及相关的错误处理。
该实现使用隐藏的iframe来启动长时间运行的请求。 它永远不会完成,并且用于将消息发送回每个注册的客户端。 当您“登录”或发送消息时,控制器将处理请求并将响应消息排队。 然后, ChatManager循环遍历每个已注册的AsyncContext ,并将JSONP发送到iframe,该iframe使用传入消息更新主页中的文本区域。
使我困扰了很长时间的一件事是,该示例在SDK示例中运行良好,但在我的示例中却无法运行。 一切看起来不错,但iframe并未收到消息。 事实证明,这是由于进行了适当的优化以使响应呈现尽可能快。 不幸的是,这导致响应编写器上的flush()调用被忽略。 由于我们需要响应式更新,并且不会呈现较大的html页面,因此我添加了代码来查找由Grails代码包装的真实响应,并直接发送给它。
在两个浏览器中打开http:// localhost:8080 / asynctest /尝试一下。 一旦您“登录”到两者,发送的消息将在两个浏览器中显示。
有关测试应用程序的一些注意事项:
  • 所有客户端逻辑都在web-app / js / chat.js中
  • grails-app / views / chat / index.gsp是主页; 它创建了文本区域来显示消息,而隐藏的iframe保持连接状态并收听消息
  • 这需要实现3.0规范的Servlet容器。 由tomcat插件提供并由run-app使用的Tomcat版本,而所有7.x版本的Tomcat都有。
  • 我运行install-templates并编辑了web.xml以添加metadata-complete="true"以防止Tomcat扫描所有jar文件中的带注释的类–由于版本7.0.26中 修复的错误 (当前未发布 ,因此这可能导致OOME)
  • 由于聊天部分基于旧代码,因此它使用Prototype,但可以轻松使用jQuery。

您可以在此处下载示例应用程序代码。

参考: An Solipsists博客上的JCG合作伙伴 Burt Beckwith 提供的在Grails 2.0中使用Servlet 3.0异步功能


翻译自: https://www.javacodegeeks.com/2012/06/using-servlet-30-async-features-in.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值