springboot vue零食商城实战开发教程 实现websocket对话功能

大家好,最近有同学问能不能写写商城系统的实战开发,最好项目能有亮点。商城功能亮点的话可以加协同过滤算法,加沙箱支付,也可以考虑实现与商家的对话功能。

于是写了一个零食商城项目,分享下重点功能实现的过程,也录制了此商城项目实战开发视频,希望能对同学们的学习有点帮助。

角色设计

很多同学写项目仍然会选择两个角色,都2025年了,大家可以多去参考目前的商城系统,如某宝,某东,两个角色目前来说太单调了,可以在管理员,用户的基础上添加一个商家的角色,有不同的店铺信息,功能也会丰富一点。

商品功能

基于三个角色,功能也比较清晰了,商家管理商品,商品在添加时可以做以下两点调整。

很多同学商品名称依然使用简短的几个字如【可乐】,【雪碧】等,但在真实电商平台中没有这样写名称的,真实使用的名称是【可乐原味碳酸饮料整箱批发24罐330ml特价爆款无糖汽水】。

鼠标放上去能直接显示文字,这个用element ui 中标签实现。

ini 复制代码
<el-tooltip :content="item.name" placement="top-start" >
  <p  class="name">{{item.name}}</p>
</el-tooltip>

在商品详情页部分,很多项目直接不写,或者几个字,但在真实平台中介绍的很详细,多张图文形式显示,可以考虑使用富文本编辑器

实现的效果也会好很多。

富文本编辑器怎么使用呢?可以去看看wangeditor编辑器官网看看,网上也有很多视频教程,初始化编辑器代码如下。

kotlin 复制代码
// 初始化编辑器
    initWangEditor(content) { //用户输入的文本作为参数传进函数。
      this.$nextTick(() => { //1.dom元素加载好后,先判断editor是否已经完成初始化,如果已经完成初始化,那么把editor销毁,清空。
        if (this.editor){
          this.editor.destroy();
          this.editor = null;
        }
        this.editor = new E('#editor') //2.新建一个editor,赋值给我们一开始定义的editor,并渲染在iD为#editor的元素里
        this.editor.config.placeholder = '请输入内容' // 配置编辑器默认展示的文本
        this.editor.config.uploadFileName = 'file' //配置编辑器文件上传的名称
        this.editor.config.uploadImgServer = 'http://localhost:9090/files/wang/upload'  //配置编辑器文件上传的接口
        this.editor.create() //执行创建编辑器
        setTimeout(() => { //延时函数,这里没有设置延时时间,即为实时获取编辑器的文本给到this.editor.txt.html()。
          this.editor.txt.html(content)
        })
      })
    },

商品详情

这一部分也是参考真实平台写的,比只有两三个字段的商品界面是不是会好些呢?数量这一部分使用的是element ui中的计数器。element ui框架也比较好用,能比html减少很多代码。

个人中心功能

可以将个人的很多功能放在个人中心部分,购物车功能,收藏功能,收货地址,订单功能。

websocket对话功能

websocket功能是一种不同于http的通信方式,websocket使用最多的是两人聊天,多人聊天,前端就模仿某宝pc端写的,界面与核心代码如下。

typescript 复制代码
package com.example.springboot.common.config;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;

import com.example.springboot.entity.Chat;
import com.example.springboot.service.ChatService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket服务 - 单聊
 */
@ServerEndpoint(value = "/chatWebsocket")
@Component
public class WebSocketServer implements InitializingBean {
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    /**
     * 记录当前在线连接数
     */
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    @Resource
    ChatService chatService;
    static ChatService staticChatService;
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        sessionMap.put(session.getId(), session);
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        sessionMap.remove(session.getId());
    }
    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session fromSession) {
        log.info("服务端收到消息:{}", message);
        Chat chat = JSONUtil.toBean(message, Chat.class);//字符串转为java对象
        chat.setTime(DateUtil.now());
        chat.setIsRead(0);//0 表示未读 1 表示已读
        // 存储数据到数据库
           staticChatService.saveChat(chat);
        String jsonStr = JSONUtil.toJsonStr(chat);  // 处理后的消息体
        this.sendAllMessage(jsonStr);
        log.info("[onMessage] 发送消息:{}", jsonStr);
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("[onError] 发生错误", error);
    }
    /**
     * 服务端发送消息给除了自己的其他客户端
     */
    private void sendMessage(Session fromSession, String message) {
        sessionMap.values().forEach(session -> {
            if (fromSession != session) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    log.error("服务端发送消息给客户端异常", e);
                }
            }
        });
    }
    /**
     * 服务端发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
    @Override
    public void afterPropertiesSet() {
              staticChatService = chatService;
    }
}
相关推荐
Chenyiax2 分钟前
从一次请求看懂 OkHttp:架构、调度与连接管理
后端
爱勇宝1 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
AskHarries1 小时前
工具失败时怎么办:重试、回滚、人工确认和风险提示
后端·程序员
苏三说技术3 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎4 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode4 小时前
Redis 在生产项目的使用
前端·后端
用户559822481224 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode4 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战4 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha4 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端