如何使用Java的Smack API发送自定义XML数据包?

时间:2011-06-17 15:16:32

标签: java xml xmpp smack

我正在使用Java中的Smack API连接到我的XMPP服务器。

我想发送一个这样的自定义消息包:

<message to="you@MyServer.com" type="chat" MYFIELD="custom stuff">
    <body> hi </body>
    <CUSTOM_STANZA A="..." B="..."> 
        C="..." 
        D="..."
    </CUSTOM_STANZA>
</message>

我猜我创建了我自己的Packet,它在它的toXML()方法中返回了这个XML。但这似乎不起作用。

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:7)

我不知道你为什么要在邮件中添加自定义属性。这在客户端上会出现问题,并且可能会导致服务器上出现问题,因为它与消息节的架构不匹配。

另一方面,消息内容很容易处理,因为@Femi用扩展包说。您需要创建一个扩展PacketExtension的MyExtension,该类中的toXML()将返回您的自定义节。

您可以通过以下方式创建和发送自定义消息:

Message message = new Message();
message.addExtension(new MyExtension());
chat.sendMessage(message);

要阅读本节,您需要注册一个provider,它将创建并返回您的自定义PacketExtension。您应该查看EmbeddedExtensionProvider,因为它会为您处理标记解析,从而简化了过程。

答案 1 :(得分:4)

我最近发现了如何在邮件中添加自定义节。一旦我弄清楚它就很容易了。我只需要使用自定义消息类扩展标准Message Class。

public class CustomMessage extends org.jivesoftware.smack.packet.Message {
  public CustomMessage() {
    super();
  }

  private String customStanza;

  /**
   * @param customStanza
   *            the customStanza to set
   */
  public void setCustomStanza(String customStanza) {
    this.customStanza = customStanza;
  }

  @Override
  public String toXML() {
    String XMLMessage = super.toXML();
    String XMLMessage1 = XMLMessage.substring(0, XMLMessage.indexOf(">"));
    String XMLMessage2 = XMLMessage.substring(XMLMessage.indexOf(">"));
    if (this.customStanza != null) {
      XMLMessage1 += " CustomStanza=\"" + this.customStanza + "\"";
    }

    return XMLMessage1 + XMLMessage2;
  }
}

然后使用自定义类发送如下消息:

CustomMessage message = new CustomMessage();
message.setCustomStanza("my data here");
System.out.println(message.toXML());
muc.sendMessage(message);

您的XML消息将如下所示:

<message id="ee7Y7-8" CustomStanza="my data here"></message>

答案 2 :(得分:2)

您可以使用packet extension:遗憾的是,没有使用数据包扩展的良好文档或示例。我之前看过this unresolved question有示例代码,但我无法让它工作:我没有例外,但它只是没有工作,因为我的扩展没有被调用,我继续只是编码我的消息正文中的数据。

编辑:对于后代,我设法让以下代码正常工作。它使用DOM4J类DocumentHelperElement

Presence np, packet = new Presence();
        packet.setID(sessionManager.nextStreamID().toString());
        packet.setFrom(server.createJID(operator, null));
        if(!available) packet.setType(Presence.Type.unavailable);
        else packet.setType(null);

        // add the custom XML
        Element xml = DocumentHelper.createElement(QName.get("custom", "http://www.custom.com/xmpp"));
        xml.addAttribute("type", "presenceupdate");
        packet.addExtension(new PacketExtension(xml));

温和幽默:一年后我碰到了我自己的答案,实际上是试图为一个真正的项目解决这个问题(而不是像我之前那样修修补补),因为我不能放弃它,我不得不把它弄清楚出。我想我会再次需要这个答案,所以在这里。所以:我在天空中的记忆。

编辑:发现了一种更简单的方法:

        Element xml = packet.addChildElement("custom", "http://www.custom.com/xmpp");
        xml.addAttribute("type", "presenceupdate");

要注意:尝试添加某些内容(在我的情况下,尝试添加延迟元素)会导致数据包无法路由。 Openfire中的东西吞噬了它,所以这是值得关注的。

答案 3 :(得分:1)

您需要定义一个自定义类实现ExtensionElement (由@ Flow表示)

可以获得产生以下节的非常详细的解释in this answer

<message id='923442621149' type='chat'><body>shanraisshan</body>
<reply xmlns='shayan:reply' rText='this is custom attribute'/>
</message>

其中回复是自定义扩展程序,其中包含

  1. 元素(回复)
  2. 命名空间(shayan:回复)
  3. 默认的xmpp名称空间列表位于Official XMPP website