heroku 无法处理网络套接字

heroku is not able to process web socket

我正在尝试将 web 套接字与 spark 一起使用,并且我正在使用 /chat 作为终点 url。以下是我的代码。

@ServerEndpoint("/chat")
public class Main {

  public static void main(String[] args) {
    port(Integer.valueOf(System.getenv("PORT")));
    Spark.staticFileLocation("/public");    
  }

  private static final Set<Session> sessions = Collections
          .synchronizedSet(new HashSet<Session>());

  private static final HashMap<String, String> nameSessionPair = new HashMap<String, String>();

  private JSONUtils jsonUtils = new JSONUtils();

  public static Map<String, String> getQueryMap(String query) {
      Map<String, String> map = Maps.newHashMap();
      if (query != null) {
          String[] params = query.split("&");
          for (String param : params) {
              String[] nameval = param.split("=");
              map.put(nameval[0], nameval[1]);
          }
      }
      return map;
  }

  @OnOpen
  public void onOpen(Session session) {

      System.out.println(session.getId() + " has opened a connection");

      Map<String, String> queryParams = getQueryMap(session.getQueryString());

      String name = "";

      if (queryParams.containsKey("name")) {

        name = queryParams.get("name");
          try {
              name = URLDecoder.decode(name, "UTF-8");
          } catch (UnsupportedEncodingException e) {
              e.printStackTrace();
          }

          nameSessionPair.put(session.getId(), name);
      }

      sessions.add(session);

      try {
          session.getBasicRemote().sendText(
                  jsonUtils.getClientDetailsJson(session.getId(),
                          "Your session details"));
      } catch (IOException e) {
          e.printStackTrace();
      }

      sendMessageToAll(session.getId(), name, " joined conversation!", true,
              false);

  }

  @OnMessage
  public void onMessage(String message, Session session) {

      System.out.println("Message from " + session.getId() + ": " + message);

      String msg = null;

      try {
          JSONObject jObj = new JSONObject(message);
          msg = jObj.getString("message");
      } catch (JSONException e) {
          e.printStackTrace();
      }

      sendMessageToAll(session.getId(), nameSessionPair.get(session.getId()),
              msg, false, false);
  }

  @OnClose
  public void onClose(Session session) {

      System.out.println("Session " + session.getId() + " has ended");

      String name = nameSessionPair.get(session.getId());

      sessions.remove(session);

      sendMessageToAll(session.getId(), name, " left conversation!", false,
              true);

  }

  private void sendMessageToAll(String sessionId, String name,
          String message, boolean isNewClient, boolean isExit) {

      for (Session s : sessions) {
          String json = null;

          if (isNewClient) {
              json = jsonUtils.getNewClientJson(sessionId, name, message,
                      sessions.size());

          } else if (isExit) {
              json = jsonUtils.getClientExitJson(sessionId, name, message,
                      sessions.size());
          } else {
              json = jsonUtils
                      .getSendAllMessageJson(sessionId, name, message);
          }

          try {
              System.out.println("Sending Message To: " + sessionId + ", "
                      + json);

              s.getBasicRemote().sendText(json);
          } catch (IOException e) {
              System.out.println("error in sending. " + s.getId() + ", "
                      + e.getMessage());
              e.printStackTrace();
          }
      }
  }
}

问题是 onOpen 方法从未被调用,当用户到达终点 url 时,它抛出 404 错误。为什么? 我正在使用 heroku 部署它,我使用 socket_url 作为我的站点名称,我在我的 js 文件中将端口留空。

我该如何解决这个问题?

此代码不适用于 example from Heroku.com. It is because tomcat and jetty runners don't have support for websockets annotation (don't know the reason). You will be able to run it using embedded Jetty. Example of main method, pom for maven and procfile for heroku you can find at privateblog.info:

web:    java $JAVA_OPTS -cp target/JettyServer-0.0.1-SNAPSHOT-jar-with-dependencies.jar info.privateblog.Proxy $PORT