springboot整合websocket
點擊上方藍色字體,選擇“標星公眾號”
優(yōu)質(zhì)文章,第一時間送達
一、永恒第一步:導入pom依賴
???org.springframework.boot
???spring-boot-starter-websocket
???org.webjars
???stomp-websocket
???2.3.3
二、添加配置文件
對應部分的說明都寫在了注釋里面
package?com.easy.config;
import?com.mbyte.easy.webscoket.consts.GlobalConsts;
import?org.springframework.cache.annotation.EnableCaching;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.messaging.simp.config.MessageBrokerRegistry;
import?org.springframework.web.bind.annotation.CrossOrigin;
import?org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import?org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import?org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
?*?@Author?zte
?*?@Description?Webscoket配置類
?*?@Date?21:33?2019/5/6
?**/
@Configuration
@EnableWebSocketMessageBroker
@EnableCaching
@CrossOrigin("*")
public?class?WebSocketStompConfig?implements?WebSocketMessageBrokerConfigurer?{
????@Override
????public?void?configureMessageBroker(MessageBrokerRegistry?config)?{
????????/**
?????????*?配置消息代理
?????????*?啟動簡單Broker,消息的發(fā)送的地址符合配置的前綴來的消息才發(fā)送到這個broker
?????????*/
????????config.enableSimpleBroker(GlobalConsts.TOPICPATH,?GlobalConsts.P2PPUSHBASEPATH);
????????config.setUserDestinationPrefix(GlobalConsts.P2PPUSHBASEPATH);
????????config.setApplicationDestinationPrefixes(GlobalConsts.APP_PREFIX);
????}
????@Override
????public?void?registerStompEndpoints(StompEndpointRegistry?registry)?{
????????/**
?????????*?注冊?Stomp的端點
?????????*?addEndpoint:添加STOMP協(xié)議的端點。這個HTTP?URL是供WebSocket或SockJS客戶端訪問的地址
?????????*?setAllowedOrigins("*")?允許跨域
?????????*?withSockJS:指定端點使用SockJS協(xié)議
?????????*/
????????registry.addEndpoint(GlobalConsts.ENDPOINT)
????????????????.setAllowedOrigins("*")
????????????????.withSockJS();
????}
}
如果需要跨域,則需要添加跨域設置
package?com.easy.config;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.web.socket.config.annotation.EnableWebSocket;
import?org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import?org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import?javax.annotation.Resource;
/**
?*?@className:?WebSocketConfig
?*?@description:
?*?@author:?zte
?*?@create:?2020-06-09?16:17
?**/
@Configuration
@EnableWebSocket
public?class?WebSocketConfig?implements?WebSocketConfigurer?{
????@Resource
????private?MyHandShakeInterceptor?handshake;
????@Resource
????private?MyHandler?handler;
????/**
?????*?實現(xiàn)?WebSocketConfigurer?接口,重寫?registerWebSocketHandlers?方法,這是一個核心實現(xiàn)方法,配置?websocket?入口,允許訪問的域、注冊?Handler、SockJs?支持和攔截器。
?????*?
?????*?registry.addHandler()注冊和路由的功能,當客戶端發(fā)起?websocket?連接,把?/path?交給對應的?handler?處理,而不實現(xiàn)具體的業(yè)務邏輯,可以理解為收集和任務分發(fā)中心。
?????*?
?????*?addInterceptors,顧名思義就是為?handler?添加攔截器,可以在調(diào)用?handler?前后加入我們自己的邏輯代碼。
?????*?
?????*?setAllowedOrigins(String[]?domains),允許指定的域名或?IP?(含端口號)建立長連接,如果只允許自家域名訪問,這里輕松設置。如果不限時使用”*”號,如果指定了域名,則必須要以?http?或?https?開頭。
?????*
?????*/
????@Override
????public?void?registerWebSocketHandlers(WebSocketHandlerRegistry?registry)?{
????????//部分?支持websocket?的訪問鏈接,允許跨域
????????registry.addHandler(handler,?"/websocket").addInterceptors(handshake).setAllowedOrigins("*");
????????//部分?不支持websocket的訪問鏈接,允許跨域
//????????registry.addHandler(handler,?"/sockjs/echo").addInterceptors(handshake).setAllowedOrigins("*").withSockJS();
????}
}
三、WebScoket常量配置
package?com.easy.webscoket.consts;
/**
?*?@program:?easy
?*?@description:?WebScoket常量配置
?*?@author:?zte
?*?@create:?2019-05-06?10:11
?**/
public?class?GlobalConsts?{
????public?static?final?String?TOPIC?=?"/topic/greetings";
????public?static?final?String?ENDPOINT?=?"/gs-guide-websocket";
????public?static?final?String?APP_PREFIX?=?"/app";
????public?static?final?String?HELLO_MAPPING?=?"/hello";
????//點對點消息推送地址前綴
????public?static?final?String?P2PPUSHBASEPATH?=?"/user";
????//點對點消息推送地址后綴,最后的地址為/user/用戶識別碼/msg
????public?static?final?String?P2PPUSHPATH?=?"/msg";
????/**
?????*?@Description?接收消息地址
?????**/
????public?static?final?String?RECEIVE_MAPPING?=?"/receive";
????/**
?????*?@Description?訂閱消息推送地址前綴
?????**/
????public?static?final?String?TOPICPATH?=?"/group";
????/**
?????*?統(tǒng)一前綴
?????*/
????public?static?final?String?URL_PREFIX?=?"/rest/";
}
四、controller層代碼
這里包含了點對點聊天以及群聊的配置
package?com.easy.webscoket.controller;
import?com.alibaba.fastjson.JSON;
import?com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import?com.mbyte.easy.common.web.AjaxResult;
import?com.mbyte.easy.detailed_info_log.entity.DetailedInfoLog;
import?com.mbyte.easy.talk_socket.entity.Message;
import?com.mbyte.easy.talk_socket.service.IMessageService;
import?com.mbyte.easy.webscoket.consts.GlobalConsts;
import?com.mbyte.easy.webscoket.vo.ClientMessage;
import?com.mbyte.easy.webscoket.vo.ServerMessage;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.messaging.handler.annotation.MessageMapping;
import?org.springframework.messaging.handler.annotation.SendTo;
import?org.springframework.messaging.simp.SimpMessagingTemplate;
import?org.springframework.stereotype.Controller;
import?org.springframework.ui.Model;
import?org.springframework.web.bind.annotation.GetMapping;
import?org.springframework.web.bind.annotation.RequestMapping;
import?org.springframework.web.util.HtmlUtils;
import?javax.websocket.OnOpen;
import?javax.websocket.Session;
import?javax.websocket.server.PathParam;
import?java.awt.event.MouseWheelEvent;
import?java.util.List;
import?java.util.Map;
import?java.util.concurrent.ConcurrentHashMap;
/**
?*?@program:?easy
?*?@description:?webscoket測試controller
?*?@author:?zte
?*?@create:?2019-05-06?10:26
?**/
@Controller
@RequestMapping("/audience/index")
public?class?GreetingController?{
????@Autowired
????private?SimpMessagingTemplate?template;
????@Autowired
????private?IMessageService?messageService;
????/**
?????*?在線用戶的Map集合,key:用戶名,value:Session對象
?????*/
????private?static?Map?sessionMap?=?new?ConcurrentHashMap<>();
????/**
?????*?連接建立成功調(diào)用的方法
?????*/
????@OnOpen
????public?void?onOpen(Session?session,?@PathParam("username")?String?username)?{
????????//在webSocketMap新增上線用戶
????????sessionMap.put(username,?session);
????????System.out.println(username);
????}
????@RequestMapping
????public?String?index(Model?model)?{
????????return?"webscoket/greeting";
????}
????@RequestMapping("/index2")
????public?String?index2(Model?model)?{
????????return?"webscoket/greeting2";
????}
????@MessageMapping(GlobalConsts.HELLO_MAPPING)
????@SendTo(GlobalConsts.TOPIC)
????public?ServerMessage?greeting(ClientMessage?message)?throws?Exception?{
????????//?模擬延時,以便測試客戶端是否在異步工作
//????????Thread.sleep(1000);
????????template.convertAndSendToUser(message.getId()?+?"",?GlobalConsts.P2PPUSHPATH,?JSON.toJSON(new?ServerMessage("Hello,?"?+?HtmlUtils.htmlEscape(message.getName())?+?"!")));
????????return?new?ServerMessage("Hello,?"?+?HtmlUtils.htmlEscape(message.getName())?+?"!");
????}
????/**
?????*?群聊
?????*
?????*?@param?message?WebMessage
?????*/
????@MessageMapping("/group")
????public?void?group(Message?message)?{
????????messageService.save(message);
????????template.convertAndSend("/group/"??+?message.getGroupPrefix(),?JSON.toJSON(message));
????}
????@GetMapping("/groupGetMessage")
????public?AjaxResult?groupGetMessage(String?groupPrefix,Integer?groupFlag)?{
????????List?messages?=?messageService.list(new?LambdaQueryWrapper().eq(Message::getGroupPrefix,groupPrefix).eq(Message::getGroupFlag,groupFlag).orderByDesc(Message::getSendTime));
????????return?AjaxResult.success(messages);
????}
}
獲取群聊消息(歷史消息)的接口
package?com.mbyte.easy.rest.message;
import?com.alibaba.fastjson.JSON;
import?com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import?com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import?com.baomidou.mybatisplus.core.metadata.IPage;
import?com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import?com.mbyte.easy.talk_socket.entity.Message;
import?com.mbyte.easy.talk_socket.service.IMessageService;
import?com.mbyte.easy.common.controller.BaseController;
import?com.mbyte.easy.common.web.AjaxResult;
import?com.mbyte.easy.util.PageInfo;
import?io.swagger.annotations.Api;
import?io.swagger.annotations.ApiImplicitParam;
import?io.swagger.annotations.ApiImplicitParams;
import?io.swagger.annotations.ApiOperation;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.messaging.handler.annotation.MessageMapping;
import?org.springframework.messaging.simp.SimpMessagingTemplate;
import?org.springframework.web.bind.annotation.RequestMethod;
import?org.springframework.web.bind.annotation.RestController;
import?org.springframework.ui.Model;
import?org.springframework.web.bind.annotation.*;
import?java.util.List;
import?java.time.LocalDate;
import?java.time.LocalDateTime;
import?java.util.HashMap;
import?java.util.Map;
/**
*?
*?前端控制器
*?
*?@author?zte
*?@since?2019-03-11
*/
@Api(tags?=?"討論聊天記錄接口")
@RestController
@RequestMapping("rest/message")
public?class?RestMessageController?extends?BaseController??{
????@Autowired
????private?IMessageService?messageService;
????/**
?????*?存儲聊天數(shù)據(jù)頁面
?????*?@return
?????*/
????@ApiOperation(value?=?"聊天記錄添加接口")
????@ApiImplicitParams({
????????????@ApiImplicitParam(name?=?"userId",?value?=?"發(fā)送人",?required?=?true),
????????????@ApiImplicitParam(name?=?"content",?value?=?"聊天內(nèi)容",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupPrefix",?value?=?"房間號",?required?=?true),
????????????@ApiImplicitParam(name?=?"msgType",?value?=?"消息類型",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupFlag",?value?=?"房間類型",?required?=?true),
????})
????@GetMapping("addSocketBefore")
????public?AjaxResult?addSocketBefore(String?userId,String?content,String?groupPrefix,Integer?msgType,Integer?groupFlag){
????????Message?message?=?new?Message();
????????message.setFromUser(userId);
????????message.setContent(content);
????????message.setGroupPrefix(groupPrefix);
????????message.setGroupFlag(groupFlag);
????????message.setMsgType(msgType);
????????return?toAjax(messageService.save(message));
????}
????@ApiOperation(value?=?"聊天歷史記錄獲取接口")
????@ApiImplicitParams({
????????????@ApiImplicitParam(name?=?"groupPrefix",?value?=?"房間號",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupFlag",?value?=?"房間類型",?required?=?true),
????})
????@GetMapping("/groupGetMessage")
????public?AjaxResult?groupGetMessage(String?groupPrefix,Integer?groupFlag)?{
????????List?messages?=?messageService.list(new?LambdaQueryWrapper().eq(Message::getGroupPrefix,groupPrefix).eq(Message::getGroupFlag,groupFlag).orderByAsc(Message::getSendTime));
????????return?AjaxResult.success(messages);
????}
五、定義實體類
package?com.easy.talk_socket.entity;
import?com.baomidou.mybatisplus.annotation.TableName;
import?com.mbyte.easy.common.entity.BaseEntity;
import?java.time.LocalDateTime;
import?lombok.Data;
import?lombok.EqualsAndHashCode;
import?lombok.experimental.Accessors;
/**
?*?
?*?
?*?
?*
?*?@author?zte
?*?@since?2020-08-28
?*/
@Data
@EqualsAndHashCode(callSuper?=?true)
@Accessors(chain?=?true)
@TableName("t_message")
public?class?Message?extends?BaseEntity?{
????private?static?final?long?serialVersionUID?=?1L;
????/**
?????*?發(fā)送人
?????*/
????private?String?fromUser;
????/**
?????*?接收人
?????*/
????private?String?toUser;
????/**
?????*?消息內(nèi)容
?????*/
????private?String?content;
????/**
?????*?消息類型:1?文字??;2語音;?3圖片;?4?視頻?5?禮物?6邀請入隊?默認為1
?????*/
????private?Integer?msgType;
????/**
?????*?是否已讀,?0:未讀,?1:已讀
?????*/
????private?Integer?readFlag;
????/**
?????*??正常為?0??刪除為1
?????*/
????private?Integer?deleteFlag;
????/**
?????*?發(fā)送時間
?????*/
????private?LocalDateTime?sendTime;
????/**
?????*?語音時長
?????*/
????private?Integer?voiceTime;
????/**
?????*?發(fā)送人昵稱
?????*/
????private?String?fromNick;
????/**
?????*?接受人昵稱
?????*/
????private?String?toNick;
????/**
?????*?組名稱???如:群聊編號,?直播編號,?話題編號
?????*/
????private?String?groupPrefix;
????/**
?????*?組標記,0:是私聊?1:是多人聊天;?3是臨時會話;4:是客服聊天
?????*/
????private?Integer?groupFlag;
????/**
?????*?發(fā)送人頭像
?????*/
????private?String?fromMsg;
????/**
?????*?接受人頭像
?????*/
????private?String?toMsg;
????/**
?????*?發(fā)送人的大v圖片
?????*/
????private?String?fromMsgSignV;
????/**
?????*?發(fā)送人的皇冠圖片
?????*/
????private?String?fromMsgSignAnCrown;
????/**
?????*?接受人大v圖片
?????*/
????private?String?toMsgSignV;
????/**
?????*?接受人皇冠圖片
?????*/
????private?String?toMsgSignAnCrown;
????/**
?????*?最佳吐槽???1為最佳吐槽?
?????*/
????private?Integer?bestBlowing;
????/**
?????*?用戶類型??普通用戶:1;客服?2;會員:3?;超級會員?4?;直播人:5;??
?????*/
????private?Integer?userType;
????/**
?????*?平臺標識
?????*/
????private?String?platCode;
}
六、定義Vo類(可選)

package?com.easy.webscoket.vo;
import?lombok.AllArgsConstructor;
import?lombok.Data;
import?lombok.NoArgsConstructor;
/**
?*?@program:?easy
?*?@description:?客戶端發(fā)過來的消息
?*?@author:?zte
?*?@create:?2019-05-06?10:22
?**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public?class?ClientMessage?{
????private?int?id;
????private?String?name;
}
package?com.easy.webscoket.vo;
import?lombok.AllArgsConstructor;
import?lombok.Data;
import?lombok.NoArgsConstructor;
/**
?*?@program:?easy
?*?@description:?服務端返回消息
?*?@author:?zte
?*?@create:?2019-05-06?10:25
?**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public?class?ServerMessage?{
????private?String?content;
}
七、點對點聊天(html)
"en">
????"UTF-8">
????Title
????
????
????
"disconnect()">
????
????????
????????
????
????"conversationDiv">
????????type="text"?id="name"?/>
????????
????????"response">
????
八、群聊(html)
"http://www.thymeleaf.org">
????群聊
????"Content-Type"?content="text/html;?charset=UTF-8"?/>
????"viewport"?content="width=device-width,?initial-scale=0.7,?user-scalable=no,?shrink-to-fit=no">
????"stylesheet"?href="/webrtc/css/bootstrap-material-design.min.css">
????
????
"width:?20%;height:?100%;align-items:?initial?!important;background:?#fff;">
????"layui-tab?layui-tab-brief"?lay-filter="docDemoTabBrief"
????????style="width:?100%;display:?block;margin:?0;">
????????"layui-tab-title"?style="display:?flex;justify-content:?center"
????????????lay-filter="queSearch">
????????????- "layui-this">簡介
????????????- 討論區(qū)
????????
????????"layui-tab-content"?style="display:?block;width:?100%;">
????????????"${introduction}"?class="layui-tab-item?layui-show"
????????????????style="color:?#333;line-height:?20px;font-size:?12px;">
????????????"layui-tab-item"?style="width:?100%;">
????????????????"commentCon">
????????????????????"response">
????????????????
????????????????"inputbottom">
????????????????????type="text"?id="yourMessage"?placeholder="說點兒什么"?maxlength="200">
????????????????????
????????????????
????????????????
????????????
????????
????
????
??
????
????
九、對應sql
/*
?Navicat?Premium?Data?Transfer
?Source?Server?????????:?hfky
?Source?Server?Type????:?MySQL
?Source?Server?Version?:?50723
?Source?Host???????????:?49.233.66.170:3306
?Source?Schema?????????:?hfky
?Target?Server?Type????:?MySQL
?Target?Server?Version?:?50723
?File?Encoding?????????:?65001
?Date:?24/09/2020?17:10:39
*/
SET?NAMES?utf8mb4;
SET?FOREIGN_KEY_CHECKS?=?0;
--?----------------------------
--?Table?structure?for?t_message
--?----------------------------
DROP?TABLE?IF?EXISTS?`t_message`;
CREATE?TABLE?`t_message`??(
??`id`?bigint(20)?NOT?NULL?AUTO_INCREMENT,
??`from_user`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人',
??`to_user`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接收人',
??`content`?text?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?COMMENT?'消息內(nèi)容',
??`msg_type`?int(4)?NULL?DEFAULT?1?COMMENT?'消息類型:1?文字??;2圖片;?默認為1',
??`read_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'是否已讀,?0:未讀,?1:已讀',
??`delete_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'?正常為?0??刪除為1',
??`send_time`?datetime(0)?NULL?DEFAULT?CURRENT_TIMESTAMP(0)?COMMENT?'發(fā)送時間',
??`voice_time`?int(4)?NULL?DEFAULT?NULL?COMMENT?'語音時長',
??`from_nick`?varchar(80)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人昵稱',
??`to_nick`?varchar(80)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人昵稱',
??`group_prefix`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'組名稱???如:群聊編號,?直播編號,?話題編號',
??`group_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'組標記,1:培訓討論;2:會診直播',
??`from_msg`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人頭像',
??`to_msg`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人頭像',
??`from_msg_sign_v`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人的大v圖片',
??`from_msg_sign_an_crown`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人的皇冠圖片',
??`to_msg_sign_v`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人大v圖片',
??`to_msg_sign_an_crown`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人皇冠圖片',
??`best_blowing`?int(11)?NULL?DEFAULT?0?COMMENT?'最佳吐槽???1為最佳吐槽?',
??`user_type`?int(11)?NULL?DEFAULT?NULL?COMMENT?'用戶類型??普通用戶:1;客服?2;會員:3?;超級會員?4?;直播人:5;??',
??`plat_code`?varchar(50)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'平臺標識',
??PRIMARY?KEY?(`id`)?USING?BTREE
)?ENGINE?=?InnoDB?AUTO_INCREMENT?=?4044?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?COMPACT;
SET?FOREIGN_KEY_CHECKS?=?1;
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:
http://blog.csdn.net/qq_44922113/article/details/108777548


??? ?
感謝點贊支持下哈?
