日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot2.x 整合websocket 消息推送,单独发送信息,群发信息

發布時間:2024/9/27 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot2.x 整合websocket 消息推送,单独发送信息,群发信息 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

根據公司需求在SpringBoot項目中集成站內信,于是,我做了一個SpringBoot2.x 整合websocket 消息推送,給指定用戶發送信息和群發信息即點點對方式和廣播方式2種模式。


文章目錄

  • 一、地址部署總覽
  • 二、實戰需求案例
  • 三、實戰準備
    • 3.1. pom依賴
    • 3.2. application.yml
    • 3.3. 配置類
    • 3.4. 實體類
    • 3.5. websocket 服務端
    • 3.6. 控制器
    • 3.7. SpringBoot入口類
  • 四、初始化頁面總覽
    • 4.1. 服務端
    • 4.2. 客戶端A
    • 4.3. 客戶端B
    • 4.4. 客戶端C
  • 五、案例實戰
    • 5.1. 客戶端A連接服務端
    • 5.2. 客戶端B連接服務端
    • 5.3. 客戶端C連接服務端
    • 5.4. 服務端連接狀態ABC
  • 六、單獨發送信息
    • 6.1. 服務端給指定客戶端A發送消息
    • 6.2. 驗證客戶端A消息是否收到
  • 七、群發信息
    • 7.1. 給在線客戶端群發消息
    • 7.2. 客戶端A 消息驗證
    • 7.2. 客戶端B 消息驗證
    • 7.3. 客戶端C 消息驗證

一、地址部署總覽

服務端地址http://localhost:8086/admin
客戶端地址http://localhost:8086/index

二、實戰需求案例

服務端實例1個
客戶端A實例1
客戶端B實例2
客戶端C實例3

三、實戰準備

3.1. pom依賴

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gblfy</groupId><artifactId>springboot-websocket</artifactId><version>v1.0.0</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.1.RELEASE</version></parent><properties><!--編碼同意設置--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!--JDK版本--><java.version>1.8</java.version></properties><dependencies><!--SpringMVC啟動器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--熱部署插件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><!--websocket啟動器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!--thymeleaf 模板引擎啟動器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></dependencies><build><plugins><!--maven 打包編譯插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build> </project>

3.2. application.yml

server:port: 80 spring:devtools:restart:exclude: static/**,public/**enabled: true

3.3. 配置類

package com.gblfy.websocket.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** 開啟websocket的支持** @Author gblfy* @Email gbly02@gmail.com* @Date 2019/11/20 PM 23:50*/ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }

3.4. 實體類

package com.gblfy.websocket.entity;import javax.websocket.Session; import java.io.Serializable;/*** @Author gblfy* @Email gbly02@gmail.com* @Date 2019/11/20 PM 23:50*/ public class Client implements Serializable {private static final long serialVersionUID = 8957107006902627635L;private String userName;private Session session;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public Session getSession() {return session;}public void setSession(Session session) {this.session = session;}public Client(String userName, Session session) {this.userName = userName;this.session = session;}public Client() {} }

3.5. websocket 服務端

