如何在 Jetty 中设置多个处理程序并且在启动期间不出错

How to set multiple handlers in Jetty and not get an error during startup

我有一些服务器代码,如下所示:

private WebAppContext getAspireWebAppContext() {
    WebAppContext root = new WebAppContext();
    root.setWar(config().<String>property("war.file"));
    root.setContextPath("/");
    return root;
}

private Server startWebApp(int port) {
  try {
    server.setConnectors(createConnectors(port));
    ServletContextHandler context = getAspireWebAppContext();
    server.setHandler(context);

    // Ensure that a websocket always has a HttpSession
    context.addFilter(HttpSessionForWebsocketFilter.class,"/ws/*",null);
    // add websocket support
    ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext( context );
    wscontainer.addEndpoint(EngineSocket.class);
    wscontainer.addEndpoint(WorkbenchSocket.class);

    server.start();
  } ....
}

我想使用 HandlerList 这样我就可以添加一个 RewriteHandler。所以我试着改变它:

HandlerList handlers = new HandlerList();

server.setConnectors(createConnectors(port));
ServletContextHandler context = getAspireWebAppContext();
// server.setHandler(context);
handlers.addHandler(context);

// Ensure that a websocket always has a HttpSession
context.addFilter(HttpSessionForWebsocketFilter.class,"/ws/*",null);
// add websocket support
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext( context );
wscontainer.addEndpoint(EngineSocket.class);
wscontainer.addEndpoint(WorkbenchSocket.class);

// RewriteHandler stuff
// handlers.addHandler(rewrite);

server.setHandler(handlers);
server.start();

甚至在我添加更多处理程序之前,这会导致 WebSocketServerContainerInitializer.configureContext(context) 行出现空异常:

Caused by: java.lang.NullPointerException at org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext(WebSocketServerContainerInitializer.java:148)

我在某处读到 context.setServer(server); 可能有帮助,但无济于事。我究竟做错了什么?谢谢

首先将 HandlerList 添加到服务器。

Server server = new Server();
HandlerList handlers = new HandlerList();
server.setHandler(handlers);

ServletContextHandler context = getAspireWebAppContext();
handlers.addHandler(context);

ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext( context );
wscontainer.addEndpoint(EngineSocket.class);
wscontainer.addEndpoint(WorkbenchSocket.class);

// RewriteHandler stuff
handlers.addHandler(rewrite);

server.start();

但归根结底,这个 NPE 是一个内部尝试从属于您的 ServletContextHandler.

Server 中获取公共 HttpClient 的错误

打开为 https://github.com/eclipse/jetty.project/issues/3139

另外请注意,您应该知道无法可靠地将过滤器应用于 WebSocket 连接。

通过 JSR356 进行的 WebSocket 升级(您选择使用的 API)旨在在过滤器链之外进行升级。这是因为 Filter 可以修改 request/response、更改响应的提交状态、包装输入流、包装输出流等。所有这些在 WebSocket 升级期间都是被禁止的。虽然您的过滤器可能有时会起作用,但它不会在 100% 的时间内起作用。并且也不保证来自此类操作的 Set-Cookie header 会在响应中发回。

如果您切换到 Jetty Native WebSocket API,您可以控制升级发生的位置(同样禁止的操作适用)。从 WebSocketServlet 扩展,或从 WebSocketUpgradeFilter 扩展并应用您自己的逻辑,或者更好的是,提供您自己的 WebSocketCreator 来执行您需要的操作。