当前位置: 首页 > news >正文

深圳网站建设 cms湖南网络推广机构

深圳网站建设 cms,湖南网络推广机构,沈阳网站建设开发,顺德网站制作案例咨询一.什么是WebSocket? WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器的全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输 HTTP 协议是一种无状态的、无连接的、单向的应用…

一.什么是WebSocket?

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器的全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输

HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步 AJAX 请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

http协议:

07e80c5383974729ba528bceef04debb.jpeg

 

websocket协议:

aec402415caf4ee68e8b89bad2e044c8.jpeg

二.HTTP协议和WebSocket协议对比:

  • HTTP是短连接
  • WebSocket是长连接
  • HTTP通信是单向的,基于请求响应模式 WebSocket支持双向通信
  • HTTP和WebSocket底层都是TCP连接

三.基于WebSocket的智能学习助手功能实现

1.需求

通过 websocket 实现一个简易的聊天室功能 

        当点击智能学习助手选项,会进入一个聊天室,小助手自动向用户问好,用户可以向小助手提问问题,小助手后端查询到问题答案后会进行回复

bfa15c4c381e4e42829925803765104d.png

2.前端

前端环境:vue3+element-plus+pinia

因为我的这个项目用户端和管理端共用该功能,所以URL上带上了从pinia中获取的当前登录用户的信息,用于与后端建立唯一的连接标识

下面的代码是只对于学习小助手组件的.vue文件,读者有需自行扩展

<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";import useUserInfoStore from "@/stores/userInfo.js";
const userInfoStore = useUserInfoStore();
const userInfo = ref({ ...userInfoStore.info });// 发送的信息
const say = ref("");
// 内容
const content = ref("");
// 管理员1,普通用户0
const role = userInfo.value.role == "管理员" ? 1 : 0;
// 发送给后端的URL
const url = ref("ws://localhost:8080/char/" + role);var websocket = null;
//判断当前浏览器是否支持WebSocket
if ("WebSocket" in window) {//连接WebSocket节点websocket = new WebSocket(url.value);
} else {ElMessage.error("Not support websocket");
}//连接发生错误的回调方法
websocket.onerror = function () {ElMessage.error("连接错误");
};//连接成功建立的回调方法
websocket.onopen = function () {ElMessage.success("连接成功");createContent(false, "你好,我是智能学习小助手~");
};//接收到消息的回调方法
websocket.onmessage = function (event) {createContent(false, event.data);
};//连接关闭的回调方法
websocket.onclose = function () {ElMessage.success("连接关闭");
};//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {websocket.close();
};//发送消息
function send() {websocket.send(say.value);createContent(true, say.value);say.value = "";
}//关闭连接
function closeWebSocket() {websocket.close();
}// 构造消息框
const createContent = (isMyMsg, msg) => {let html;// 当前用户消息if (isMyMsg) {html ='<div class="el-row" style="padding: 5px 0">\n' +'  <div class="el-col el-col-22" style="text-align: right; padding-right: 10px">\n' +'    <div style="color: white;text-align: center;border-radius: 10px;font-family: sans-serif;padding: 10px;width:auto;display:inline-block !important;display:inline;background-color: deepskyblue;">' +msg +"</div>\n" +"  </div>\n" +'  <div class="el-col el-col-2">\n' +'  <span class="el-avatar el-avatar--circle" style="height: 40px; width: 40px; line-height: 40px;">\n' +'    <img src="' +userInfo.value.userUrl +'" style="object-fit: cover;">\n' +"  </span>\n" +"  </div>\n" +"</div>";} else {// 助手信息html ='<div class="el-row" style="padding: 5px 0">\n' +'  <div class="el-col el-col-2" style="text-align: right">\n' +'  <span class="el-avatar el-avatar--circle" style="height: 40px; width: 40px; line-height: 40px;">\n' +'    <img src="' +"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" +'" style="object-fit: cover;">\n' +"  </span>\n" +"  </div>\n" +'  <div class="el-col el-col-22" style="text-align: left; padding-left: 10px">\n' +'    <div style="color: white;text-align: center;border-radius: 10px;font-family: sans-serif;padding: 10px;width:auto;display:inline-block !important;display:inline;background-color: deepskyblue;">' +msg +"</div>\n" +"  </div>\n" +"</div>";}content.value += html;
};
</script>
<template><el-card class="page-container"><template #header><div class="block text-center"><el-row :gutter="20"><el-col :span="6" :offset="11"><span>智能学习小助手</span></el-col></el-row><!-- 分割线 --><el-divider /><!-- 走马灯 --><el-carousel height="150px"><el-carousel-item v-for="item in 4" :key="item"><h3 class="small justify-center" text="2xl">韩磊大帅哥{{ item }}</h3></el-carousel-item></el-carousel></div></template><!-- 滚动条 --><el-scrollbar height="460px"><div v-html="content"></div></el-scrollbar><template #footer><el-row><el-inputstyle="width: 100%":autosize="{ minRows: 4, maxRows: 8 }"type="textarea"v-model="say"placeholder="有困难就找汪汪队~"/></el-row><el-row style="margin-top: 10px"><el-col :span="2" :offset="20"><div class="grid-content ep-bg-purple" /><el-button type="primary" @click="send()">发送</el-button></el-col><el-col :span="1"><div class="grid-content ep-bg-purple" /><el-button type="primary" @click="say = ''">清空文本</el-button></el-col></el-row></template></el-card>
</template>
<style lang="scss" scoped>
.page-container {min-height: 100%;box-sizing: border-box;.header {display: flex;align-items: center;justify-content: space-between;}
}
.el-carousel__item h3 {color: #475669;opacity: 0.75;line-height: 150px;margin: 0;text-align: center;
}
.img {width: 100%;height: 460px;
}
.el-carousel__item:nth-child(2n) {background-color: #99a9bf;
}.el-carousel__item:nth-child(2n + 1) {background-color: #d3dce6;
}
.tip {color: white;text-align: center;border-radius: 10px;font-family: sans-serif;padding: 10px;width: auto;display: inline-block !important;display: inline;
}
.right {background-color: deepskyblue;
}
.left {background-color: forestgreen;
}
</style>

