Servlet 规范是否保证单线程初始化和内联 attributeChanged 事件?
我有一个 Web 应用程序,在初始化 ServletContext 时从外部系统引导事件接收器。所有需要接收事件的组件都在侦听 ServletContext 属性事件并将自身附加为侦听器。由于我不希望事件侦听器错过事件,因此我想仅在附加所有侦听器后才启动事件源。
我在 Servlet 2.5 和 3.0 规范中找不到任何初始化的线程要求,因此我假设完全异步初始化模型,但我注意到 Tomcat 立即从 setAttribute() 方法触发 ServletContext 属性更改事件。这意味着如果所有其他 servlet 容器都效仿,我可以简化我的启动过程。
编辑:根据要求,这是一个示例(我已尝试尽可能具体)。在我的 web.xml 中,我目前已
- 在 servlet 上下文初始化上注册: BootstrapEventSourceContextListener:
- 创建事件源并将其设置为 servlet-context 属性。
- 事件源此时尚未启动(即它不发出事件)
- 当接收到包含事件源的属性已被设置的通知时, ConsumerAContextAttributeListener:
- 从 servlet-context 属性查找事件源
- 实例化 ConsumerA
- 将 ConsumerA 连接到事件源
- 将 ConsumerA 的数据模型设置为 servlet-context 中的属性
- ConsumerBContextAttributeListener - 与 Comsumer 相同A
- ConsumerCContextAttributeListener - 与 A 和 B 相同,不同之处在于它还取决于
- 页面启动时 B StartEventSourceFilter 的数据模型访问:
- 从 servlet 上下文查找事件源
- 启动事件源
- 阻塞,直到事件源收到初始快照
- 继续渲染页面
问题是我是否真的需要 StartEventSourceFilter,或者是否保证当我设置事件源属性时,所有消费者都将被附加(即属性侦听器不会延迟)。我关心 Tomcat、Jetty 和 Websphere。
I have a web application that bootstraps event-receiver from external system when a ServletContext is initialized. All components that need to receive events are listening for ServletContext attribute events and attaching themselves as listeners. As I do not want the event-listeners to miss events, I want to start the event-source only after all listeners have been attached.
I could not find any threading requirements for initialization in the Servlet 2.5 and 3.0 specification, so I was assuming completely async initialization model, yet I noticed that Tomcat fires the ServletContext attribute-changed events immediately from the setAttribute() method. This would mean that if all other servlet containers follow suit, I can simplify my startup procedure.
EDIT: As requested, here is an example (I have tried to be as concrete as possible). In my web.xml, I currently have registered:
- BootstrapEventSourceContextListener on servlet-context initialization:
- creates event-source and sets it as servlet-context attribute.
- the event-source is not started at this time (i.e. it does not emit events)
- ConsumerAContextAttributeListener when it receives a notification that the attribute containing the event-source has been set:
- looks up the event-source from the servlet-context attribute
- instantiates ConsumerA
- attaches ConsumerA to the event-source
- sets the data model of ConsumerA as attribute in the servlet-context
- ConsumerBContextAttributeListener - same as Comsumer A
- ConsumerCContextAttributeListener - same as A and B, except that it also depends on the datamodel of B
- StartEventSourceFilter when a page is accessed:
- looks up the event-source from the servlet-context
- starts the event-source
- blocks until the event-source has received initial snapshot
- continues to render the page
The question is whether I really need the StartEventSourceFilter, or is it guaranteed that all the consumers will be attached the moment I set the event-source attribute (i.e. attribute listeners are not deferred). I care about Tomcat, Jetty and Websphere.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于没有人回答,我深入研究,发现了以下内容:
Servlet 3.0 规范没有提到侦听器是内联通知还是异步通知,但它在第 11 章中提供了以下保证:
唯一剩下的问题是 servlet-context 属性侦听器是否始终与 setter 内联运行,或者是否存在将它们排队的实现(例如合并同一属性的多个更改事件)。我相信可以合理地假设规范的意图和所有实现都会内联通知侦听器(并在 Tomcat 和 Jetty 中证实了这一点)。
底线是:当从 context-init 侦听器设置上下文属性时,可以相当安全地假设所有上下文属性侦听器在 setter 方法返回时都已完成。规范没有明确保证这一点,但所有指定的约束和保证都指向这个方向。
As nobody answered, I dug in and here is what I found:
The Servlet 3.0 spec does not mention whether listeners are notified inline or asynchronously, but it provides the following guarantees in chapter 11:
The only remaining issue is whether the servlet-context attribute listeners always run inline with the setters, or are there implementations that queue them up (say to coalesce multiple change events for the same attribute). I believe it is reasonable to assume that the intent of the spec and all implementations would notify the listeners inline (and confirmed this for Tomcat and Jetty).
Bottom-line is: when setting a context attribute from a context-init listener, it is reasonably safe to assume that all context-attribute listeners will have finished when the setter method returns. The specification does not explicitly guarantee this, but all specified constraints and guarantees point in that direction.