电商网站建设需求分析 实例题,国外搜索网站建设,电子商务网站建设的主要内容,南京广告公司招聘信息springbootwebsocket微信小程序实现评论区功能 WebSocketSTOMP协议具体实现1.在pom文件中添加Spring WebSocket依赖2. 创建WebSocket配置类3.接收发送消息4.前端 参考 WebSocket
1. 什么是WebSocket#xff1f;
WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双… springbootwebsocket微信小程序实现评论区功能 WebSocketSTOMP协议具体实现1.在pom文件中添加Spring WebSocket依赖2. 创建WebSocket配置类3.接收发送消息4.前端 参考 WebSocket
1. 什么是WebSocket
WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信能更好的节省服务器资源和带宽并达到实时通讯它建立在 TCP 之上同 HTTP 一样通过 TCP 来传输数据但是它和 HTTP 最大不同是 WebSocket 是一种双向通信协议在建立连接后WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据就像 Socket 一样 WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接连接成功后才能相互通信。
2. WebSocket的特点
全双工通信WebSocket协议支持服务器和客户端之间的全双工通信客户端和服务器可以同时发送消息。持久连接WebSocket连接一旦建立将持续保持打开状态直到客户端或服务器关闭连接。跨域通信WebSocket协议支持跨域通信允许不同域的服务器与客户端建立连接。
STOMP协议
STOMP协议相当于Websocket的子协议。 STOMP 中文为: 面向消息的简单文本协议 websocket定义了两种传输信息类型:文本信息和二进制信息。类型虽然被确定但是他们的传输体是没有规定的。所以需要用一种简单的文本传输类型来规定传输内容它可以作为通讯中的文本传输协议。 STOMP是基于帧的协议客户端和服务器使用STOMP帧流通讯 一个STOMP客户端是一个可以以两种模式运行的用户代理可能是同时运行两种模式。 作为生产者通过SEND框架将消息发送给服务器的某个服务 作为消费者通过SUBSCRIBE制定一个目标服务通过MESSAGE框架从服务器接收消息。 例如 COMMAND
header1:value1
header2:value2Body^注帧以commnand字符串开始以EOL结束。其中包括可选回车符13字节紧接着是换行符10字节。command下面是0个或多个:格式的header条目, 每个条目由EOL结束。一个空白行即额外EOL表示header结束和body开始。body连接着NULL字节。本文档中的例子将使用^代表NULL字节。NULL字节可以选择跟多个EOLs。欲了解更多关于STOMP帧的详细信息请参阅STOMP1.2协议规范。 具体实现
微信小程序提供的关于WebSocket的API不是基于STOMP协议的只能用websocket实现当然可以对微信小程序的前端进行更改使其可以使用基于STOMP协议的后端实现。
基于STOMP协议的websocket实现可以参考Java实战Spring Boot实现WebSocket实时通信
1.在pom文件中添加Spring WebSocket依赖
dependencies!-- Spring Boot Web依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!-- Spring Boot WebSocket依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId/dependency
/dependencies2. 创建WebSocket配置类
package com.lixy.sharingcurriculum.config;import com.lixy.sharingcurriculum.controller.CommentController;
import com.lixy.sharingcurriculum.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;Configuration
EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {/*使用springboot内置tomcat需要该bean打war包则注释掉该bean*/Beanpublic ServerEndpointExporter serverEndpoint() {return new ServerEndpointExporter();}Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {//注册一个WebSocket端点路径为/ws//registry.addEndpoint(/ws).withSockJS();//客户端调用的URLregistry.addEndpoint(/ws).setAllowedOrigins(*);}//因为websocket中不能直接使用Autowired注入Service添加下面配置 在socket引入ServiceAutowiredpublic void socketUserService(CommentService commentService){CommentController.commentService commentService;}
} 创建一个WebSocket的配置类WebSocketConfig 实现WebSocketMessageBrokerConfigurer 接口需要手动注入ServerEndpointExporter这个bean会自动注册使用了ServerEndpoint注解声明的Websocket endpoint。 我的理解是为了将WebSocket与Spring容器整合通过在配置类中添加Bean使其返回对象ServerEndpointExporter意味着将该对象纳入spring框架的管理中spring容器将能够处理WebSocket相关的配置和依赖。 registry.addEndpoint(/ws).setAllowedOrigins(*);意思是允许/ws/*的所有请求访问。websocket默认禁止了非同源访问 如果没有加入自己的跨域配置或这个配置的话前端将会报403错误。参考客户端连接spring websocket 返回403错误 因为我需要同时对数据库进行修改所以引入了commentService进行数据相关操作。 同源访问指的是WebSocket连接的客户端和服务器端拥有相同的协议、主机和端口。 在Web开发中同源策略是一种安全机制它要求前端的网页脚本只能与同源的服务器进行交互。具体来说同源访问要求客户端的页面和服务器端的服务必须使用相同的协议如HTTP或HTTPS、相同的主机名如www.example.com以及相同的端口号如80或443。如果这些条件中有任何一个不匹配那么就是非同源访问。 对于WebSocket而言虽然它本身并不强制执行同源策略但浏览器的安全限制通常要求WebSocket遵循同源策略。这意味着默认情况下一个网页中的WebSocket脚本只能连接到与其同源的服务器。如果需要连接到不同源的服务器可以使用CORS跨域资源共享来允许这种跨域访问。 总结来说同源访问是WebSocket通信的一种默认安全限制它要求客户端和服务器在协议、主机和端口上保持一致。如果需要进行非同源访问开发者需要在服务器端配置相应的CORS策略以允许跨域的WebSocket连接。 3.接收发送消息
webSocket接收和发送的消息的类型只能是String类型所以在传数据的时候需要做相应的处理。
package com.lixy.sharingcurriculum.controller;import com.alibaba.fastjson.JSON;
import com.lixy.sharingcurriculum.entity.Message;
import com.lixy.sharingcurriculum.entity.dto.MessDto;
import com.lixy.sharingcurriculum.service.CommentService;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
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.Component;
import org.springframework.stereotype.Controller;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;Component
ServerEndpoint(/ws/{courid}/{userid})
Slf4j
public class CommentController {//存储被课程id和正在讨论区中的用户id和对应会话public static final MapString, MapString, Session sessionMap new ConcurrentHashMap();public static CommentService commentService;/**** 建立连接时调用* 1.第一层map存储被课程id和浏览的用户及会话* 2.第二层map存储用户id及会话*/OnOpenpublic void onOpen(Session session, PathParam(courid) String courid,PathParam(userid) String userid){log.info(用户{}打开了课程{}的讨论区,userid,courid);if(sessionMap.containsKey(courid)){sessionMap.get(courid).put(userid,session);}else {MapString,Session map new HashMap();map.put(userid,session);sessionMap.put(courid,map);}log.info(String.valueOf(sessionMap));}/*** 接收处理客户端发来的数据*/OnMessagepublic void onMessage(String message) {
// 解析消息为java对象Message msg JSON.parseObject(message, Message.class);log.info(msg:msg);if(msg ! null msg.getContent() ! null !msg.getContent().isEmpty()){//将评论内容存入数据库MessDto messDtocommentService.saveComment(msg);//将评论内容发送给其他正在浏览该文章的用户sendAllMessage(messDto);}else{System.out.println(评论内容为空);}}//服务端发送消息给客户端private void sendAllMessage(Message message) {log.info(sendAllMessage:{},message);try {String courid message.getCourid();log.info(courid:{},courid);//根据评论发送课程的id将该评论发送给正在讨论区中的用户MapString,Session passageMap sessionMap.get(courid);for (Session session : passageMap.values()) {session.getBasicRemote().sendText(JSON.toJSONString(message));}} catch (Exception e) {e.printStackTrace();}}//关闭连接/*** 1.把登出的用户从sessionMap中剃除* 2.发送给所有人当前登录人员信息*/OnClosepublic void onClose(PathParam(courid) String courid,PathParam(userid) String userid) {//用户退出讨论区则将该用户及其会话移除MapString,Session passageMap sessionMap.get(courid);passageMap.remove(userid);//没有用户在讨论区中则将课程id从map中移除if(passageMap.isEmpty()){sessionMap.remove(courid);}}OnErrorpublic void onError(Session session, Throwable error) {System.out.println(发生错误);error.printStackTrace();}}
4.前端
//创建WebSocket连接createWebSocket(){const websocket wx.connectSocket({url: ws://localhost:8080/ws/this.data.courid/this.data.userid,success: () {console.log(WebSocket连接成功);},fail: (error) {console.log(WebSocket连接失败, error);}})// 监听WebSocket连接打开事件websocket.onOpen(() {console.log(WebSocket连接已打开);console.log(readyState:, websocket.readyState); // 应该输出: OPEN (1) });// 监听WebSocket接收到服务器消息事件websocket.onMessage((message) {console.log(收到服务器消息, message);// 处理服务器返回的消息例如更新页面数据等操作var commentJSON.parse(message.data)comment.createtimethis.timestampToDate(comment.createtime)var comment_listthis.data.comment_list;comment_list.push(comment)this.setData({comment_list})});// 监听WebSocket连接关闭事件websocket.onClose(() {console.log(WebSocket连接已关闭);});// 监听WebSocket错误事件websocket.onError((error) {console.log(WebSocket发生错误, error);});// 将WebSocket对象保存到data中this.setData({websocket: websocket,});},// 发送消息到WebSocket服务器if (this.data.websocket this.data.websocket.readyState 1) {this.data.websocket.send({data: JSON.stringify(message), // 要发送的消息内容success: () {console.log(消息发送成功);},fail: (error) {console.log(消息发送失败, error);},});} else {console.log(WebSocket连接未打开或不存在);}
参考
Java实战Spring Boot实现WebSocket实时通信 WebSocket和Stomp协议 个人博客——使用websocket实现评论实时展示 客户端连接spring websocket 返回403错误 微信小程序 内容评论-回复评论-回复回复的实现