我在我的应用程序中嵌入码头以通过 websockets 进行通信,如何定义不同的路径?

I'm embedding jetty in my app to communicate over websockets, how can define different paths?

我有一个 java 服务器需要与 Web 客户端进行实时通信。为此,我嵌入了 Jetty 9。Jetty 将充当 Web 客户端的静态 Web 服务器以及 WebSocket 服务器。根据我在网上找到的示例,静态页面处理程序和 WS 处理程序都在同一路径下提供服务。我不清楚如何让码头从两条不同的路径为他们提供服务。我会很感激任何指示。这是我的代码

public static void main(String ...args) throws Exception {
    Server server = new Server(8080);

    ResourceHandler resource_handler = new ResourceHandler();
    resource_handler.setDirectoriesListed(true);
    resource_handler.setWelcomeFiles(new String[]{ "index.html" });
    resource_handler.setResourceBase("./webapp");


    WebSocketHandler wsHandler = new WebSocketHandler() {
        @Override
        public void configure(WebSocketServletFactory factory) {
            factory.register(MyWebSocketHandler.class);
        }
    };

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler,wsHandler, new DefaultHandler() });
    server.setHandler(handlers);

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

使用 ContextHandlerCollection 并将 WebSockets 包裹在 ContextHandler 个对象中。

    ContextHandlerCollection contexts = new ContextHandlerCollection();
    contexts.addHandler(new ContextHandler(wsFooHandler, "/foo"));
    contexts.addHandler(new ContextHandler(wsBarHandler, "/bar"));

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler, contexts, new DefaultHandler() });

但是,将 ServletContextHandlerWebSocketUpgradeFilter 及其 addMapping 一起使用可以让您以更强大的方式控制 websocket 创建。

示例:

public static void main(String... args) throws Exception
{
    Server server = new Server(8080);

    ServletContextHandler context = new ServletContextHandler();
    context.setContextPath("/");
    context.setWelcomeFiles(new String[] { "index.html" });

    WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);

    filter.addMapping(new ServletPathSpec("/foo/*"),new SingleWebSocketCreator(FooSocket.class));
    filter.addMapping(new ServletPathSpec("/bar/*"),new SingleWebSocketCreator(BarSocket.class));
    filter.addMapping(new ServletPathSpec("/*.ws"),new SingleWebSocketCreator(WsTypeSocket.class));
    filter.addMapping(new RegexPathSpec("/chat/room/[a-zA-z_]*/public"),new SingleWebSocketCreator(ChatSocket.class));

    // add your own non-websocket servlets
    context.addServlet(HelloServlet.class,"/hello");

    // Lastly, the default servlet for root content (serves up static content)
    // It is important that this is last.
    ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
    holderPwd.setInitParameter("resourceBase","./webapp");
    holderPwd.setInitParameter("dirAllowed","true");
    context.addServlet(holderPwd,"/");

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { context, new DefaultHandler() });
    server.setHandler(handlers);

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

并且不小心遗漏了 SingleWebSocketCreator ...

public class SingleWebSocketCreator implements WebSocketCreator
{
    private Class<?> endpoint;

    public SingleWebSocketCreator(Class<?> websocketEndpoint)
    {
        this.endpoint = websocketEndpoint;
    }

    @Override
    public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
    {
        try
        {
            // new instance of endpoint for each upgrade
            return endpoint.newInstance();
        }
        catch (InstantiationException | IllegalAccessException e)
        {
            // failure to instantiate can flow out
            throw new RuntimeException(e);
        }
    }
}