springboot+websocket+微信小程序实现评论区功能

这篇具有很好参考价值的文章主要介绍了springboot+websocket+微信小程序实现评论区功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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:value2

Body^@

注:帧以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依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Boot WebSocket依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
</dependencies>

2. 创建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
     */
    @Bean
    public ServerEndpointExporter serverEndpoint() {
        return new ServerEndpointExporter();
    }


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个WebSocket端点,路径为"/ws"
        //registry.addEndpoint("/ws").withSockJS();

        //客户端调用的URL;
        registry.addEndpoint("/ws").setAllowedOrigins("*");
    }

    //因为websocket中不能直接使用@Autowired注入Service,添加下面配置 在socket引入Service
    @Autowired
    public 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 Map<String, Map<String, Session>> sessionMap = new ConcurrentHashMap<>();
    public static CommentService commentService;


    /***
     * 建立连接时调用
     * 1.第一层map存储被课程id和浏览的用户及会话
     * 2.第二层map存储用户id及会话
     */
    @OnOpen
    public 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 {
            Map<String,Session> map = new HashMap<>();
            map.put(userid,session);
            sessionMap.put(courid,map);
        }

        log.info(String.valueOf(sessionMap));


    }

    /**
     * 接收处理客户端发来的数据
     */
    @OnMessage
    public 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 messDto=commentService.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,将该评论发送给正在讨论区中的用户
            Map<String,Session> passageMap = sessionMap.get(courid);
            for (Session session : passageMap.values()) {
                session.getBasicRemote().sendText(JSON.toJSONString(message));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //关闭连接
    /**
     * 1.把登出的用户从sessionMap中剃除
     * 2.发送给所有人当前登录人员信息
     */
    @OnClose
    public void onClose(@PathParam("courid") String courid,@PathParam("userid") String userid) {
        //用户退出讨论区,则将该用户及其会话移除
        Map<String,Session> passageMap = sessionMap.get(courid);
        passageMap.remove(userid);
        //没有用户在讨论区中,则将课程id从map中移除
        if(passageMap.isEmpty()){
            sessionMap.remove(courid);
        }


    }

    @OnError
    public 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 comment=JSON.parse(message.data)
      comment.createtime=this.timestampToDate(comment.createtime)
      
      var comment_list=this.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错误
微信小程序 内容评论-回复评论-回复回复的实现文章来源地址https://www.toymoban.com/news/detail-853433.html

到了这里,关于springboot+websocket+微信小程序实现评论区功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序完整实现微信支付功能(SpringBoot和小程序)

    1.前言 不久前给公司实现支付功能,折腾了一阵子,终于实现了,微信支付对于小白来说真的很困难,特别是没有接触过企业级别开发的大学生更不用说,因此尝试写一篇我如何从小白实现微信小程序支付功能的吧,使用的后端是 SpringBoot 。 2.准备工作 首先,要实现支付功能

    2024年02月04日
    浏览(68)
  • springboot实现微信小程序V3微信支付功能

    appId:小程序appid appSecret:小程序的secret mchId:商户号 keyPath:商户私钥路径(apiclient_key.pem) certPath:证书路径(apiclient_cert.pem) platFormPath:平台证书(cert.pem) 注 : 需要通过写程序生成平台证书(见v3Get()方法) apiKey3:apiv3密钥 serialnumber:商户证书序列号 notifyUrl:回调地

    2024年02月12日
    浏览(61)
  • 微信小程序 内容评论-回复评论-回复回复的实现(纯前端)

    输入框失去焦点时触发 如果你是点击输入框右边按钮才发送内容的话需要在输入框bindinput属性绑定以下方法获取用户输入的值

    2024年02月04日
    浏览(49)
  • springboot使用 WxJava 实现 微信小程序(uniapp开发)的登陆功能

    前端使用uniapp来开发微信小程序 后端springboot中使用WxJava来做服务端( WxJava是微信服务端开发 的Java SDK ) 该图来源于微信小程序官方文档 根据uniapp的官网直接通过它提供的第三方 登陆api直接使用,代码如下 直接根据WxJava的官方demo (1) yml配置 (2)两个配置文件 (3)contro

    2024年02月15日
    浏览(56)
  • uniapp+java/springboot实现微信小程序APIV3支付功能

    微信小程序的支付跟H5的支付和APP支付流程不一样,本次只描述下小程序支付流程。 1.微信小程序账号 文档:小程序申请 小程序支付需要先认证,如果你有已认证的公众号,也可以通过公众号免费注册认证小程序。 一般300元,我是认证的政府的免费。 然后登录小程序,设置

    2023年04月19日
    浏览(47)
  • 微信小程序毕业设计作品成品(68)微信小程序电视剧电影影视评论系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(55)
  • 基于微信小程序电影影视点评评论系统设计与实现

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年04月27日
    浏览(42)
  • SpringBoot对接微信小程序支付功能开发(一,下单功能)

    1,接入前准备: 接入模式选择直连模式; 申请小程序,得到APPID,并开通微信支付; 申请微信商户号,得到mchid,并绑定APPID; 配置商户API key,下载并配置商户证书,根据微信官方文档操作:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml 上面都配置完之后会得到:小

    2024年02月10日
    浏览(64)
  • SpringBoot对接微信小程序支付功能开发(二,支付回调功能)

    接着上一篇: SpringBoot对接微信小程序支付功能开发(一,下单功能) 在上一篇下单功能中我们有传支付结果回调地址。 下面是回调接口实现 根据官网给的参数进行业务处理 这就完成了,微信支付回调你的地址,并且把支付的信息传进来,剩下就要根据自己业务进行操作。

    2024年02月11日
    浏览(65)
  • Vue+SpringBoot实现评论功能

    评论系统相信大家并不陌生,在社交网络相关的软件中是一种常见的功能。然而对于初学者来说,实现一个完整的评论系统并不容易。本文笔者以 Vue+SpringBoot 前后端分离的架构细说博客评论功能的实现思路。 对于一个评论系统主要包含评论人,评论时间,评论内容,评论回

    2023年04月08日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包