Java 使用spring集成建立xmpp连接侦听器
我想在springboot中在android和appserver之间建立xmpp连接。android向app server发送消息,然后app server根据从android接收到的消息从firebase实时数据库中获取一些数据,最后app server将响应发送回android。问题是xmpp连接已建立,但侦听器不工作。需要帮忙吗`Java 使用spring集成建立xmpp连接侦听器,java,spring-boot,firebase-realtime-database,xmpp,smack,Java,Spring Boot,Firebase Realtime Database,Xmpp,Smack,我想在springboot中在android和appserver之间建立xmpp连接。android向app server发送消息,然后app server根据从android接收到的消息从firebase实时数据库中获取一些数据,最后app server将响应发送回android。问题是xmpp连接已建立,但侦听器不工作。需要帮忙吗` @Configuration public class XmppConfig implements org.jivesoftware.smack.Connec
@Configuration
public class XmppConfig implements org.jivesoftware.smack.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();
}*/
@Bean
public XMPPConnection prepareXmppConnection() {
logger.info("preparing TO FCM XMPP");
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(host)
.enableDefaultDebugger()
.build();
} catch (XmppStringprepException e) {
logger.info("prepareXmppConnection error", e);
}
xmppConnection = new XMPPTCPConnection(conf);
establishXmppConnection();
xmppConnection.addConnectionListener(this);
xmppConnection.addAsyncStanzaListener(xmppService, xmppService);
Roster.getInstanceFor(xmppConnection).setRosterLoadedAtLogin(false);
logger.info("finish preparing TO FCM XMPP");
return xmppConnection;
}
private void establishXmppConnection() {
try {
logger.info("establish XMPP connection ");
xmppConnection.connect();
xmppConnection.login();
} catch (Exception e) {
logger.info("XMPP establishXmppConnection error", e);
}
}
@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");
}
@Override
public void connectionClosed() {
logger.info("LOST CONNECTION TO FCM XMPP");
// Utils.sleep(5000);
establishXmppConnection();
}
@Override
public void connectionClosedOnError(Exception e) {
logger.info("LOST CONNECTION TO FCM XMPP ON ERROR", e);
//Utils.sleep(5000);
establishXmppConnection();
}
@Value("https://fcmapplication-9181f.firebaseio.com")
private String databaseUrl;
@Bean
public DatabaseReference firebaseDatabse() throws IOException {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("fcmapplication-9181f-firebase-adminsdk-mbpkv-
b742eac500.json");
FirebaseOptions options = new FirebaseOptions.Builder()
// .setServiceAccount(inputStream)
.setCredentials(GoogleCredentials.fromStream(inputStream))
.setDatabaseUrl(databaseUrl)
.build();
// FirebaseApp.initializeApp(options);
if (FirebaseApp.getApps().isEmpty()) {
FirebaseApp.initializeApp(options);
}
else {
FirebaseDatabase.getInstance().setPersistenceEnabled(false);
}
DatabaseReference firebase = FirebaseDatabase.getInstance().getReference("eye_case");
System.out.println("firebase ");
return firebase;
}
}
@Service
public class XmppService implements StanzaListener , StanzaFilter {
private Logger logger = LoggerFactory.getLogger(XmppService.class);
@Autowired
private XmppConfig xmppConfig;
@Override
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException {
JSONObject stanza;
try {
stanza = XML.toJSONObject(packet.toXML(null).toString());
if (!stanza.has("message")) return;
JSONObject message = stanza.getJSONObject("message");
if (message.has("type")) {
normalMessage(message);
} else {
otherMessage(message);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private void normalMessage(JSONObject message) {
JSONObject gcm;
JSONObject content=null;
String message_id="";
String from="";
try {
gcm = message.getJSONObject("gcm");
String contentString = gcm.getString("content");
content = new JSONObject(contentString);
message_id = content.getString("message_id");
from = content.getString("from");
} catch (JSONException e) {
e.printStackTrace();
}
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) {
try {
String action=content.getString("action");
if (action == "REGISTER") {
logger.info("Register Message");
}
else if (action == "ECHO") {
logger.info("Echo Message");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
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.xmppConnectionFactoryBean().getObject().sendStanza(stanza);
// xmppConfig.getXmppConnection().sendStanza(generateStanza(message_id,json));
} catch (Exception e) {
logger.info("fcm sending ack error", e);
}
}
private void otherMessage(JSONObject message) {
JSONObject gcm;
try {
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());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
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;
}
}
@配置
公共类XmppConfig实现org.jivesoftware.smack.ConnectionListener{
@值(${fcm.sender\u id}”)
私有字符串senderId;
@值(${fcm.server_key}”)
私有字符串服务器密钥;
@值(${fcm.host}”)
私有字符串主机;
@值(${fcm.port}”)
专用int端口;
/*@自动连线
私有XmppService XmppService*/
私有记录器Logger=LoggerFactory.getLogger(XmppConfig.class);
私有易失性布尔xmppConnected;
专用XMPPTCPConnection xmppConnection;
公共XMPPTCPConnection getXmppConnection(){
返回xmppConnection;
}
/*@施工后
public void postConstruct()引发异常{
新线程(()->prepareXmppConnection()).start();
}*/
@豆子
公共XMPPConnection prepareXmppConnection(){
logger.info(“准备FCM XMPP”);
xmpptcpconnectionconf=null;
试一试{
conf=XMPPTCPConnectionConfiguration.builder()
.setHost(主机)
.setPort(端口)
.setSendPresence(错误)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setSocketFactory(SSLSocketFactory.getDefault())
.SetUserName和密码(senderId,服务器密钥)
.setXmppDomain(主机)
.enableDefaultDebugger()
.build();
}捕获(xmppstringpreception e){
logger.info(“prepareXmppConnection错误”,e);
}
xmppConnection=新的XMPPTCPConnection(conf);
建立xmppconnection();
xmppConnection.addConnectionListener(此);
addAsyncStanzaListener(xmppService,xmppService);
getInstanceFor(xmppConnection).setRosterLoadedAtLogin(false);
logger.info(“完成对FCM XMPP的准备”);
返回xmppConnection;
}
私有连接xmppconnection(){
试一试{
logger.info(“建立XMPP连接”);
xmppConnection.connect();
xmppConnection.login();
}捕获(例外e){
logger.info(“XMPP建立xmppconnection错误”,e);
}
}
@凌驾
连接的公共void(XMPPConnection){
logger.info(“连接到FCM XMPP”);
}
@凌驾
已验证的公共void(XMPPConnection连接,布尔恢复){
logger.info(“通过FCM XMPP认证”);
}
@凌驾
公共无效连接关闭(){
logger.info(“与FCM XMPP的连接中断”);
//Utils.睡眠(5000);
建立xmppconnection();
}
@凌驾
public void connectionClosedOnError(异常e){
logger.info(“错误时与FCM XMPP的连接中断”,e);
//Utils.睡眠(5000);
建立xmppconnection();
}
@价值(”https://fcmapplication-9181f.firebaseio.com")
私有字符串数据库URL;
@豆子
公共数据库引用FirebaseDatabase()引发IOException{
InputStream InputStream=this.getClass()
.getClassLoader()
.getResourceAsStream(“FCMapApplication-9181f-firebase-adminsdk-mbpkv-
b742eac500.json);
FirebaseOptions=newfirebaseOptions.Builder()
//.setServiceAccount(inputStream)
.setCredentials(GoogleCredentials.fromStream(inputStream))
.setDatabaseUrl(数据库URL)
.build();
//FirebaseApp.initializeApp(选项);
if(FirebaseApp.getApps().isEmpty()){
FirebaseApp.initializeApp(选项);
}
否则{
FirebaseDatabase.getInstance().setPersistenceEnabled(false);
}
DatabaseReference firebase=FirebaseDatabase.getInstance().getReference(“eye_case”);
System.out.println(“firebase”);
返回火基;
}
}
@服务
公共类XmppService实现了StanzaListener、StanzaFilter{
私有记录器Logger=LoggerFactory.getLogger(XmppService.class);
@自动连线
私有XmppConfig XmppConfig;
@凌驾
public void processStanza(节数据包)抛出NotConnectedException、InterruptedException、NotLoggeDineException{
JSONObject节;
试一试{
stanza=XML.toJSONObject(packet.toXML(null.toString());
如果(!节有(“消息”))返回;
JSONObject message=stanza.getJSONObject(“消息”);
if(message.has(“type”)){
正常消息(消息);
}否则{
其他消息(message);
}
}捕获(JSONException e){
e、 printStackTrace();
}
}
私有无效消息(JSONObject消息){
JSONObject gcm;
JSONObject content=null;
字符串消息_id=“”;
字符串from=“”;
试一试{
gcm=message.getJSONObject(“gcm”);
String contentString=gcm.getString(“内容”);
内容=新的JSONObject(contentString);
message_id=content.getString(“message_id”);
from=content.getString(“from”);
}捕获(JSONException e){
e、 printStackTrace();
}
if(content.has(“消息类型”)){
logger.info(“不是来自
:: Spring Boot :: (v2.2.6.RELEASE)
2020-05-13 13:20:50.733 INFO 3700 --- [ main] c.p.t.phdProject.PhdProjectApplication :
Starting PhdProjectApplication on DESKTOP-HAHBAOS with PID 3700
(D:\MarsWorkSpace\phdProject\target\classes started by lenovo in D:\MarsWorkSpace\phdProject)
2020-05-13 13:20:50.736 INFO 3700 --- [ main] c.p.t.phdProject.PhdProjectApplication :
No active profile set, falling back to default profiles: default
2020-05-13 13:20:51.260 INFO 3700 --- [ main] faultConfiguringBeanFactoryPostProcessor :
No
bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel
will be created.
2020-05-13 13:20:51.268 INFO 3700 --- [ main] faultConfiguringBeanFactoryPostProcessor :
No bean named 'taskScheduler' has been explicitly defined. Therefore, a default
ThreadPoolTaskScheduler will be created.
2020-05-13 13:20:51.271 INFO 3700 --- [ main] faultConfiguringBeanFactoryPostProcessor :
No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default
DefaultHeaderChannelRegistry will be created.
2020-05-13 13:20:51.305 INFO 3700 --- [ main] trationDelegate$BeanPostProcessorChecker :
Bean 'org.springframework.integration.config.IntegrationManagementConfiguration' of type
[org.springframework.integration.config.IntegrationManagementConfiguration] is not eligible for
getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 13:20:51.316 INFO 3700 --- [ main] trationDelegate$BeanPostProcessorChecker :
Bean 'integrationChannelResolver' of type
[org.springframework.integration.support.channel.BeanFactoryChannelResolver] is not eligible for
getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 13:20:51.318 INFO 3700 --- [ main] trationDelegate$BeanPostProcessorChecker :
Bean 'integrationDisposableAutoCreatedBeans' of type
[org.springframework.integration.config.annotation.Disposables] is not eligible for getting
processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 13:20:51.381 INFO 3700 --- [ main] c.p.t.phdProject.Config.XmppConfig :
preparing TO FCM XMPP
2020-05-13 13:20:51.725 INFO 3700 --- [ main] c.p.t.phdProject.Config.XmppConfig :
establish XMPP connection
13:20:52 SENT (0): <stream:stream xmlns='jabber:client' to='fcm-xmpp.googleapis.com'
xmlns:stream='http://etherx.jabber.org/streams' version='1.0'
from='225392295170@gcm.googleapis.com@fcm-xmpp.googleapis.com' xml:lang='en'>
13:20:52 RECV (0): <stream:stream from="fcm-xmpp.googleapis.com" id="1682A44DC61D4116" version="1.0"
xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
13:20:52 RECV (0): <stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>X-OAUTH2</mechanism><mechanism>X-GOOGLE-TOKEN</mechanism><mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
13:20:52 SENT (0): <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>
ADIyNTM5MjI5NTE3MEBnY20uZ29vZ2xlYXBpcy5jb20AQUl6YVN5QzBuTjdvX0NaWnZFdkRtUkMzVGJHem5ZUVd
zTEFmSVNN</auth>
13:20:53 RECV (0): <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
13:20:53 SENT (0): <stream:stream xmlns='jabber:client' to='fcm-xmpp.googleapis.com'
xmlns:stream='http://etherx.jabber.org/streams' version='1.0'
from='225392295170@gcm.googleapis.com@fcm-xmpp.googleapis.com' id='1682A44DC61D4116' xml:lang='en'>
13:20:53 RECV (0): <stream:stream from="fcm-xmpp.googleapis.com" id="7467168502A88D0E" version="1.0"
xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
13:20:53 RECV (0): <stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session
xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
13:20:53 SENT (0): <iq id='o2A3D-3' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
</bind>
</iq>
13:20:53 RECV (0): <iq id="o2A3D-3" type="result"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
<jid>225392295170@gcm.googleapis.com/79295C1E</jid></bind></iq>
13:20:53 SENT (0): <iq id='o2A3D-5' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-
session'/>
</iq>
13:20:53 RECV (0):
13:20:53 RECV (0): <iq type="result" id="o2A3D-5"/>
13:20:53 User logged (0): 225392295170@gcm.googleapis.com:5235/79295C1E
13:20:53 SENT (0): <iq id='o2A3D-7' type='get'><query xmlns='jabber:iq:roster'></query></iq>
13:20:53 XMPPConnection authenticated (XMPPTCPConnection[225392295170@gcm.googleapis.com/79295C1E]
(0))
2020-05-13 13:20:53.720 INFO 3700 --- [ main] c.p.t.phdProject.Config.XmppConfig :
finish preparing TO FCM XMPP
firebase
2020-05-13 13:20:54.159 INFO 3700 --- [ main] o.s.s.c.ThreadPoolTaskScheduler :
Initializing ExecutorService 'taskScheduler'
2020-05-13 13:20:54.203 INFO 3700 --- [ main] o.s.i.endpoint.EventDrivenConsumer :
Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the
'errorChannel' channel
2020-05-13 13:20:54.204 INFO 3700 --- [ main] o.s.i.channel.PublishSubscribeChannel :
Channel 'application.errorChannel' has 1 subscriber(s).
2020-05-13 13:20:54.204 INFO 3700 --- [ main] o.s.i.endpoint.EventDrivenConsumer :
started bean '_org.springframework.integration.errorLogger'
2020-05-13 13:20:54.211 INFO 3700 --- [ main] c.p.t.phdProject.PhdProjectApplication :
Started PhdProjectApplication in 3.813 seconds (JVM running for 4.452)
2020-05-13 13:20:54.215 INFO 3700 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer :
Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to
the 'errorChannel' channel
2020-05-13 13:20:54.215 INFO 3700 --- [extShutdownHook] o.s.i.channel.PublishSubscribeChannel :
Channel 'application.errorChannel' has 0 subscriber(s).
2020-05-13 13:20:54.216 INFO 3700 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer :
stopped bean '_org.springframework.integration.errorLogger'
2020-05-13 13:20:54.216 INFO 3700 --- [extShutdownHook] o.s.s.c.ThreadPoolTaskScheduler :
Shutting down ExecutorService 'taskScheduler'
'