2

对于我即将提出的问题,我已经有了答案。

在任何情况下,我都在这里问它,以便它可以帮助人们从 JEE 6 迁移到 JEE 7 并且正在考虑使用 websocket - 例如用 websocket 功能代替长轮询。

问题:在支持 JEE 7 的 Weblogic 12.2.1.2 中,并尝试使用如下指南设置 websocket: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/HomeWebsocket/WebsocketHome。 html

注意:上面的指南非常简单,它所说的都是正确的并且“应该”工作。不一定适用于您的应用程序,因为它没有在我的应用程序中。但在概念上它应该。

尽管那样。在从浏览器到支持的握手期间,websocket 应用程序出错,其中 HTTP 连接应该升级为 tcp/ip Web 套接字连接。

Weblogic,抱怨 tyrus 不能使用 Ascyn servlet 行为来处理这个握手协议。下面列出了握手期间错误的堆栈跟踪:

2017-01-23 14:54:59,065 ThreadId:53 错误 HTTP - [ServletContext@129852715[app:primefaces-60 模块:primefaces-60

path:null spec-version:3.1]] Servlet 失败并出现异常 <[ACTIVE] ExecuteThread: '5' for queue: 'weblogic.kernel.Default (self-tuning)'> java.lang.IllegalStateException: 异步支持对此请求禁用:weblogic.servlet.internal.ServletRequestImpl@2c87c663[ GET /primefaces-60/actions HTTP/1.1 连接:升级编译指示:无缓存缓存控制:无缓存升级:websocket 来源: http://本地主机:7001Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 DNT: 1 Accept-Encoding: gzip, deflate, sdch , br Accept-Language: en-US,en;q=0.8,pt-PT;q=0.6,pt;q=0.4,fr;q=0.2,it;q=0.2,de;q=0.2 Sec-WebSocket -Key:flKcAkxO3CJBIc8cYvwvlA== Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits

] 在 weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:2029) 在 weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:2005) 在 javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432)在 weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:241) 在 weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) 在 filter.DummyTimeoutFilter2.doFilter(DummyTimeoutFilter2.java:81) 在 weblogic。 servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) 在 weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:32) 在 weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) 在 weblogic .servlet.内部。WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3683) 在 weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3649) 在 weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326)在 weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197) 在 weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203) 在 weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71 ) 在 weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2281) 在 weblogic.servlet.internal.WebAppServletContext 的 weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2433)。在 weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1651) 在 weblogic.servlet.provider.ContainerSupportProviderImpl 在 weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1691) 处执行(WebAppServletContext.java:2259) $WlsRequestExecutor.run(ContainerSupportProviderImpl.java:270) 在 weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:348) 在 weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:333) 在 weblogic.work.LivePartitionUtility.doRunWorkUnderContext( LivePartitionUtility.java:54) 在 weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41) 在 weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:第640章)

基于设置 websocket 端点的后端代码是完美的假设,用于尝试建立 websocket 连接的 javascript 代码是完美的。有人可以按照信中的指南解释为什么会出现上述错误吗?

注意: - 根据对真实应用程序的分析,上述堆栈跟踪已在示例应用程序中隔离,该示例应用程序具有工作的 websocket 端点已损坏为上述异常。

一旦你知道答案很简单......如果没有人支持正确的解决方案,我将在一天左右的时间内回答。

4

1 回答 1

4

回答我自己的问题。

应用程序在尝试打开 web-socket 连接时遇到的问题与 tyrus 使用 Sevlet 3.0 规范的特性有关,即异步 servlet 处理。

即使在最微不足道的 Web 应用程序中,也可能有适当的过滤器,这些过滤器可以交叉应用于所有 Web 请求。比如带有过滤器映射/*的过滤器。

那么这正是问题所在。如以下参考资料中所述,为了允许异步 servlet 运行通向 servlet 的完整过滤器链,它们的 sevles 必须支持异步请求处理。

https://blogs.oracle.com/enterprisetechtips/entry/asynchronous_support_in_servlet_3

需要 asyncSupported 属性来区分为同步处理编写的代码和为在异步上下文中使用而编写的代码。事实上,对于使用异步功能的应用程序,整个请求处理链必须通过注释或在其部署描述符中设置此属性。如果应用程序尝试启动异步操作并且请求处理链中存在不支持异步处理的 servlet 或 servlet 过滤器,则会引发 IllegalStateException。

因此,要解决此问题,必须为过滤器集提供一个附加元素:

<async-supported>true</async-supported>

例如:

<filter>
    <filter-name>AFilter</filter-name>
    <filter-class>webapp.AFilter</filter-class>
    <async-supported>true</async-supported>
</filter>

在上面的堆栈跟踪的情况下,使问题在独立应用程序中可重现所需要做的就是添加一个虚拟过滤器,该过滤器除了将请求传递给下一个过滤器之外什么都不做。过滤器是:DummyTimeoutFilter2。这个过滤器是在没有异步支持的情况下声明的。

因此,总而言之,请注意您的容器可能需要异步 servlet 来打开 Web 套接字。如果你有任何过滤器拦截到你的 websocket 端点的请求,你可能会对这样的副作用感到惊讶。对于来自 JEE 6 的应用程序尤其如此,但它很容易发生在任何全新的 JEE 7 应用程序上。

然而,大多数人可能没有过滤器拦截对 websocket 端点的调用......

于 2017-01-25T20:16:53.797 回答