SpringBoot
SpringBoot使用Smack實現XMPP訊息推送
2021/11/05 16:59:41
0
1386
SpringBoot使用Smack實現XMPP訊息推送
一、前言
XMPP技術簡介
服務端元件Openfire
是基於即時訊息開放協定(XMPP),採用Java語言開發的即時協作伺服器。 Openfire安裝和使用都非常簡單,並利用Web進行管理。
Java開發庫Smack
開源,易於使用的XMPP用戶端類庫。
用戶端元件Spark
使用XMPP協議的IM軟體,可以通過Openfire進行文字通訊。
Smack可與不同的Java框架整合使用,本次利用SpringBoot框架實現訊息推送。
二、環境配置
範例環境
* Java 8
* Spring Boot 2.5.4.RELEASE
* Maven
三、實作步驟
1. 在pom.xml加入smack庫的相關依賴
<!--xmpp smack-->
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-core</artifactId>
<version>4.1.8</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-tcp</artifactId>
<version>4.1.8</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-java7</artifactId>
<version>4.1.8</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-extensions</artifactId>
<version>4.1.8</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-sasl-provided</artifactId>
<version>4.1.8</version>
</dependency>
2. 在application.properties加入Openfire伺服器網址(此次使用的是本機)
#openfire伺服器網址
openfire.server=127.0.0.1
3. 代碼實作
package com.example.demosmack;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.sasl.provided.SASLPlainMechanism;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.search.ReportedData;
import org.jivesoftware.smackx.search.UserSearchManager;
import org.jivesoftware.smackx.xdata.Form;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class SmackController {
@Value("${openfire.server}")
protected String openfireServer;
@RequestMapping("")
public Object index(String userName, String msg) {
return sendSmackMessage(userName, msg, false);
}
public boolean sendSmackMessage(String userName, String msg, boolean deliveryReceiptRequest) {
try {
if (StringUtils.isEmpty(userName)) {
return false;
}
XMPPTCPConnection con = getXmpptcpConnection();
con.connect();
if (con.isConnected()) {
SASLAuthentication.registerSASLMechanism(new SASLPlainMechanism());
con.loginAnonymously(); //匿名登錄
String serviceName = con.getServiceName();
UserSearchManager userSearchManager = new UserSearchManager(con);
Form searchForm = userSearchManager.getSearchForm("search." + serviceName);
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", userName);
ReportedData data = userSearchManager.getSearchResults(answerForm,
"search." + serviceName);
List<ReportedData.Row> list = data.getRows();
for (ReportedData.Row row : list) {
for (String jid : row.getValues("jid")) {
Message message = new Message();
message.setBody(msg); //發送的訊息
message.setTo(jid); //發送的目標
if(deliveryReceiptRequest){
message.setType(Message.Type.chat); //Type.chat:一對一聊天
}else{
message.setType(Message.Type.normal); //Type.normal:廣播
}
message.setSubject(msg);
con.sendStanza(message);
}
}
}
con.disconnect();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private XMPPTCPConnection getXmpptcpConnection() {
XMPPTCPConnectionConfiguration.Builder config=XMPPTCPConnectionConfiguration.builder();
config.setServiceName(openfireServer);
config.setHost(openfireServer);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
config.setSendPresence(true);
config.setCompressionEnabled(false);
XMPPTCPConnection con = new XMPPTCPConnection(config.build());
SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");
SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
SASLAuthentication.blacklistSASLMechanism("CRAM-MD5");
return con;
}
}
代碼解釋:
Controller的sendSmackMessage為推送訊息的方法,userName為對方ID,msg為傳送的訊息,deliveryReceiptRequest是否為離線訊息。
getXmpptcpConnection為連結XMPP的方法。
send方法裡使用的是匿名登錄的方式,也可以用帳號登入成為發送方。
因此發送的訊息都將以廣播的方式推送,離線時接收,在登入Spack後也會收到。
4. 測試
啟動專案後,在瀏覽器輸入http://localhost:8080/?userName=test&msg=Smack測試
(已知前提:test為openfire新增的使用者)
在Spack客戶端就可以接收到推送訊息。
四、結語
如專案中有推送訊息的需求,可以考慮XMPP服務作為選擇。
聊天、群組、添加好友等功能,Smack也一應俱全,更多的功能可以查看官方文件。
參考連結: