WebSocket的代碼編寫會根據(jù)業(yè)務(wù)邏輯而進(jìn)行變化,需要去理解編寫思路,這樣才能在工作中使用得游刃有余。
1. 引入依賴
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.? 編寫WebSocketConfig配置類
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter getServerEndpointExporter() {
return new ServerEndpointExporter();
}
}
3. 編寫WebSocket服務(wù)類文章來源:http://www.zghlxwxcb.cn/news/detail-508119.html
下面的服務(wù)類中,可以編寫多個sendMeg方法(寫法比較多樣化),作用是發(fā)送消息回前端,使用方式就是你在自己的業(yè)務(wù)代碼中自行調(diào)用,例(serviceImpl中調(diào)用):文章來源地址http://www.zghlxwxcb.cn/news/detail-508119.html
WebSocketServer.sendCountToUaa(ownerId, unreadNewsCount);
import com.sms.service.InternalNewsService;
import com.sms.service.impl.InternalNewsServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Websocket服務(wù),推送信息
*/
@Slf4j
@Component
@ServerEndpoint("/webSocket/sms")
public class WebSocketServer {
/**
* 定義集合,用于存儲連接信息
* 根據(jù)業(yè)務(wù)需求自定義,數(shù)據(jù)格式可隨意變化
*/
//瀏覽器端連接,這種數(shù)據(jù)格式是因為考慮到同一個用戶賬號可以在不同的瀏覽器登錄,所以一個用戶需要保存多個連接
private static final ConcurrentHashMap<String, ArrayList<Session>> sessionMap = new ConcurrentHashMap<>();
//微信端連接
private static final List<Session> wxSessionList = new ArrayList<>();
/**
* 作用:
* 這里使用@Autowared是無法正常注入對象的,需要注入外部對象就需要使用這種方式
* 需在啟動類也就是main方法中加入:WebSocketServer.setApplicationContext(context);
* context參數(shù)是啟動類中run方法的返回值
* 使用:
* 在需要對象的地方使用
* 例:
* UserServiceImpl userServiceImpl = applicationContext.getBean(UserService.class);
*/
private static ApplicationContext applicationContext;
public static void setApplicationContext(ApplicationContext applicationContext) {
WebSocketServer.applicationContext = applicationContext;
}
/**
* 前端關(guān)閉頁面或者主動關(guān)閉websocket鏈接,都會執(zhí)行@OnClose
*/
@OnClose
public void close(Session session) {
if (null == session) {
return;
}
/**
* 以下代碼都是根據(jù)業(yè)務(wù)邏輯編寫,寫法并不固定
*/
//關(guān)閉微信端中的session
ListIterator<Session> sessionListIterator = wxSessionList.listIterator();
while (sessionListIterator.hasNext()) {
Session next = sessionListIterator.next();
if (session == next) {
sessionListIterator.remove();
return;
}
}
//關(guān)閉瀏覽器端中的session
Iterator<Map.Entry<String, ArrayList<Session>>> iterator = sessionMap.entrySet().iterator();
while (iterator.hasNext()) {
ArrayList<Session> values = iterator.next().getValue();
if (null == values || 1 > values.size()) {
continue;
}
for (int i = 0; i < values.size(); i++) {
Session sess = values.get(i);
if (null == sess) {
continue;
}
if (session == sess) {
values.remove(i--);
return;
}
}
}
}
/**
* 前端連接后端socket時執(zhí)行@OnMessage,前后端建立起連接,后端保存連接
*/
@OnMessage
public void onMessage(String userId, Session session) {
if (StringUtils.isEmpty(userId) || null == session) {
return;
}
if ("ykj".equals(userId)) {
//微信端消息標(biāo)識,自定義,沒有微信端可直接將這個if刪掉
wxSessionList.add(session);
} else {
//接收到消息后,找到對應(yīng)的session
ArrayList<Session> sessions = sessionMap.get(userId);
if (null == sessions) {
sessions = new ArrayList<>();
} else {
//遍歷,看該session是否存在,如果存在代表是在心跳檢測操作
for (int i = 0; i < sessions.size(); i++) {
if (sessions.get(i) == session) {
try {
//發(fā)送消息回前端
session.getAsyncRemote().sendText("{\"heartbeat\":\"socket心跳檢測成功!??!\"}");
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//說明session不存在,添加到列表
sessions.add(session);
sessionMap.put(userId, sessions);
//查詢當(dāng)前用戶未讀消息條數(shù)(業(yè)務(wù)代碼,查詢數(shù)據(jù)庫)
InternalNewsService internalNewsService = applicationContext.getBean(InternalNewsService.class);
Integer newsCount = internalNewsService.selectUnreadNewsCount(userId, 0, 4);
if (newsCount == null) {
session.getAsyncRemote().sendText("0");//發(fā)送消息回前端
} else {
session.getAsyncRemote().sendText(newsCount.toString());//發(fā)送消息回前端
}
return;
}
try {
session.getAsyncRemote().sendText("200");//發(fā)送消息回前端
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 發(fā)送數(shù)據(jù)到前端
*
* @param msg
*/
public static void sendMsg(String userIds, String msg) {
if (StringUtils.isEmpty(userIds) || StringUtils.isEmpty(msg)) {
return;
}
String[] user_id = userIds.split(",");
int uis = user_id.length;
if (1 > uis) {
return;
}
for (int ii = 0; ii < uis; ii++) {
String userId = user_id[ii];
if (StringUtils.isEmpty(userId)) {
continue;
}
ArrayList<Session> sessions = sessionMap.get(userId);
if (null == sessions || 1 > sessions.size()) {
continue;
}
Iterator<Session> iterator = sessions.iterator();
while (iterator.hasNext()) {
Session next = iterator.next();
if (null == next || !next.isOpen()) {
continue;
}
try {
next.getBasicRemote().sendText(msg);
//System.out.println("推送給socket:" + next);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 發(fā)送數(shù)據(jù)到前端uaa端
*/
public static void sendCountToUaa(String userId, Integer count) {
if (StringUtils.isEmpty(userId)) {
return;
}
ArrayList<Session> sessions = sessionMap.get(userId);
if (null == sessions || 1 > sessions.size()) {
return;
}
Iterator<Session> iterator = sessions.iterator();
while (iterator.hasNext()) {
Session next = iterator.next();
if (null == next || !next.isOpen()) {
continue;
}
try {
//next.getBasicRemote().sendText(count.toString());
next.getAsyncRemote().sendText(count.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 給微信端用戶推送消息
*
* @param msg
*/
public static void sendToVXMsg(String msg) {
ListIterator<Session> sessionListIterator = wxSessionList.listIterator();
while (sessionListIterator.hasNext()) {
Session session = sessionListIterator.next();
try {
session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
到了這里,關(guān)于WebSocket實現(xiàn)前后端消息推送的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!