3.后端

后端环境:springboot+lombok+web+mybatisplus+websocket

3.1.Springboot 添加Pom依赖

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

3.2.添加Websocket配置


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类,用于注册WebSocket的Bean*/
@Configuration
public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

3.3.构建数据库

3.3.1.配置并连接数据库并创建问题表(自行完成)

3.3.2.pojo类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("lw_answers")
public class Answer {@TableId(type = IdType.AUTO)private Long answerId; // 问题IDprivate String issue; // 问题private String answer; // 回答
}

3.3.3.注册Mapper接口

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hl.pojo.entity.Answer;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface AnswerMapper extends BaseMapper<Answer> {
}

3.3.4.注册WebSocketServer接口

因为我们每个建立会话的对象要唯一!所以对于不同的用户我们根据用户角色和用户id来建立唯一标识

package com.hl.server.websocket;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hl.common.constant.MessageConstant;
import com.hl.common.context.BaseContext;
import com.hl.common.enumeration.UserRole;
import com.hl.pojo.entity.Answer;
import com.hl.server.mapper.AnswerMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** WebSocket服务*/
@Slf4j
@Component
@ServerEndpoint("/char/{role}")
public class WebSocketServer {/*** WebSocket API 是独立于任何特定框架的标准,* 它的生命周期和管理是由 WebSocket 容器负责的,而不是由 Spring 容器负责。* 因此,WebSocket 容器不会识别或处理 Spring 的依赖注入注解。*/private static AnswerMapper answerMapper;@Autowiredprivate void setAnswerMapper(AnswerMapper answerMapper) {WebSocketServer.answerMapper = answerMapper;}//存放会话对象private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session,@PathParam("role") Integer role) {String key=getUserInfo(role);log.info("WebSocketServer onOpen role:{}",key);sessionMap.put(key, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message,@PathParam("role") Integer role) {String key=getUserInfo(role);log.info("WebSocketServer onMessage user:{} message:{}",key,message);LambdaQueryWrapper<Answer> queryWrapper=new LambdaQueryWrapper<Answer>().like(Answer::getIssue,message);Answer ans = answerMapper.selectOne(queryWrapper);String answer = ans==null? MessageConstant.BU_ZHIDAO:ans.getAnswer();sessionMap.get(key).getAsyncRemote().sendText(answer);}/*** 连接关闭调用的方法*/@OnClosepublic void onClose(@PathParam("role") Integer role) {String key=getUserInfo(role);log.info("WebSocketServer onClose:{}",key);sessionMap.remove(key);}/*** 获取唯一标识key*/public String getUserInfo(Integer role) {String key="";// 根据LocalThread获取当前登录用户idLong id= BaseContext.getCurrentId();if(role== UserRole.COMMON.getValue()){//普通用户key=UserRole.COMMON.getDesc()+id;}else{//管理员key=UserRole.ADMIN.getDesc()+id;}return key;}}

注: WebSocket API 是独立于任何特定框架的标准, 它的生命周期和管理是由 WebSocket 容器负责的,而不是由 Spring 容器负责。 因此,WebSocket 容器不会识别或处理 Spring 的依赖注入注解,所以我们不能使用字段注入!

 

 

 

http://www.khdw.cn/news/41842.html

相关文章:

  • 上海网站优化排名网站设计与制作毕业论文范文
  • 合肥做网站公一份完整的品牌策划方案
  • 沈阳网站建设电话seo工作流程
  • 做鞋用什么网站好天津seo推广优化
  • 乐从做网站网页设计制作
  • 达州达县网站建设清博大数据舆情监测平台
  • 河北优化网站获客qq网站宣传方式有哪些
  • 国外做免费的视频网站外贸推广如何做
  • 提供做网站服务好谷歌网页版
  • 东莞网站建设模板设计商品营销推广的方法有哪些
  • 免费一站式网站建设百度账号设置
  • 网页设计网站模板网站建设网页模板优化设计五年级上册语文答案
  • 上海建网站服务器郑州seo外包费用
  • 网站建设推广保举火13星优化模型
  • 美女直接做的视频网站国家卫健委:不再发布每日疫情信息
  • 成都网站建设市场百度贴吧广告投放价格
  • 现货做网站百度统计代码
  • 滨海企业做网站多少钱东营百度推广电话
  • 官方网站做兼职免费下载官方百度
  • 专门做情趣用品的网站求购买链接
  • php如何做视频网站郑州做网站推广资讯
  • 为什么电脑打开那个做网站都是那一个软文案例400字
  • 确保网站建设又在前列优化疫情防控 这些措施你应该知道
  • flash网站建设方案夜夜草
  • 选择热门网站做推广的原因个人怎么注册自己的网站
  • 网站 友情链接怎么做百度关键词seo外包
  • 毕业论文做家具网站设计要求seo云优化平台
  • 云服务器怎么做网站域名查询ip爱站网
  • 美食网页设计报告搜索引擎排名优化技术
  • 做教育类的网站名注册一个公司网站需要多少钱