Servlets 容器不可知Websocket抛出带有嵌入式码头的NPE
我正在编写一个容器无关的Websocket服务器。我的开发环境使用IntelliJ IDEA和嵌入式Jetty版本Servlets 容器不可知Websocket抛出带有嵌入式码头的NPE,servlets,websocket,jetty,embedded-jetty,java-websocket,Servlets,Websocket,Jetty,Embedded Jetty,Java Websocket,我正在编写一个容器无关的Websocket服务器。我的开发环境使用IntelliJ IDEA和嵌入式Jetty版本9.3.11.v20160721(下面的嵌入式代码) 但是,我的代码使用Tomcat Websocket库,Tomcat Websocket api和Tomcat Websocket,版本8.5.4 我想用ServletContextListener注册Websocket端点。根据Joakim Erdfelt(@Joakim Erdfelt))的Jetty邮件列表中的一些示例以及SO
9.3.11.v20160721
(下面的嵌入式代码)
但是,我的代码使用Tomcat Websocket库,Tomcat Websocket api
和Tomcat Websocket
,版本8.5.4
我想用ServletContextListener
注册Websocket端点。根据Joakim Erdfelt(@Joakim Erdfelt))的Jetty邮件列表中的一些示例以及SO上的一些答案,我编写了以下实现,并通过web.xml
中的侦听器添加了它
代码进入contextInitialized()
方法,使该部分看起来工作正常,但不幸的是,ServletContext不包含属性javax.websocket.server.ServerContainer
,因此返回null
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
final ServerContainer serverContainer = (ServerContainer) servletContextEvent
.getServletContext()
.getAttribute("javax.websocket.server.ServerContainer");
// *** serverContainer is null ***
try {
serverContainer.addEndpoint(ChatAnnotation.class);
}
catch (DeploymentException e) { e.printStackTrace(); }
}
唯一可用的属性是javax.servlet.context.tempdir
,org.eclipse.jetty.util.DecoratedObjectFactory
,org.eclipse.jetty.tlds
,org.eclipse.jetty.resources
,org.eclipse.jetty.webFragments
我做错了什么?这完全是一个嵌入问题吗?它是否能在标准码头正常运行(即未嵌入)
嵌入代码如下所示:
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setResourceBase(webroot);
webapp.setDescriptor(webroot + "/WEB-INF/web.xml");
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.setConnectors(new ServerConnector[] { connector });
server.setHandler(webapp);
server.start();
server.join();
JSR ServerContainer未在嵌入式jetty中自动初始化
使用WebSocketServerContainerInitializer
WebAppContext webapp=new WebAppContext();
webapp.setContextPath(“/”);
webapp.setResourceBase(webroot);
setDescriptor(webroot+“/WEB-INF/WEB.xml”);
服务器=新服务器();
ServerConnector连接器=新的ServerConnector(服务器);
连接器。设置端口(8080);
setConnectors(新的ServerConnector[]{connector});
setHandler(webapp);
//添加这一行
WebSocketServerContainerInitializer.configureContext(webapp);
server.start();
join();
注意:WebSocketServerContainerInitializer
是一个javax.servlet.ServerContainerInitializer
,您可以设置嵌入式jetty
自动执行该ServerContainerInitializer
如果您严重依赖于注释的字节码扫描,或者有一个javax.websocket.server.ServerApplicationConfig
实现,那么您需要让servercontainerinInitializer
自动执行
注意:javax.servlet.ServerContainerInitializer
仅对org.eclipse.jetty.webapp.WebAppContext
有效
如果使用org.eclipse.jetty.servlet.ServletContextHandler
(嵌入式jetty中更常见的形式),则不能使用javax.servlet.ServerContainerInitializer
要进行设置,请执行以下操作:
private void enableAnnotationScanning(服务器)
{
Configuration.ClassList ClassList=Configuration.ClassList.setServerDefault(服务器);
classlist.addAfter(“org.eclipse.jetty.webapp.FragmentConfiguration”,
“org.eclipse.jetty.plus.webapp.EnvConfiguration”,
“org.eclipse.jetty.plus.webapp.PlusConfiguration”);
classlist.addBefore(“org.eclipse.jetty.webapp.JettyWebXmlConfiguration”,
“org.eclipse.jetty.annotations.AnnotationConfiguration”);
}
// ... 后来。。。
服务器=新服务器();
enableAnnotationScanning(服务器);
感谢您的及时回复。因此,澄清一下,这是一个严格的嵌入问题,在部署到标准Servlet容器时不应该发生,对吗?添加该行会在早期引发另一个NPE:线程“main”java.lang.NullPointerException中的异常与目标VM断开连接,地址:'127.0.0.1:50113',传输:org.eclipse.jetty.websocket.jsr356.server.deploy.websocketservercontainerininitializer.configureContext(websocketservercontainerininitializer.java:100)
我更新了您的答案。必须在server.setHandler(webapp)
之后下移行,这修复了两个NPE。谢谢只要在jetty分发版中启用了--module=websocket
,它就可以在不需要额外行的情况下工作。实际上,我试图避免扫描,因为它们会延长启动时间。嵌入式Jetty主要用于开发目的,因此添加该线路不是问题。我正在讨论是否在这个项目中使用Jetty Websocket
和Tomcat Websocket
,而Tomcat的依赖关系似乎更“有条理”(我可能错了),所以至少目前我选择了Tomcat。我可能会转用Jetty,因为你们在这里提供了巨大的支持。