【问题标题】:How can I programmatically add a websocket endpoint in embedded tomcat?如何以编程方式在嵌入式 tomcat 中添加 websocket 端点?
【发布时间】:2016-01-28 08:54:03
【问题描述】:

我已经尝试了数周来让 websockets 与嵌入式 tomcat 一起工作。我尝试在 tomcat 单元测试中模拟示例无济于事。这是我第一次尝试使用 websockets,所以我可能会犯一个愚蠢的错误。有没有人有嵌入式 tomcat websockets 的简单“Echo”示例?

public void run() {

    if(!new File(consoleAppBase).isDirectory())
    {
         consoleAppBase = Paths.get("").toAbsolutePath().toString() + File.separatorChar + "wepapp";
    }

    tomcat = new Tomcat();

    tomcat.getService().removeConnector(tomcat.getConnector()); // remove default
    tomcat.getService().addConnector(createSslConnector(ConfigManager.getWeb_securePort())); // add secure option

    StandardServer server = (StandardServer) tomcat.getServer();
    AprLifecycleListener listener = new AprLifecycleListener();
    server.addLifecycleListener(listener);

    try {
        SecurityConstraint constraint = new SecurityConstraint();
        constraint.setDisplayName("SSL Redirect Constraint");
        constraint.setAuthConstraint(true);
        SecurityCollection collection = new SecurityCollection();
        collection.addPattern("/*");
        constraint.addAuthRole("administrator");
        constraint.addCollection(collection);

        //create the console webapp.
        consoleContext = tomcat.addWebapp(consoleContextPath, consoleAppBase);
        consoleContext.addConstraint(constraint);

        //this allows that little login popup for the console webapp.
        LoginConfig loginConfig = new LoginConfig();
        loginConfig.setAuthMethod("BASIC");
        consoleContext.setLoginConfig(loginConfig);
        consoleContext.addSecurityRole("administrator");

        //this creates a valid user.
        tomcat.addUser(ConfigManager.getWeb_username(), Encryptor.decrypt(ConfigManager.getWeb_passwordEncrypted()));
        tomcat.addRole("admin", "administrator");

    } catch (ServletException e) {
        LogMaster.getWebServerLogger().error("Error launching Web Application. Stopping Web Server.");
        LogMaster.getErrorLogger().error("Error launching Web Application. Stopping Web Server.", e);
        return;
    }

    addServlets(); // this is where I usually call a convenience method to add servlets

    // How can I add websocket endpoints instead?

}

【问题讨论】:

  • 我的回答中的代码仅在 Tomcat 8 上运行良好。
  • 在您的帮助下,我能够让它在 Tomcat 7 中工作。非常感谢
  • 它适用于 Tomcat 7.0.41 或 42 左右。

标签: java tomcat embedded-tomcat-7


【解决方案1】:

对于编程(非注释)端点,您必须提供一个实现 Endpoint 的类来充当服务器端,然后:

  1. 在您的 WAR 文件中部署一个实现 ServerApplicationConfig 的类,该类提供有关在 WAR 文件中找到的部分或全部非注释 Endpoint 实例的 EndpointConfig 信息,或者
  2. 在您的网络应用部署阶段致电ServerContainer.addEndpoint()

请参阅 Java™ API for WebSocket,JSR 356。

【讨论】:

    【解决方案2】:

    我是这样使用 WebSocket 的:

    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    //...
    
    @ServerEndpoint("/move")
    public class TestWebSocketEndPoint {//@OnMessage 
    public void onMessage(Session session, String message) {}
    private static final Queue<Session> QUEUE = new ConcurrentLinkedQueue<Session>();
    
    @OnOpen
    public void open(Session session) {
        QUEUE.add(session);
    }
    
    @OnError
    public void error(Session session, Throwable t) {
        StaticLogger.log(TestWebSocketEndPoint.class, t);
        QUEUE.remove(session);
    }
    
    @OnClose
    public void closedConnection(Session session) {
        QUEUE.remove(session);
    }
    
    public static void sendToAll(String message) throws IOException {
        ArrayList<Session> closedSessions = new ArrayList<Session>();
        for (Session session : QUEUE) {
            if (!session.isOpen()) {
                closedSessions.add(session);
            } else {
                session.getBasicRemote().sendText(message);
            }
        }
        QUEUE.removeAll(closedSessions);
    }
    }
    


    和JS调用:

    var webSocket;
    webSocket = new WebSocket("ws://localhost:8585/test/move");
    webSocket.onmessage = function () {
        alert('test');
    }
    


    Java 调用:

      TestWebSocketEndPoint.sendToAll(result);
    

    【讨论】:

    • 这不是以编程方式添加端点,这是一个带注释的端点,由ServerContainer 自动添加。
    【解决方案3】:

    据我所知,配置 websocket 与配置 servlet(或 servlet 过滤器)相同。在 web.xml 中,您必须包含 &lt;async-supported&gt;true&lt;/async-supported&gt;

    我假设 java 配置中有一个类似的标志。

    【讨论】:

    • 配置 WebSocket 与配置 servlet 或 servlet 过滤器不同; Servlet 不需要async-supported,更不用说 WebSocket 端点了;在任何情况下,这都不是程序化解决方案。
    猜你喜欢
    • 2012-07-19
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2014-08-20
    • 2014-01-18
    • 2012-08-31
    • 1970-01-01
    相关资源
    最近更新 更多