springboot整合websocket

java1234

共 16354字,需浏览 33分钟

 · 2020-09-28

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

66套java从入门到精通实战课程分享

一、永恒第一步:导入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,消息的发送的地址符合配置的前缀来的消息才发送到这个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协议的端点。这个HTTP URL是供WebSocket或SockJS客户端访问的地址
         * setAllowedOrigins("*") 允许跨域
         * withSockJS:指定端点使用SockJS协议
         */
        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;

    /**
     * 实现 WebSocketConfigurer 接口,重写 registerWebSocketHandlers 方法,这是一个核心实现方法,配置 websocket 入口,允许访问的域、注册 Handler、SockJs 支持和拦截器。
     * 


     * registry.addHandler()注册和路由的功能,当客户端发起 websocket 连接,把 /path 交给对应的 handler 处理,而不实现具体的业务逻辑,可以理解为收集和任务分发中心。
     * 


     * addInterceptors,顾名思义就是为 handler 添加拦截器,可以在调用 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";

    /**
     * 统一前缀
     */
    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<>();

    /**
     * 连接建立成功调用的方法
     */
    @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;

    /**
     * 存储聊天数据页面
     * @return
     */
    @ApiOperation(value = "聊天记录添加接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "发送人", required = true),
            @ApiImplicitParam(name = "content", value = "聊天内容", 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;

    /**
     * 发送人
     */
    private String fromUser;

    /**
     * 接收人
     */
    private String toUser;

    /**
     * 消息内容
     */
    private String content;

    /**
     * 消息类型:1 文字  ;2语音; 3图片; 4 视频 5 礼物 6邀请入队 默认为1
     */
    private Integer msgType;

    /**
     * 是否已读, 0:未读, 1:已读
     */
    private Integer readFlag;

    /**
     *  正常为 0  删除为1
     */
    private Integer deleteFlag;

    /**
     * 发送时间
     */
    private LocalDateTime sendTime;

    /**
     * 语音时长
     */
    private Integer voiceTime;

    /**
     * 发送人昵称
     */
    private String fromNick;

    /**
     * 接受人昵称
     */
    private String toNick;

    /**
     * 组名称   如:群聊编号, 直播编号, 话题编号
     */
    private String groupPrefix;

    /**
     * 组标记,0:是私聊 1:是多人聊天; 3是临时会话;4:是客服聊天
     */
    private Integer groupFlag;

    /**
     * 发送人头像
     */
    private String fromMsg;

    /**
     * 接受人头像
     */
    private String toMsg;

    /**
     * 发送人的大v图片
     */
    private String fromMsgSignV;

    /**
     * 发送人的皇冠图片
     */
    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: 客户端发过来的消息
 * @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()">

    

        "connect" onclick="connect();">连接
        "disconnect" disabled="disabled" onclick="disconnect();">断开连接
    

    "conversationDiv">
        type="text" id="name" />
        "sendName" onclick="sendName();">发送
        "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">简介
            
  • 讨论区

  •         
            "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">
                        "sendAll();" id="sendAll" type="button"
                            class="layui-btn layui-btn-normal"
                            style="background-color: #38AAFF !important;border-radius: 5px">发送
                    

                    
                
            
        




        
      
        
        



    九、对应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 '发送人',
      `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 '消息内容',
      `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 '发送时间',
      `voice_time` int(4) NULL DEFAULT NULL COMMENT '语音时长',
      `from_nick` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发送人昵称',
      `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 '发送人头像',
      `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 '发送人的大v图片',
      `from_msg_sign_an_crown` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送人的皇冠图片',
      `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;




    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    本文链接:

    http://blog.csdn.net/qq_44922113/article/details/108777548




         



    感谢点赞支持下哈 

    浏览 39
    点赞
    评论
    收藏
    分享

    手机扫一扫分享

    举报
    评论
    图片
    表情
    推荐
    点赞
    评论
    收藏
    分享

    手机扫一扫分享

    举报