SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能
WebSocket簡(jiǎn)介
WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動(dòng)發(fā)送信息給客戶端。
SpringBoot整合WebSocket的相關(guān)依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
WebSokcet工具類記錄當(dāng)前的在線連接對(duì)鏈接進(jìn)行操作
public class WebsocketUtil { /** * 記錄當(dāng)前在線的Session */ private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>(); /** * 添加session * @param userId * @param session */ public static void addSession(String userId, Session session){ // 此處只允許一個(gè)用戶的session鏈接。一個(gè)用戶的多個(gè)連接,我們視為無(wú)效。 ONLINE_SESSION.putIfAbsent ( userId, session ); } /** * 關(guān)閉session * @param userId */ public static void removeSession(String userId){ ONLINE_SESSION.remove ( userId ); } /** * 給單個(gè)用戶推送消息 * @param session * @param message */ public static void sendMessage(Session session, String message){ if(session == null){ return; } // 同步 RemoteEndpoint.Async async = session.getAsyncRemote (); async.sendText ( message ); } /** * 向所有在線人發(fā)送消息 * @param message */ public static void sendMessageForAll(String message) { //jdk8 新方法 ONLINE_SESSION.forEach((sessionId, session) -> sendMessage(session, message)); } }
WebSocket接口處理類
/** * websocket接口處理類 */ @Component @ServerEndpoint(value = "/chat/{userId}") public class WebsocketController { /** * 連接事件,加入注解 * @param userId * @param session */ @OnOpen public void onOpen(@PathParam(value = "userId") String userId, Session session) { String message = "[" + userId + "]加入聊天室!!"; // 添加到session的映射關(guān)系中 WebsocketUtil.addSession(userId, session); // 廣播通知,某用戶上線了 // WebsocketUtil.sendMessageForAll(message); } /** * 連接事件,加入注解 * 用戶斷開鏈接 * * @param userId * @param session */ @OnClose public void onClose(@PathParam(value = "userId") String userId, Session session) { String message = "[" + userId + "]退出了聊天室..."; // 刪除映射關(guān)系 WebsocketUtil.removeSession(userId); // 廣播通知,用戶下線了 WebsocketUtil.sendMessageForAll(message); } /** * 當(dāng)接收到用戶上傳的消息 * * @param userId * @param session */ @OnMessage public void onMessage(@PathParam(value = "userId") String userId, Session session, String message) { String msg = "[" + userId + "]:" + message; System.out.println("接收到信息:" + msg); // 直接廣播 WebsocketUtil.sendMessageForAll(msg); } /** * 處理用戶活連接異常 * * @param session * @param throwable */ @OnError public void onError(Session session, Throwable throwable) { try { session.close(); } catch (IOException e) { e.printStackTrace(); } throwable.printStackTrace(); } }
服務(wù)器端單個(gè)用戶推送消息
@PostMapping("/send") public void send(@RequestParam("id") String id,@RequestParam("message")String message) { Session session = ONLINE_SESSION.get(id); WebsocketUtil.sendMessage(session,message); System.out.println("發(fā)送成功"); }
使用Apifox進(jìn)行測(cè)試
添加連接服務(wù)端的WebSocket接口
連接成功:
服務(wù)端推送消息
客戶端收到的消息
WebSocket工具類里面有群發(fā)的方法,大家想用可以直接調(diào)用,這里就不進(jìn)行演示了
問(wèn)題一:如何在上面WebSocket接口處理類中注入其他的Bean?
我也是在一次工作中遇到這樣的問(wèn)題,今天正好和大家講一下如何解決
查閱資料才知道WebSocket接口處理類使用@ServerEndPoint注解表明他是一個(gè)WebSocket端點(diǎn),因此Spring不會(huì)將其納入Spring容器的管理范圍,WebSocket的生命周期和Spring Bean 的生命周期并不一致,所以通過(guò)@Autowired 注解注入得到的都是空的Bean 無(wú)法使用
我們自定義一個(gè)工具類手動(dòng)獲取Bean在 WebSocket接口處理類中使用:
/** *AppUtils類 * * @author qiancj * @since 2020-06-30 13:02 */ @Component("appUtils") public class AppUtils { /** * 應(yīng)用上下文 */ private static ApplicationContext context; @Resource public void setApplicationContext(ApplicationContext c) { context = c; } /** * 獲取配置參數(shù) * * @param property 配置參數(shù)名 * @return 配置參數(shù)值 */ public static String getProperty(String property) { return context.getEnvironment().getProperty(property); } /** * 獲取bean對(duì)象 * * @param requiredType Class * @param <T> T * @return bean對(duì)象 */ public static <T> T getBean(Class<T> requiredType) { return context.getBean(requiredType); } /** * 獲取bean對(duì)象 * * @param name bean name * @param requiredType Class * @param <T> T * @return bean對(duì)象 */ public static <T> T getBean(String name, Class<T> requiredType) { return context.getBean(requiredType); } }
使用:
MessageService messageService = AppUtils.getBean(MessageService.class);
然后我們就可以使用messageService調(diào)用Service層相關(guān)的方法了。
問(wèn)題解決。
以上就是SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot WebSocket推送消息的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息的示例
- SpringBoot2.0集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息
- Spring?Boot?使用?SSE?方式向前端推送數(shù)據(jù)詳解
- SpringBoot整合WebSocket實(shí)現(xiàn)后端向前端主動(dòng)推送消息方式
- SpringBoot集成WebSocket實(shí)現(xiàn)后臺(tái)向前端推送信息
- SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例
- 利用Netty+SpringBoot實(shí)現(xiàn)定時(shí)后端向前端推送數(shù)據(jù)
相關(guān)文章
Java編程中利用InetAddress類確定特殊IP地址的方法
這篇文章主要介紹了Java編程中利用InetAddress類確定特殊IP地址的方法,InetAddress類是Java網(wǎng)絡(luò)編程中一個(gè)相當(dāng)實(shí)用的類,需要的朋友可以參考下2015-11-11Java實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07Idea如何配置Maven才能優(yōu)先從本地倉(cāng)庫(kù)獲取依賴(親測(cè)方法有效)
對(duì)于Idea怎么配置Maven才能優(yōu)先從本地倉(cāng)庫(kù)獲取依賴,網(wǎng)上說(shuō)法有很多種,都不太靠譜,最終都沒(méi)有效果,最好的解決方法是通過(guò)修改maven配置文件settings.xml,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10Gson中@JsonAdater注解的幾種方式總結(jié)
這篇文章主要介紹了Gson中@JsonAdater注解的幾種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08SpringBoot中集成screw(螺絲釘)實(shí)現(xiàn)數(shù)據(jù)庫(kù)表結(jié)構(gòu)文檔生成方法
這篇文章主要介紹了SpringBoot中集成screw(螺絲釘)實(shí)現(xiàn)數(shù)據(jù)庫(kù)表結(jié)構(gòu)文檔生成,下面以連接mysql數(shù)據(jù)庫(kù)并生成html格式的數(shù)據(jù)庫(kù)結(jié)構(gòu)文檔為例,插件的使用方式除可以使用代碼外,還可以使用Maven插件的方式,需要的朋友可以參考下2024-07-07JAVA SpringBoot jar程序 Systemctl生產(chǎn)環(huán)境部署方案
這篇文章主要介紹了JAVA SpringBoot jar程序 Systemctl生產(chǎn)環(huán)境部署方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03