當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
SpringBoot2.x 整合websocket 消息推送,单独发送信息,群发信息
生活随笔
收集整理的這篇文章主要介紹了
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/index |
二、實戰需求案例
| 客戶端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: true3.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 消息推送,单独发送信息,群发信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第9篇:Flowable-Modeler
- 下一篇: SpringMVC项目 使用IDEA快速