package com.gblfy.websocket.server;import com.gblfy.websocket.entity.Client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors;/**** @Author gblfy* @Email gbly02@gmail.com* @Date 2019/11/20 PM 23:50*/ @ServerEndpoint(value = "/socketServer/{userName}") @Component public class SocketServer {private static final Logger logger = LoggerFactory.getLogger(SocketServer.class);/**** 用線程安全的CopyOnWriteArraySet來存放客戶端連接的信息*/private static CopyOnWriteArraySet<Client> socketServers = new CopyOnWriteArraySet<>();/**** websocket封裝的session,信息推送,就是通過它來信息推送*/private Session session;/**** 服務端的userName,因為用的是set,每個客戶端的username必須不一樣,否則會被覆蓋。* 要想完成ui界面聊天的功能,服務端也需要作為客戶端來接收后臺推送用戶發送的信息*/private final static String SYS_USERNAME = "niezhiliang9595";/**** 用戶連接時觸發,我們將其添加到* 保存客戶端連接信息的socketServers中** @param session* @param userName*/@OnOpenpublic void open(Session session,@PathParam(value="userName")String userName){this.session = session;socketServers.add(new Client(userName,session));logger.info("客戶端:【{}】連接成功",userName);}/**** 收到客戶端發送信息時觸發* 我們將其推送給客戶端(niezhiliang9595)* 其實也就是服務端本身,為了達到前端聊天效果才這么做的** @param message*/@OnMessagepublic void onMessage(String message){Client client = socketServers.stream().filter( cli -> cli.getSession() == session).collect(Collectors.toList()).get(0);sendMessage(client.getUserName()+"<--"+message,SYS_USERNAME);logger.info("客戶端:【{}】發送信息:{}",client.getUserName(),message);}/**** 連接關閉觸發,通過sessionId來移除* socketServers中客戶端連接信息*/@OnClosepublic void onClose(){socketServers.forEach(client ->{if (client.getSession().getId().equals(session.getId())) {logger.info("客戶端:【{}】斷開連接",client.getUserName());socketServers.remove(client);}});}/**** 發生錯誤時觸發* @param error*/@OnErrorpublic void onError(Throwable error) {socketServers.forEach(client ->{if (client.getSession().getId().equals(session.getId())) {socketServers.remove(client);logger.error("客戶端:【{}】發生異常",client.getUserName());error.printStackTrace();}});}/**** 信息發送的方法,通過客戶端的userName* 拿到其對應的session,調用信息推送的方法* @param message* @param userName*/public synchronized static void sendMessage(String message,String userName) {socketServers.forEach(client ->{if (userName.equals(client.getUserName())) {try {client.getSession().getBasicRemote().sendText(message);logger.info("服務端推送給客戶端 :【{}】",client.getUserName(),message);} catch (IOException e) {e.printStackTrace();}}});}/**** 獲取服務端當前客戶端的連接數量,* 因為服務端本身也作為客戶端接受信息,* 所以連接總數還要減去服務端* 本身的一個連接數** 這里運用三元運算符是因為客戶端第一次在加載的時候* 客戶端本身也沒有進行連接,-1 就會出現總數為-1的情況,* 這里主要就是為了避免出現連接數為-1的情況** @return*/public synchronized static int getOnlineNum(){return socketServers.stream().filter(client -> !client.getUserName().equals(SYS_USERNAME)).collect(Collectors.toList()).size();}/**** 獲取在線用戶名,前端界面需要用到* @return*/public synchronized static List<String> getOnlineUsers(){List<String> onlineUsers = socketServers.stream().filter(client -> !client.getUserName().equals(SYS_USERNAME)).map(client -> client.getUserName()).collect(Collectors.toList());return onlineUsers;}/**** 信息群發,我們要排除服務端自己不接收到推送信息* 所以我們在發送的時候將服務端排除掉* @param message*/public synchronized static void sendAll(String message) {//群發,不能發送給服務端自己socketServers.stream().filter(cli -> cli.getUserName() != SYS_USERNAME).forEach(client -> {try {client.getSession().getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}});logger.info("服務端推送給所有客戶端 :【{}】",message);}/**** 多個人發送給指定的幾個用戶* @param message* @param persons*/public synchronized static void SendMany(String message,String [] persons) {for (String userName : persons) {sendMessage(message,userName);}} }

3.6. 控制器

package com.gblfy.websocket.controller;import com.gblfy.websocket.server.SocketServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;import java.util.List;/*** websocket* 消息推送(個人和廣播)** @Author gblfy* @Email gbly02@gmail.com* @Date 2019/11/20 PM 23:50*/ @Controller public class WebSocketController {@Autowiredprivate SocketServer socketServer;/**** 客戶端頁面* @return*/@RequestMapping(value = "/index")public String idnex() {return "index";}/**** 服務端頁面* @param model* @return*/@RequestMapping(value = "/admin")public String admin(Model model) {int num = socketServer.getOnlineNum();List<String> list = socketServer.getOnlineUsers();model.addAttribute("num",num);model.addAttribute("users",list);return "admin";}/*** 個人信息推送* @return*/@RequestMapping("sendmsg")@ResponseBodypublic String sendmsg(String msg, String username){//第一個參數 :msg 發送的信息內容//第二個參數為用戶長連接傳的用戶人數String [] persons = username.split(",");SocketServer.SendMany(msg,persons);return "success";}/*** 推送給所有在線用戶* @return*/@RequestMapping("sendAll")@ResponseBodypublic String sendAll(String msg){SocketServer.sendAll(msg);return "success";} }

3.7. SpringBoot入口類

package com.gblfy.websocket;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;/*** SpringBoot 啟動器入口*/ @SpringBootApplication public class SpringBootWebSocketApplication {public static void main(String[] args) {SpringApplication.run(SpringBootWebSocketApplication.class,args);} }

四、初始化頁面總覽

4.1. 服務端

4.2. 客戶端A

4.3. 客戶端B

4.4. 客戶端C

五、案例實戰

5.1. 客戶端A連接服務端

5.2. 客戶端B連接服務端

5.3. 客戶端C連接服務端

5.4. 服務端連接狀態ABC

六、單獨發送信息

6.1. 服務端給指定客戶端A發送消息

6.2. 驗證客戶端A消息是否收到

七、群發信息

7.1. 給在線客戶端群發消息

7.2. 客戶端A 消息驗證

7.2. 客戶端B 消息驗證

7.3. 客戶端C 消息驗證


從以上圖中可以看出,測試符合預期。

項目源碼:https://github.com/gb-heima/springboot-websocket

zip包下載鏈接:
https://github.com/gb-heima/springboot-websocket/archive/master.zip

總結

以上是生活随笔為你收集整理的SpringBoot2.x 整合websocket 消息推送,单独发送信息,群发信息的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。