【问题标题】:Programmatic ServerEndpoint wont work within Embedded Tomcat程序化 ServerEndpoint 在嵌入式 Tomcat 中不起作用
【发布时间】:2018-11-26 05:13:20
【问题描述】:

我有一个嵌入式 tomcat 正在运行,我正在尝试以编程方式设置 websocket,但不能使用注释,因为我动态获取上下文路径列表。使用 Java 8 和 Tomcat 7。

下面是我正在使用的代码,

嵌入式Tomcat,

public class EmbeddedTomcat {
/**
 * @param args
 * @throws LifecycleException 
 */
public static void main(String[] args) throws LifecycleException {
    Tomcat tomcat = new Tomcat();
    tomcat.setPort(5555);

    Context ctx = tomcat.addContext("", new File(".").getAbsolutePath());

    Tomcat.addServlet(ctx, "hello", new HttpServlet() {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) 
                throws ServletException, IOException {
            Writer w = resp.getWriter();
            w.write("Hello World !!");
            w.flush();
            w.close();
        }
    });

    ctx.addServletMapping("/hello", "hello");

    ctx.addApplicationListener(WSContextListener.class.getName());

    tomcat.start();
    tomcat.getServer().await();
}

}

WebSocket 监听器动态添加端点,

public class WSContextListener extends WsContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
    super.contextInitialized(sce);

    ServerContainer sc =
            (ServerContainer) sce.getServletContext().getAttribute(
                    Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE);
    try {
        ServerEndpointConfig endPointConfig = ServerEndpointConfig.Builder
                .create(WSEndpoint.class, "/wshello")
                .build();
        sc.addEndpoint(endPointConfig);
    } catch(DeploymentException de) {
        de.printStackTrace();
    }
}

}

实际的服务器端点类,

public class WSEndpoint extends Endpoint {

/* (non-Javadoc)
 * @see javax.websocket.Endpoint#onOpen(javax.websocket.Session, javax.websocket.EndpointConfig)
 */
@Override
public void onOpen(Session session, EndpointConfig endpointConfig) {
    System.out.println(String.format("Opened a new session with Id[%s] associated to endpoint[%s]", session.getId(), session.getRequestURI().getPath()));

    session.addMessageHandler(new MessageHandler.Whole<String>() {
        @Override
        public void onMessage(String data) {
            System.out.println("Data received - " + data);
            session.getAsyncRemote().sendText(data);
        }
    });
}

@Override
public void onClose(Session session, CloseReason closeReason) {
    System.out.println(String.format("Closing the connection to endpoint[%s] for session Id[%s] ", session.getRequestURI().getPath(), session.getId()));
    super.onClose(session, closeReason);
}

@Override
public void onError(Session session, Throwable throwable) {
    System.out.println(String.format("Error [%s] occurred on session Id[%s] associated to endpoint[%s]", throwable.getMessage(), session.getId(), session.getRequestURI().getPath()));
    super.onError(session, throwable);
}

}

最后,连接到 Websocket 的 javascript 位,

var webSocket = new WebSocket("ws://localhost:5555/wshello");

我可以访问 servlet (http://localhost:5555/hello) 并且该位有效。当我尝试通过上面的 javascript 代码访问 websocket 时,它失败了,

websocket_test.html:18 WebSocket 连接到“ws://localhost:5555/wshello”失败:WebSocket 握手期间出错:意外响应代码:404

【问题讨论】:

    标签: java tomcat websocket


    【解决方案1】:

    试试这个

    var webSocket = new WebSocket("ws://localhost:5555/hello", "protocol");
    

    添加到客户端处理 websocket 的协议(可选)。 删除 wshello "ws"

    【讨论】:

    • javascript api 不是问题,因为如果我尝试访问公共 websocket 服务器,它可以工作。 var webSocket = new WebSocket("wss://echo.websocket.org") 问题似乎出在服务器端。此外,为 websocket 配置的端点是“wshello”,所以不知道为什么应该在那里使用 servlet 端点“hello”。
    猜你喜欢
    • 2019-03-01
    • 1970-01-01
    • 2018-12-13
    • 2012-07-25
    • 2017-01-02
    • 2016-03-29
    • 2021-06-18
    • 1970-01-01
    • 2012-09-18
    相关资源
    最近更新 更多