7

我正在尝试学习 GAE 的通道 API(使用 Java),但我不知道从哪里开始。

我浏览了Channel API Overview (Java),但出于简洁的目的,那里发布的代码并不完整。

而且由于我是新手,如果有完整的示例代码可用,那将非常有帮助。

谢谢, 史瑞

4

2 回答 2

33

您链接到的 Channel API 概述中的代码非常完整,只是有点到处都是。我承认,一旦你理解了它,我觉得它比他们看起来的要简单得多,但我很高兴他们在提供太多信息方面犯了错误。

在没有无关信息的情况下为此提供完整的解决方案有点困难,因为您将如何使用 Channel API 有点依赖于您现有应用程序的基础架构。出于这个原因,我试图详细说明 AppEngine 文档提供的内容,希望您能更好地理解。如果您有任何问题,评论将允许您提出具体问题。

首先,一些词汇:

  • 通道消息:您希望发送给客户端的消息(可能是您首先使用通道 API 的原因)。
  • Channel Key:用户唯一的字符串和用户尝试发送消息的范围。
  • Channel Token:对任何客户端都是唯一的字符串。每个客户每 2 小时 1 个通道令牌。
  • Channel Service: AppEngine 服务器端类,它提供了一种创建通道并通过它们发送通道消息的方法。

在服务器上,您将需要执行以下操作:

ChannelService channelService = ChannelServiceFactory.getChannelService();

// The channelKey can be generated in any way that you want, as long as it remains
// unique to the user.
String channelKey = "xyz";
String token = channelService.createChannel(channelKey);

获得令牌后,您只需要某种方式将其发送到客户端代码。您链接到的 AppEngine 文档通过从 Java servlet 提供 HTML 并调用index.replaceAll("\\{\\{ token \\}\\}", token).

这是如何工作的,他们所做的是将文字字符串{{ token }}放入他们的 JavaScript 代码中(如下所示),因此无论{{ token }}出现在 JavaScript 代码中的什么地方,它都会被channelService.createChannel(...)上面调用生成的实际令牌替换。请注意,您不需要将令牌注入以这种方式提供服务的客户端代码中,但这是一个很好的起点,因为他们就是这样做的(并记录了它)。


现在您已经将令牌注入到 JavaScript 中,您需要将带有通道令牌的代码获取到客户端(请注意,如上所述,您也可以只获取客户端的令牌,并以这种方式创建通道)。他们拥有的代码是:

<body>
  <script>
    channel = new goog.appengine.Channel('{{ token }}');
    socket = channel.open();
    socket.onopen = onOpened;
    socket.onmessage = onMessage;
    socket.onerror = onError;
    socket.onclose = onClose;
  </script>
</body>

他们删除了有关如何从服务器上的文件中读取此内容的详细信息,但同样,您可以以任何您喜欢的方式执行此操作。您也可以resp.getWriter().print(index)在 JavaServlet 中直接打印字符串,其中index是存储上面列出的 HTML/JavaScript 内容的字符串。就像我最初所说的那样,最适合您的应用程序现有基础架构的东西取决于您。

它们旨在让您定义自己的 JavaScript 函数onOpened, onMessage, onError, 并onClose在通道打开、接收消息、遇到错误或关闭时分别调用。您可能希望创建简单的实现以更好地了解正在发生的事情:

function onOpened() {
    alert("Channel opened!");
}

function onMessage(msg) {
    alert(msg.data);
}

function onError(err) {
    alert(err);
}

function onClose() {
    alert("Channel closed!");
}

我仍然建议将它们分成单独的函数,以便您可以更轻松地扩展它们来玩弄和解决问题。有关 JavaScript API 的更多详细信息,请参阅Channel API JavaScript 参考


您需要建立一种机制来获取要从客户端发送到服务器的数据。再一次,你希望如何做到这一点并不重要。AppEngine 文档建议设置一个XMLHttpRequest来实现该目的。

sendMessage = function(path, opt_param) {
  path += '?g=' + state.game_key;
  if (opt_param) {
    path += '&' + opt_param;
  }
  var xhr = new XMLHttpRequest();
  xhr.open('POST', path, true);
  xhr.send();
};

这里,opt_param只是格式中的一串可选参数x=1&y=2&z=3。这是他们为 Tic-Tac-Toe 示例应用程序构建的所有基础设施,对于 Channel API 的功能并不重要;就像我说的,你可以随意拨打这个电话。

path是应该处理消息发送和接收的 servlet(您需要在 web.xml 文件中设置)的路径(请参阅下一节)。


将消息从客户端发送到服务器后,您将需要一个 servlet,它可以向具有相同通道密钥的所有客户端发送更新

ChannelService channelService = ChannelServiceFactory.getChannelService();

// This channelKey needs to be the same as the one in the first section above.
String channelKey = "xyz"

// This is what actually sends the message.
channelService.sendMessage(new ChannelMessage(channelKey, "Hello World!"));

上面的channelService.sendMessage(...)调用是实际发送消息的内容,以便onMessage您在上一节中定义的函数可以接收它。


我希望这个答案是完整的(就此而言,是正确的)足以帮助您入门。他们在文档中(以及我的代码)中的大部分内容都可以复制和粘贴,只需稍作调整。

于 2011-11-25T16:54:07.433 回答
13

我是 StackOverflow 的新手,不确定这个问题是否仍然存在,但如果您仍在寻找使用 Google 的 Channel API 的完整 Java 示例,ServerSide(Java) 和 Client(Java) 都可以找到详细描述我'在这里写了:http: //masl.cis.gvsu.edu/2012/01/31/java-client-for-appengine-channels/

它列出了从创建通道(客户端和服务器)、在通道上发送消息(客户端和服务器)以及 Java 客户端可以用来与通道交互的简单框架的所有内容。我也很难理解 Google 的文档并理解这一切。我希望这些信息仍然具有相关性和帮助性:-)

完整的源代码和聊天示例可以在 GitHub 上找到:https ://github.com/gvsumasl/jacc

这是一些示例代码,我希望这会有所帮助:-)


Java 客户端通道创建(使用 ChannelAPI 框架:Jacc)

ChatListener chatListener = new ChatListener();
ChannelAPI channel = new ChannelAPI("http://localhost:8888", "key", chatListener);
channel.open();

Java 服务器端通道创建:

public class ChatChannelServlet extends HttpServlet {
  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {    
    String channelKey = req.getParameter("c");

    //Create a Channel using the 'channelKey' we received from the client
    ChannelService channelService = ChannelServiceFactory.getChannelService();
    String token = channelService.createChannel(channelKey);

    //Send the client the 'token' + the 'channelKey' this way the client can start using the new channel
    resp.setContentType("text/html");
    StringBuffer sb = new StringBuffer();
    sb.append("{ \"channelKey\":\"" + channelKey + "\",\"token\":\"" + token + "\"}");

    resp.getWriter().write(sb.toString());
  }
}

Java 客户端消息发送(使用 ChannelAPI 框架:Jacc)

/***
* Sends your message on the open channel
* @param message
*/
public void sendMessage(String message){
try {
        channel.send(message, "/chat");
    } catch (IOException e) {
        System.out.println("Problem Sending the Message");
    }
}

Java 服务器端消息发送:

public class ChatServlet extends HttpServlet {
  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String channelKey = req.getParameter("channelKey");
    String message = req.getParameter("message");

    //Send a message based on the 'channelKey' any channel with this key will receive the message
    ChannelService channelService = ChannelServiceFactory.getChannelService();
    channelService.sendMessage(new ChannelMessage(channelKey, message));
  }
}
于 2012-02-09T17:02:00.107 回答