简体   繁体   English

如何以编程方式在嵌入式tomcat中添加Websocket端点?

[英]How can I programmatically add a websocket endpoint in embedded tomcat?

I've been trying for weeks to get websockets working with embedded tomcat. 我已经尝试了数周时间,以使Websocket与嵌入式tomcat一起工作。 I've tried emulating the examples in the tomcat unit tests to no avail. 我试图模拟tomcat单元测试中的示例,但毫无用处。 This is the first time I've tried to use websockets so I'm likely making a foolish mistake. 这是我第一次尝试使用websocket,因此我很可能犯了一个愚蠢的错误。 Does anyone have any simple "Echo" examples for embedded tomcat websockets? 有没有人为嵌入式tomcat Websocket提供任何简单的“ 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?

}

I was using WebSocket in such way: 我以这种方式使用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);
}
}


And JS call: 和JS调用:

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


Java call: Java调用:

  TestWebSocketEndPoint.sendToAll(result);

For programmatic (non-annotated) endpoints, you have to provide a class that implements Endpoint to act as the server end, and then either: 对于编程(无注释)端点,您必须提供一个实现Endpoint充当服务器端的类,然后执行以下任一操作:

  1. Deploy a class that implements ServerApplicationConfig in your WAR file, that supplies EndpointConfig information about some or all of the non-annotated Endpoint instances that were found in the WAR file, or 在您的WAR文件中部署一个实现ServerApplicationConfig的类,该类提供有关在WAR文件中找到的一些或所有未注释的Endpoint实例的EndpointConfig信息,或者
  2. Call ServerContainer.addEndpoint() during the deployment phase of your webapp. 在您的Web应用程序的部署阶段调用ServerContainer.addEndpoint()

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

As far as I know, configuring a websocket is the same as configuring a servlet (or a servlet filter). 据我所知,配置websocket与配置servlet(或servlet过滤器)相同。 In web.xml you must include <async-supported>true</async-supported> . 在web.xml中,您必须包含<async-supported>true</async-supported>

I assume there's a similar flag in the java config. 我假设在Java配置中有一个类似的标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM