Jetty 中的 JSR-356 javax websockets(嵌入式和非嵌入式)

JSR-356 javax websockets in Jetty (embedded and not)

鉴于:

我想将打包为 WAR 并包含 web.xml 的 webapp 部署到 Jetty 服务器。

在该应用程序中,我希望能够配置 JSR-356 指定的 javax websocket 端点。我更喜欢通过 ServerEndpointConfig 而不是 注释扫描来提供这些端点。

有许多资源举例说明了嵌入式 Jetty,利用著名的 WebSocketServerContainerInitializer.configureContext(context); API。显然,我不能那样做。

还有其他的,直接跳转到ServletContextListener,通过著名的context.getAttribute("javax.websocket.server.ServerContainer"获得ServerContainer。到目前为止,我通过这个 API 得到了很多 NULL,所以显然没有添加容器。

问题:

缺少的配置是什么?最好通过 web.xml 来完成吗?如果它是关于 jetty.xmljetty.ini 之类的配置文件 - 示例会很好,同样,最好是 xml 语法。

更新:

根据下面的答案(已接受的答案),正如我实际上试图在这里描述的那样 - 已知的配置方式 absolutely 工作得很好。说已知我的意思是通过将 --module=websocket 添加到非嵌入式 Jetty 的某些 *.ini 文件,或者通过调用 WebSocketServerContainerInitializer.configureContext 来获得嵌入式 Jetty。

所以重新表述这个问题:是否有人 experience/knowledge 通过纯粹基于 XML 的配置来启用 websocket 模块?

如果使用 ${jetty.base}${jetty.home} recommended installation process for Standalone Jetty,您应该转到 ${jetty.base} 实例目录并启用 websocket 模块。

$ cd /path/to/mybase
$ java -jar /opt/jetty/jetty-home-9.4.14.v20181114/start.jar --add-to-start=websocket
$ grep "websocket" start.ini
--module=websocket

现在您已为该 ${jetty.base} 实例启用了 websocket。

如果您希望 Jetty 通过字节码扫描您已部署的 Web 应用程序的注释来发现您的服务器 WebSocket 端点,那么您还需要 annotations 模块。

$ cd /path/to/mybase
$ java -jar /opt/jetty/jetty-home-9.4.14.v20181114/start.jar --add-to-start=annotations
$ grep "annotations" start.ini
--module=annotations

完成后,您可以执行以下一项(或多项)操作以将 websocket 服务器端点与您的 webapp 一起部署。

为什么这在独立 Jetty 中有效?独立 Jetty 正在做什么来使这成为可能?

发生以下情况:

  • websocket module 添加 lib/websocket/*.jar 到服务器 classpath
  • websocket 模块依赖于 clientannotations 模块
  • client module 添加 lib/jetty-client-<jetty.version>.jar 到服务器 classpath
  • annotations module 添加 lib/jetty-annotations-<jetty.version>.jarlib/annotations/*.jar 到服务器 classpath
  • annotations模块依赖于plus模块
  • annotations模块选择etc/jetty-annotations.xml启动时执行
  • annotations模块按名称添加JPMS模块org.objectweb.asm
  • plus module 添加 lib/jetty-plus-<jetty.version>.jar 到服务器 classpath
  • plus模块选择etc/jetty-plus.xml启动时执行
  • plus模块依赖于serversecurityjndiwebapptransactions模块

(我将跳过以这种方式选择的其余模块)

简而言之,只需添加 websocket 模块,您就可以获得以下服务器 class 路径条目

lib/websocket/*.jar
lib/jetty-client-<jetty.version>.jar
lib/jetty-annotations-<jetty.version>.jar
lib/annotations/*.jar
lib/jetty-plus-<jetty.version>.jar

以及以下 XML 个文件

lib/jetty-annotations.xml
lib/jetty-plus.xml

这两个 XML 文件只是修改服务器端的默认 Configuration 列表,使它们引入的 Configuration 行为可用于所有已部署的 WebApps。

您也可以 set the Configuration on the WebAppContext(在启动之前)针对 webapp 的特定行为。

示例:

WebAppContext context = new WebAppContext();
context.setContextPath("/");
context.setBaseResource(Resource.newResource(rootResourceUrl));

context.setConfigurations(new Configuration[] {
            new AnnotationConfiguration(),
            new WebXmlConfiguration(),
            new WebInfConfiguration(),
            new PlusConfiguration(), 
            new MetaInfConfiguration(),
            new FragmentConfiguration(), 
            new EnvConfiguration()});    

handlerList.addHandler(context);

Note: for javax.websocket you must use a WebAppContext, as the behaviors defined for its initialization require a full Web App to function. While you can use a ServletContextHandler with javax.websocket endpoints, this style is 100% manually defined, intialized, and declared, with no automatic bytecode / annotation scanning features that JSR-356 relies on.

您也可以从命令行看到所有这些。

显示活动的 ${jetty.base} 配置,XML 属性 值是什么,服务器 class 路径是什么,以及 XML 是什么被执行(以什么顺序!!)

$ cd /path/to/mybase
$ java -jar /opt/jetty/jetty-home-9.4.14.v20181114/start.jar --list-config

显示模块列表及其关联方式(以及在您的 ${jetty.base} 配置中选择的模块)

$ cd /path/to/mybase
$ java -jar /opt/jetty/jetty-home-9.4.14.v20181114/start.jar --list-modules