关于java:在jetty中部署webapps和websockets

Deploy webapps and websockets in jetty

我已将 Jetty 嵌入到我的应用程序中。我有一个 webapp,并且我成功地在 Jetty 中部署了该 webapp。现在我对 Websockets 有了另一个要求。我按照此链接在 Jetty 中部署 websockets。将 Websocket 部署到我的服务器后,第一个 web 应用程序无法正常工作(主页未打开)。这是图像

enter

1
2
3
4
5
6
7
8
9
10
List<Handler> handlersList = new ArrayList<Handler>();
WebAppContext webAppContext = new WebAppContext();
webAppContext.setResourceBase(webApp.appDir);
webAppContext.setDescriptor(webApp.appDir +"/WEB-INF/web.xml");
webAppContext.setContextPath(webApp.contextPath);
webAppContext.setParentLoaderPriority(true);
// webAppContext.setWar(webApp.appDir);
webAppContext.setVirtualHosts(webApp.hostName);
handlersList.add(webAppContext);
argNewServer.setHandler(handlersList);

WebSocket 部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/echo");
argServer.setHandler(context);

// Initialize javax.websocket layer
ServerContainer wscontainer;
try {
    wscontainer = WebSocketServerContainerInitializer.configureContext(context);
    // Add WebSocket endpoint to javax.websocket layer
    wscontainer.addEndpoint(WebSocketServer.class);
} catch (ServletException | DeploymentException e) {
    throw new RuntimeException("Exception while adding websocket endpoint:", e);
}

WebSocketServer.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.tdg.chat;

import java.io.IOException;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value ="/events/")
public class WebSocketServer {
    @OnOpen
    public void onWebSocketConnect(Session sess) {
        System.out.println("Socket Connected:" + sess);
    }

    @OnMessage
    public void onWebSocketText(Session argSession, String argMessage) throws IOException {
        System.out.println("Received TEXT message:" + argMessage);
        argSession.getBasicRemote().sendText("From Server:");
    }

    @OnClose
    public void onWebSocketClose(CloseReason reason) {
        System.out.println("Socket Closed:" + reason);
    }

    @OnError
    public void onWebSocketError(Throwable cause) {
        cause.printStackTrace(System.err);
    }
}

如果我包含上述 websocket 代码,则实际的 webapp 无法正常工作,但 websocket 代码正在运行。

那么如何在一个 Jetty 服务器上部署 webapp 和 websocket 呢?

更新:

我尝试将 Websockets 包含在当前 webapp 本身中,但出现以下异常。

java.lang.NullPointerException: null
at org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext(WebSocketServerContainerInitializer.java:65) ~[javax-websocket-server-impl-9.3.6.v20151106.jar:9.3.6.v20151106]
at com.tdg.daemon.server.RiseServer.getWebappHandlers(RiseServer.java:122) ~[classes/:na]
at com.tdg.daemon.server.RiseServer.addWebApps(RiseServer.java:77) ~[classes/:na]
at com.tdg.daemon.server.RiseServer.init(RiseServer.java:59) ~[classes/:na]
at com.tdg.daemon.server.RiseServerConfiguration.build(RiseServerConfiguration.java:475) ~[classes/:na]
at com.tdg.daemon.server.launcher.DefaultTdgServerLauncher.start(DefaultTdgServerLauncher.java:78) [classes/:na]
at com.tdg.daemon.server.launcher.DefaultTdgServerLauncher.main(DefaultTdgServerLauncher.java:140) [classes/:na]
java.lang.NullPointerException
at org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext(WebSocketServerContainerInitializer.java:65)
at com.tdg.daemon.server.RiseServer.getWebappHandlers(RiseServer.java:122)
at com.tdg.daemon.server.RiseServer.addWebApps(RiseServer.java:77)
at com.tdg.daemon.server.RiseServer.init(RiseServer.java:59)
at com.tdg.daemon.server.RiseServerConfiguration.build(RiseServerConfiguration.java:475)
at com.tdg.daemon.server.launcher.DefaultTdgServerLauncher.start(DefaultTdgServerLauncher.java:78)
at com.tdg.daemon.server.launcher.DefaultTdgServerLauncher.main(DefaultTdgServerLauncher.java:140)
[] 12/02/2015 17:50:06.985 [main - ] INFO c.t.d.s.l.DefaultTdgServerLauncher - RiseServer started on port 80 and 443.


WebSocketServerContainerInitializer.configureContext() 需要了解将在其下运行的 Server

有两种方法可以完成此操作,请在调用 WebSocketServerContainerInitializer.configureContext()

之前选择其中一种方法

  • 在尝试配置上下文之前,通过 Server.setHandler(Handler) 调用将 ServletContextHandler 添加到 Server 实例。 (ServletContextHandler 可以是更大的 Handler 树的一部分,这将起作用)。仅调用 Server.setHandler(Handler) 的行为就会为您声明的所有 Handler 实例填充 Server 引用。 (这是推荐的方法)
  • 手动调用 ServletContextHandler.setServer(server) - 但请注意不要换出/更改您稍后在 Server.setHandler(Handler) 调用中使用的 Server 实例。此外,一旦这样做,您就无法更改服务器中的内容,例如线程池、执行程序、缓冲池、调度程序等。(这是一种不受欢迎但实用的方法)

  • @Joakim Erdfelt,这是我的错误,我同意你的第二点。我所做的是,首先我将我的 webapp 处理程序添加到服务器,然后我将 websocket 处理程序添加到服务器(基于上述示例)。

    1
    2
    argNewServer.setHandler(webAppContext);
    argNewServer.setHandler(context);

    正如您在第二点中提到的,如果我们将处理程序设置为服务器,我们就无法修改服务器中的内容。没错,我修改了我的代码,就像我一次性添加了所有处理程序一样。然后我的 webapp 开始工作,我的 websocket 也在工作。这是修改后的代码

    1
    2
    3
    4
    List<Handler> handlersList = new ArrayList<Handler>();
    handlersList.add(webAppContext);
    handlersList.add(context);
    argNewServer.setHandler(handlersList);

    非常感谢@Joakim Erdfelt。