我对XMPP和Spring Integration完全陌生,并且想向FCM用户发送消息。我为出站消息创建了XML配置,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-xmpp="http://www.springframework.org/schema/integration/xmpp"
...>
<context:component-scan base-package="com.avantovr.esysync_backend.webservices.restful.fcm.xmppserver" />
<int-xmpp:outbound-channel-adapter id="xmppOutboundAdapter" channel="xmppOutboundChannel" xmpp-connection="xmppConnection"/>
<int:service-activator ref="fcmSender" input-channel="xmppOutbound" />
<int:logging-channel-adapter id="xmppOutboundChannel" log-full-message="true" />
</beans>
现在,我想创建一个Java类,其中有一种用于通过XMPP将Downstrwam messagr发送到FCM的方法。请问有任何初学者通过Spring集成向FCM发送和接收xmpp消息的示例吗?
答案 0 :(得分:0)
这可能不是最佳解决方案,但对我来说足够好。第一次处理XMPP。
除了pom.xml依赖项之外,我没有任何XML配置。
睡眠5秒钟,断开连接后重新连接。 FCM会不时断开XMPP连接以平衡负载。
发回ACK正常,未测试接收ACK和NACK。
要从Java-> fcm->手机发送消息;
@Autowired
private XmppConfig xmppConfig;
xmppConfig.getXmppConnection().sendStanza(generateStanza(messageId,json));
来自https://firebase.google.com/docs/cloud-messaging/server 的 json应该是这样的
快速依赖 application.properties XmppConfig.java XmppService.java {
"to":"REGISTRATION_ID", // "to" replaces "registration_ids"
"message_id":"m-1366082849205" // new required field
"data":
{
"hello":"world",
}
"time_to_live":"600",
"delivery_receipt_requested": true/false
}
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-tcp</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-java7</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-extensions</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>
fcm.sender_id=YOUR_SENDER_ID@fcm.googleapis.com
fcm.server_key=YOUR_SERVER_KEY
fcm.host=fcm-xmpp.googleapis.com
fcm.port=5235
import com.alessoft.utils.Utils;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.stringprep.XmppStringprepException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.net.ssl.SSLSocketFactory;
@Configuration
class XmppConfig implements ConnectionListener {
@Value("${fcm.sender_id}")
private String senderId;
@Value("${fcm.server_key}")
private String server_key;
@Value("${fcm.host}")
private String host;
@Value("${fcm.port}")
private int port;
@Autowired
private XmppService xmppService;
private Logger logger = LoggerFactory.getLogger(XmppConfig.class);
private volatile boolean xmppConnected;
private XMPPTCPConnection xmppConnection;
public XMPPTCPConnection getXmppConnection() {
return xmppConnection;
}
@PostConstruct
public void postConstruct() throws Exception {
new Thread(() -> prepareXmppConnection()).start();
}
public XMPPConnection prepareXmppConnection() {
XMPPTCPConnectionConfiguration conf = null;
try {
conf = XMPPTCPConnectionConfiguration.builder()
.setHost(host)
.setPort(port)
.setSendPresence(false)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setSocketFactory(SSLSocketFactory.getDefault())
.setUsernameAndPassword(senderId, server_key)
.setXmppDomain("somedomain.com")
.build();
} catch (XmppStringprepException e) {
logger.info("prepareXmppConnection error", e);
}
xmppConnection = new XMPPTCPConnection(conf);
xmppConnection.addAsyncStanzaListener(xmppService, xmppService);
xmppConnection.addConnectionListener(this);
Roster.getInstanceFor(xmppConnection).setRosterLoadedAtLogin(false);
establishXmppConnection();
return xmppConnection;
}
private void establishXmppConnection() {
try {
xmppConnection.connect();
xmppConnection.login();
} catch (Exception e) {
logger.info("XMPP establishXmppConnection error", e);
}
}
@Override
public void connectionClosedOnError(Exception e) {
logger.info("LOST CONNECTION TO FCM XMPP ON ERROR", e);
Utils.sleep(5000);
establishXmppConnection();
}
@Override
public void connectionClosed() {
logger.info("LOST CONNECTION TO FCM XMPP");
Utils.sleep(5000);
establishXmppConnection();
}
@Override
public void connected(XMPPConnection connection) {
logger.info("CONNECTED TO FCM XMPP");
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
logger.info("AUTHENTICATED TO FCM XMPP");
}
}
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class XmppService implements StanzaListener, StanzaFilter {
private Logger logger = LoggerFactory.getLogger(XmppService.class);
@Autowired
private XmppConfig xmppConfig;
@Override
public void processStanza(Stanza stanzaXml) throws SmackException.NotConnectedException, InterruptedException, SmackException.NotLoggedInException {
JSONObject stanza = XML.toJSONObject(stanzaXml.toXML(null).toString());
if (!stanza.has("message")) return;
JSONObject message = stanza.getJSONObject("message");
if (message.has("type")) {
normalMessage(message);
} else {
otherMessage(message);
}
}
private void otherMessage(JSONObject message) {
JSONObject gcm = message.getJSONObject("gcm");
String contentString = gcm.getString("content");
JSONObject content = new JSONObject(contentString);
if (content.getString("message_type").equals("ack")) {
logger.info("RECEIVED ACK");
} else if (content.getString("message_type").equals("nack")) {
logger.info("RECEIVED NACK: \n" + content.toString(2));
} else {
logger.info("RECEIVED UNKNOWN: \n" + content.toString());
}
}
private void normalMessage(JSONObject message) {
JSONObject gcm = message.getJSONObject("gcm");
String contentString = gcm.getString("content");
JSONObject content = new JSONObject(contentString);
String message_id = content.getString("message_id");
String from = content.getString("from");
if (content.has("message_type")) {
logger.info("NOT FROM DEVICE:\n" + message.toString());
} else {
processMessage(content);
sendAck(message_id, from);
}
}
private void processMessage(JSONObject content) {
// your own processing
}
private void sendAck(String message_id, String regId) {
try {
JSONObject json = new JSONObject();
json.put("to", regId);
json.put("message_id", message_id);
json.put("message_type", "ack");
String messageString = String.format("<message><gcm xmlns=\"google:mobile:data\">%s</gcm></message>", json.toString());
Stanza stanza = PacketParserUtils.parseStanza(messageString);
xmppConfig.getXmppConnection().sendStanza(stanza);
} catch (Exception e) {
logger.info("fcm sending ack error", e);
}
}
private Stanza generateStanza(String messageId, JSONObject json) {
String messageString = String.format("<message id=\"%s\"><gcm xmlns=\"google:mobile:data\">%s</gcm></message>", messageId, json.toString());
try {
return PacketParserUtils.parseStanza(messageString);
} catch (Exception e) {
logger.info("generateStanza error", e);
return null;
}
}
@Override
public boolean accept(Stanza stanza) {
return true;
}
}