spring boot 集成socketIo 做消息推送
生活随笔
收集整理的這篇文章主要介紹了
spring boot 集成socketIo 做消息推送
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
spring boot 集成socketIo 做消息推送
- 項(xiàng)目需求
- 代碼展示
- 客戶端代碼
- 服務(wù)端代碼
項(xiàng)目需求
后臺(tái)管理系統(tǒng)用戶小鈴鐺,消息推送功能并展示有多少條消息或者小紅點(diǎn)
代碼展示
客戶端代碼
1.引入 socketIo.js<script src="/js/socket.io/socket.io.js"></script> 2. 自定義 socket.io 的請(qǐng)求處理<script src="/js/socket.io/socket-tools.js?t=<%=date.getTime()%>"></script>主要代碼 // 創(chuàng)建socket 在后端項(xiàng)目中配置的socket 的端口 var socket = io("http://localhost:9098");// 用于連接后端的服務(wù) /** 創(chuàng)建自定義事件 'news' 作用:接受服務(wù)端 socket.emit('news', 數(shù)據(jù)); 發(fā)出的數(shù)據(jù)*/socket.on('connect', function() {socket.emit('accept_send', JSON.stringify({//登錄用戶id和客戶機(jī)的ip 作為請(qǐng)求socekt.io 的一個(gè)表示sysUserId : sysUserId})); });socket.on('accept_response', function(data) {var obj = JSON.parse(data);// 輸出服務(wù)端響應(yīng)了數(shù)據(jù)if (obj.length > 99) {$("#sys_message_count").html("99+");} else {$("#sys_message_count").html(obj.length);}var html="";for (var i=0 ;i< obj.length && i<4;i++) {//小鈴鐺內(nèi)容設(shè)置html +="<li class=\"msg-list\">" +"<a οnclick=\"Detail(\'"+obj[i].id+"\',\'"+obj[i].type+"\')\" target=\"toolsAdmin\">"+"<p class=\"msg-title\">" +obj[i].title+"</p>"+"<p class=\"msg-content\">" +obj[i].content.substr(0,20)+"..."+"</p>"+"<p class=\"msg-time\">"+obj[i].createTimeTo+"</p></a></li>";}html+="";console.log(html);//刪除ui 內(nèi)容重新 然后重新添加$("#message_show").find("li").remove(); $("#message_show").append(html);});服務(wù)端代碼
服務(wù)端pom 主要是 netty-socketio
<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version><relativePath /> <!-- lookup parent from repository --></parent><groupId>org.example</groupId><artifactId>SOC_IM</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><!-- <scope>runtime</scope> --></dependency><!-- https://github.com/mrniko/netty-socketio --><dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>1.7.7</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.7</version></dependency></dependencies> </project>application.properties 文件 配置也是從別的地方拿的 沒有深究每一項(xiàng)的配置
server.port=8084spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://local:3306/xkb?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 # 搜索指定包別名 #mybatis.typeAliasesPackage=com.xkb.ctc # 配置mapper的掃描,找到所有的mapper.xml映射文件 #mybatis.mapperLocations=classpath*:mybatis/mapper/**/*Mapper.xml # 加載全局的配置文件 #mybatis.configLocation=classpath:mybatis/mapper/mybatis-config.xml#============================================================================ # netty socket io setting #============================================================================ # host在本地測(cè)試可以設(shè)置為localhost或者本機(jī)IP,在Linux服務(wù)器跑可換成服務(wù)器IP socketio.host=localhost socketio.port=9098 # 設(shè)置最大每幀處理數(shù)據(jù)的長(zhǎng)度,防止他人利用大數(shù)據(jù)來(lái)攻擊服務(wù)器 socketio.maxFramePayloadLength=1048576 # 設(shè)置http交互最大內(nèi)容長(zhǎng)度 socketio.maxHttpContentLength=1048576 # socket連接數(shù)大小(如只監(jiān)聽一個(gè)端口boss線程組為1即可) socketio.bossCount=1 socketio.workCount=100 socketio.allowCustomRequests=true # 協(xié)議升級(jí)超時(shí)時(shí)間(毫秒),默認(rèn)10秒。HTTP握手升級(jí)為ws協(xié)議超時(shí)時(shí)間 socketio.upgradeTimeout=1000000 # Ping消息超時(shí)時(shí)間(毫秒),默認(rèn)60秒,這個(gè)時(shí)間間隔內(nèi)沒有接收到心跳消息就會(huì)發(fā)送超時(shí)事件 socketio.pingTimeout=6000000 # Ping消息間隔(毫秒),默認(rèn)25秒。客戶端向服務(wù)器發(fā)送一條心跳消息間隔 socketio.pingInterval=25000 Application.java @SpringBootApplication @EnableAutoConfiguration public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}} import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /*** 存放前端鏈接用戶ip 與sysUserId* 原版本只保存了客戶端連接的ip 會(huì)導(dǎo)致推送 錯(cuò)誤,需要綁定到對(duì)應(yīng)的用戶* @author K**/ public class UserInfoMapUtil {public static ConcurrentMap<String, Object> webUserInfoMap = new ConcurrentHashMap<>();public static void put(String key,Object object) {webUserInfoMap.put(key, object);}public static Object get(String key) {return webUserInfoMap.get(key);}public static void remove(String key) {webUserInfoMap.remove(key);}public static Collection<Object> getValues(){return webUserInfoMap.values();}public static ConcurrentMap<String, Object> getWebUserInfoMap(){return webUserInfoMap;} } import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component;import com.corundumstudio.socketio.SocketIOServer; /*** 服務(wù)啟動(dòng)執(zhí)行,SpringBoot啟動(dòng)之后執(zhí)行* @author K**/ @Primary @Component public class ServerRunner implements CommandLineRunner{private final Logger log = LoggerFactory.getLogger(getClass());@Autowiredprivate SocketIOServer socketIOServer;@Overridepublic void run(String... args) throws Exception{socketIOServer.start();log.info("socket.io啟動(dòng)成功!");}} import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import com.corundumstudio.socketio.SocketConfig; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;@Configuration public class SocketIOConfig {@Value("${socketio.host}")private String host;@Value("${socketio.port}")private Integer port;@Value("${socketio.bossCount}")private int bossCount;@Value("${socketio.workCount}")private int workCount;@Value("${socketio.allowCustomRequests}")private boolean allowCustomRequests;@Value("${socketio.upgradeTimeout}")private int upgradeTimeout;@Value("${socketio.pingTimeout}")private int pingTimeout;@Value("${socketio.pingInterval}")private int pingInterval;/*** 以下配置在上面的application.properties中已經(jīng)注明* @return*/@Beanpublic SocketIOServer socketIOServer(){SocketConfig socketConfig = new SocketConfig();socketConfig.setTcpNoDelay(true);socketConfig.setSoLinger(0);com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();config.setSocketConfig(socketConfig);config.setHostname(host);config.setPort(port);socketConfig.setReuseAddress(true);//添加配置config.setBossThreads(bossCount);config.setWorkerThreads(workCount);config.setAllowCustomRequests(allowCustomRequests);config.setUpgradeTimeout(upgradeTimeout);config.setPingTimeout(pingTimeout);config.setPingInterval(pingInterval);return new SocketIOServer(config);}@Beanpublic SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {return new SpringAnnotationScanner(socketServer);} } package com.soc.im.service;import com.alibaba.fastjson.JSONObject; import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnEvent; import com.soc.im.utils.UserInfoMapUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Component;import java.util.Map; import java.util.concurrent.ConcurrentHashMap;@Component @EnableScheduling // 開啟定時(shí)任務(wù) public class SocketIoServer {private static final Logger log= LoggerFactory.getLogger(SocketIoServer.class);private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();@OnConnectpublic void onConnect(SocketIOClient client) {String address = client.getSessionId().toString();log.info(address + "-------------------------" + "客戶端已連接");clientMap.put(address, client);UserInfoMapUtil.put(address,client);}@OnDisconnectpublic void onDisconnect(SocketIOClient client) {String address = client.getSessionId().toString();log.info(address + "-------------------------" + "客戶端已斷開連接");clientMap.remove(address);UserInfoMapUtil.remove(address);}@OnEvent(value = "accept_send")public void onEvent(SocketIOClient client, AckRequest ackRequest, String data) {/**1.客戶端推送advert_info事件時(shí),onData接受數(shù)據(jù),2.這里是string類型的json數(shù)據(jù),還可以為Byte[],object其他類型3.獲取客戶端連接的ip4. sysUserId與 前端頁(yè)面socket.io 請(qǐng)求 傳參屬性名稱一致*/String address = client.getSessionId().toString();log.info("address:{}",address);log.info(address + ":客戶端:************" + data);JSONObject gpsData = (JSONObject) JSONObject.parse(data);String sysUserId = gpsData.get("sysUserId") + "";UserInfoMapUtil.put(address, sysUserId);clientMap.put(address, client); // 這里處理相關(guān)業(yè)務(wù)然后返回 String message 給前端log.info("返回客戶端IP:" + address+"ID: "+sysUserId+"message: ");client.sendEvent("accept_response", "message");}/**1.獲取全部客戶端2.獲取客戶端連接的ip定時(shí)更新小鈴鐺信息*/@Scheduled(cron = "0 0/30 * * * ?")public void pushMessageAllClients() {logger.info("開始-------->pushMessageAllClients...{}",System.currentTimeMillis());clientMap.forEach((address, client)->{Object object = UserInfoMapUtil.get(address);logger.info("用戶信息...{}",String.valueOf(object));String message = sysMessage(String.valueOf(object));client.sendEvent("accept_response", message);logger.info("sendEvent:{}",client);});}public static Map<String, SocketIOClient> getClientMap() {return clientMap;}public static void setClientMap(Map<String, SocketIOClient> clientMap) {SocketIoServer.clientMap = clientMap;}}總結(jié)
以上是生活随笔為你收集整理的spring boot 集成socketIo 做消息推送的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TreeSize Free (硬盘空间显
- 下一篇: 揭秘Gamefi今年火爆的5大原因