首页 > 解决方案 > 将自定义配置器与 WebSocket 一起使用

问题描述

关于扩展 ServerEndpointConfig.Configurator 以覆盖 Tomcat 在接收 WebSocket 请求时实例化带有 @ServerEndpoint 注释的 POJO 类的默认操作的快速问题。我这样做的原因是我的端点类依赖于 IoC 依赖注入,因此需要从注册表中获取它的依赖项。

我的配置器方法:

@Override 
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException { 
    return endpointClass.cast(RegistryProxy.getService(HarbourServerEndpoint.class)); 
} 

@ServerEndpoint 注释放在我的 HarbourServerEndpointImpl POJO 类上,而不是它实现的接口上。根据下面的运行时 catalina.out 错误消息,问题似乎是注册表返回 HarbourServerEndpoint 而 Tomcat 期待 HarbourServerEndpointImpl 的实例?

我希望有人可以解释我的自定义配置器出了什么问题。

2019 年 4 月 15 日 12:45:28.488 严重 [http-nio-8080-exec-915] org.apache.coyote.AbstractProtocol$ConnectionHandler.process 读取请求时出错,忽略 java.lang.ClassCastException:无法将 $HarbourServerEndpoint_39c9cc24eb8b2a 转换为 com .optomus.harbour.services.HarbourServerEndpointImpl at java.lang.Class.cast(Class.java:3369) at com.optomus.harbour.services.HarbourServerEndpointConfigurator.getEndpointInstance(HarbourServerEndpointConfigurator.java:17) at org.apache.tomcat.websocket .pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:44)

    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:133)

    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:846)

    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)

    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

    at java.lang.Thread.run(Thread.java:748) 

最后,完全没有强制转换,编译器给出了错误:

Error:(17, 40) java: incompatible types: inference variable T has incompatible bounds 
    equality constraints: com.optomus.harbour.services.HarbourServerEndpoint 
    upper bounds: T,java.lang.Object

标签: javatomcatwebsocket

解决方案


自从发布这个问题以来,我研究了 Tapestry-IoC 及其工作原理。事实证明,返回的内容看起来有点奇怪($HarbourServerEndpoint_39c9cc24eb8b2a)是有原因的。它是一个服务代理对象,而不是我所期望的服务实现的实例。我不确定这对于 IoC 容器有多典型。引用 Tapestry 网站:

“服务由两个主要部分组成:服务接口和服务实现。

服务接口是服务将如何在注册表的其余部分中表示。由于传递的通常是代理,因此您不能期望将服务对象强制转换为实现类(您会看到 ClassCastException)。换句话说,您应该小心确保您的服务接口是完整的,因为 Tapestry IoC 有效地将您与 casts 等后门隔离开来。”

这使得从使用@ServerEndpoint 注释的类的 IoC 注册表实例中获取相当棘手,我现在正在探索其他选项。

问候,

克里斯。


推荐阅读