我正在编写与容器无关的Websocket服务器。我的开发环境使用IntelliJ IDEA和嵌入式Jetty版本9.3.11.v20160721
(嵌入下面的代码)。
但是,我的代码使用Tomcat Websocket库,tomcat-websocket-api
和tomcat-websocket
,版本8.5.4
。
我想用EndPoint
注册Websocket ServletContextListener
。根据{{3}}中的一些示例,以及Joakim Erdfelt(@ joakim-erdfelt)在SO和Jetty邮件列表中的一些答案,我编写了以下实现并通过listener
添加了它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.server.Executor
,org.eclipse.jetty.webFragments
我做错了什么?这严格来说是一个嵌入问题吗?它会在标准Jetty中正常运行(即未嵌入)吗?
嵌入代码如下:
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();
答案 0 :(得分:2)
JSR ServerContainer不会在embedded-jetty中自动初始化。
使用WebSocketServerContainerInitializer
...
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);
// Add this line
WebSocketServerContainerInitializer.configureContext(webapp);
server.start();
server.join();
注意:WebSocketServerContainerInitializer
是javax.servlet.ServerContainerInitializer
,您可以将embedded-jetty
设置为自动执行ServerContainerInitializer
。
如果您严重依赖注释的字节码扫描,或者实施javax.websocket.server.ServerApplicationConfig
,那么您希望自动执行ServerContainerInitializer
。
注意:
javax.servlet.ServerContainerInitializer
仅对org.eclipse.jetty.webapp.WebAppContext
有效。如果您使用
org.eclipse.jetty.servlet.ServletContextHandler
(嵌入式码头中更常见的表单),则无法使用javax.servlet.ServerContainerInitializer
。
要进行设置,请执行以下操作:
private void enableAnnotationScanning(Server server)
{
Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
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");
}
// ... later on ...
Server server = new Server();
enableAnnotationScanning(server);