SpringBoot + WebSocket实现聊天(1)

电脑杂谈  发布时间:2020-05-31 16:05:26  来源:网络整理

websocket 服务端实现_websocket实现单聊_websocket实现

聊天功能是为了促进HR的快速沟通. 由于人力资源的数量有限,因此此处不考虑高并发问题. 小伙伴必须结合问题来考虑环境. 好,让我们先看一下效果图:

聊天渲染

登录成功后,单击右上角的警报图标进入消息页面,单击“好友聊天”页签,效果如下:

图片描述

此时更改浏览器,或使用chrome中的多用户模式打开另一个浏览器,以另一个用户身份登录并开始聊天. 聊天页面如下:

图片描述

如果系统管理员正在与Han Yu聊天,并且此时李白发送了消息,那么李白的名字旁边会出现一个提示:

图片描述

websocket实现单聊_websocket 服务端实现_websocket实现

系统消息的有效图片

只有管理员有权发送系统消息. 管理员的系统消息页面如下:

图片描述

普通HR的系统消息页面没有发送按钮. 系统消息页面如下:

图片描述

消息发送成功后,将出现一个红点提示未读消息,如下所示:

图片描述

好的,总体效果是这样的,功能仍然不完善websocket实现单聊,以后会有时间修复它.

websocket 服务端实现_websocket实现单聊_websocket实现

让我们讨论一下实施思路:

聊天使用SpringBoot + WebSocket实现. 为了确保用户隐私,所有聊天数据都存储在系统本地,服务器仅转发数据. 好,接下来,让我们看一下一般的实现步骤.

服务器

服务器首先加入websocket依赖关系,如下所示:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

创建如下的WebSocket配置类:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/ws/endpointChat").withSockJS();
    }
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/queue","/topic");
    }
}

这里我没有使用本地websocket协议,但是使用了websocket子协议stomp,这更加方便. 消息代理使用/队列和/主题,主要是因为我同时具有发送系统消息的点对点单一聊天(队列)和组聊天(主题).

websocket实现_websocket 服务端实现_websocket实现单聊

创建一个websocket处理类Controller,如下所示:

@Controller
public class WsController {
    @Autowired
    SimpMessagingTemplate messagingTemplate;
    @MessageMapping("/ws/chat")
    public void handleChat(Principal principal, String msg) {
        String destUser = msg.substring(msg.lastIndexOf(";") + 1, msg.length());
        String message = msg.substring(0, msg.lastIndexOf(";"));
        messagingTemplate.convertAndSendToUser(destUser, "/queue/chat", new ChatResp(message, principal.getName()));
    }
}

消息协议非常简单: 消息已发送,最后一条;然后是要发送消息的用户,这里是通过字符串截取提取消息的. 响应消息包含两个字段,一个是消息的内容,另一个是发送消息的人.

好的,在那之后,我们的服务器被编写,非常简单.

前端

前端代码稍微复杂一点. 在这里,我将主要与朋友们一起介绍我的一般想法和核心代码. 特定的代码合作伙伴可以通过星标源代码进行研究.

首先websocket实现单聊,当用户成功登录时,我启动一个websocket连接并连接ws. 我主要在商店中编写了ws代码,如下所示:

connect(context){
    context.state.stomp = Stomp.over(new SockJS("/ws/endpointChat"));
    context.state.stomp.connect({}, frame=> {
    context.state.stomp.subscribe("/user/queue/chat", message=> {
        var msg = JSON.parse(message.body);
        var oldMsg = window.localStorage.getItem(context.state.user.username + "#" + msg.from);
        if (oldMsg == null) {
        oldMsg = [];
        oldMsg.push(msg);
        window.localStorage.setItem(context.state.user.username + "#" + msg.from, JSON.stringify(oldMsg))
        } else {
        var oldMsgJson = JSON.parse(oldMsg);
        oldMsgJson.push(msg);
        window.localStorage.setItem(context.state.user.username + "#" + msg.from, JSON.stringify(oldMsgJson))
        }
        if (msg.from != context.state.currentFriend.username) {
        context.commit("addValue2DotMap", "isDot#" + context.state.user.username + "#" + msg.from);
        }
        //更新msgList
        var oldMsg2 = window.localStorage.getItem(context.state.user.username + "#" + context.state.currentFriend.username);
        if (oldMsg2 == null) {
        context.commit('updateMsgList', []);
        } else {
        context.commit('updateMsgList', JSON.parse(oldMsg2));
        }
    });
    }, failedMsg=> {
    });
}

websocket实现单聊_websocket 服务端实现_websocket实现

连接成功后,您就可以从服务器接收消息了. 从服务器接收到消息后,数据将保存在localStorage中,格式为当前用户名#消息发件人用户名: [{来自: '消息发件人',消息: '消息内容'}],请注意,后面是一个json数组,整个存储的键使用当前用户名#消息发件人用户名,以避免由多个用户在同一浏览器中登录生成的数据Disorder,OK,因此两个人的聊天记录将保存在此数组中. 在聊天显示页面上,当数组中的数据更改时,它会自动更新.

在聊天页面上,通过重脚发送消息,如下所示:

this.$store.state.stomp.send("/ws/chat", {}, this.msg + ";" + this.currentFriend.username);

请注意,除了内容本身之外,每封邮件的内容还必须包括当前发件人的姓名.

每次成功传输后,更新聊天页面. 更新聊天页面的代码如下:

<template v-for="msg in msgList">
<!--发送来的消息-->
<div
    style="display: flex;justify-content: flex-start;align-items: center;box-sizing: border-box;"
    v-if="msg.from==currentFriend.username">
    <img :class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="currentFriend.userface" class="userfaceImg">
    <div
    style="display: inline-flex;border-style: solid;border-width: 1px;border-color: #20a0ff;border-radius: 5px;padding: 5px 8px 5px 8px">
    {{msg.msg}}
    </div>
</div>
<!--发出去的消息-->
<div v-if="msg.from!=currentFriend.username"
        style="display: flex;justify-content: flex-end;align-items: center;box-sizing: border-box;">
    <div
    style="display: inline-flex;border-style: solid;border-width: 1px;border-color: #20a0ff;border-radius: 5px;padding: 5px 8px 5px 8px;margin-right: 3px;background-color: #9eea6a">
    {{msg.msg}}
    </div>
    <img :class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="currentUser.userface" class="userfaceImg">
</div>
</template>

如果消息中“发件人”字段的值是当前聊天的用户名,则为已发送消息,否则为已发送消息,并且可以用不同的样式设置不同的消息.

核心代码基本相同,但琐碎的细节实际上更多,小伙伴可以研究星形源代码.


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-228995-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...