vue+springboot实现聊天功能

前言

在我的项目中,突然有种想法,想实现聊天功能,历经一段时间终于做出来了;那么接下来会讲解如何实现,这篇文章只会实现最基础的逻辑,实时获取对方聊天记录,话不多说,我们就开始吧

实际项目演示

我的项目中,分为了两部分,一部分为用户区,一部分为聊天区

🍁🍁🍁🍁🍁🍁🍁

在这里插入图片描述

🌰🌰🌰🌰🌰🌰🌰

用户区,通过回车获取指定用户名称的用户
ps:这里可根据自己的需求直接获取所有人员或者在线人员的数据

在这里插入图片描述
当点击对应用户,可获取对应用户和自己的聊天记录

己方视角:

在这里插入图片描述
对方视角
在这里插入图片描述

建表

我的项目中连接的是mysql数据库,对应建表有如下:

用户信息表

CREATE TABLE `user` (
  `user_id` varchar(20) NOT NULL COMMENT '用户id',
  `avatar` longtext COMMENT '头像',
  `user_name` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `salt` varchar(128) DEFAULT NULL COMMENT '加密盐值',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `phone` varchar(50) DEFAULT NULL COMMENT '联系方式',
  `sex` varchar(50) DEFAULT NULL COMMENT '性别',
  `age` int(3) DEFAULT NULL COMMENT '年龄',
  `status` int(1) NOT NULL COMMENT '用户状态:1有效; 0删除',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

发送信息表

CREATE TABLE `message` (
  `handle` varchar(40) NOT NULL COMMENT '主键',
  `send_user` varchar(20) DEFAULT NULL COMMENT '发送人',
  `receive_user` varchar(20) DEFAULT NULL COMMENT '接收人',
  `content` varchar(500) DEFAULT NULL COMMENT '留言内容',
  `is_read` tinyint(1) DEFAULT '0' COMMENT '是否已读',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '留言时间',
  PRIMARY KEY (`handle`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='留言板';

其中有一点,为了能够发送emoji表情,如😂😃😍😘等等一系列数据,需要将我们的数据库设置为utf8mb4类型,以及对应接收发送信息的表字段设置为utf8mb4类型

设置数据库

 ALTER DATABASE 数据库名称 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

设置指定表字段

ALTER TABLE 表名 MODIFY 字段名称 VARCHAR(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

以上,我们就满足了我们最最基础的聊天功能了

🍉🍊🍋🍉🍊🍋🍉🍊🍋

前端

依赖安装

在开始之前,请安装相关依赖

npm i axios@1.5.0
npm i element-ui -S

mian.js

主入口逻辑

// 如下省略router
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false

Vue.use(ElementUI)
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

request.js

axios封装类

import axios from 'axios'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 请求超时时间 withCredentials: true,
  timeout: 30000
})

// 请求统一拦截处理
service.interceptors.request.use(config => {
  return config
},
error => {
  // 请求失败
  console.log(error) // for debug
  return Promise.reject(error)
}
)

// 响应拦截器
service.interceptors.response.use(res => {
  console.log('res.data', res.data)
}, error => {
  return Promise.reject(error)
}
)

export default service

axios调用后端js

封装需要的方法

user.js

// 位置换成自己项目位置
import request from '@/utils/request'

// 根据用户名查用户
export function searchUserByUserName (userName) {
  return request({
    url: '/user/searchUserByUserName',
    method: 'get',
    params: {
      userName
    }
  })
}

message.js

import request from '@/utils/request'

// 发送信息
export function sendMessage (data) {
  return request({
    url: '/message/sendMessage',
    method: 'post',
    data: data
  })
}

// 根据发送用户和接收用户获取聊天记录
export function findMessageBySendUserAndReceiveUser (sendUserId, receiveUserId) {
  return request({
    url: '/message/findMessageBySendUserAndReceiveUser',
    method: 'get',
    params: {
      sendUserId,
      receiveUserId
    }
  })
}

聊天界面逻辑

界面

<template>
  <div class="chat-container">
    <!-- Left side: User list -->
    <div class="left-side">
      <!-- Search input (moved outside) -->
      <div class="search-wrapper">
        <el-input v-model="searchUserName" placeholder="回车搜索用户" class="search-input" @keydown.enter.native="searchUsers"></el-input>
      </div>
      <!-- User list (with scroll) -->
      <el-scrollbar class="user-list-scroll">
        <el-menu>
          <el-menu-item v-for="user in filteredUsers" :key="user.id" @click="chooseUser(user)" class="user-item">
            <el-avatar :src="user.avatar" size="medium"></el-avatar>
            <span>{{ user.userName }}</span>
            <span slot="title">{{ user.lastMessage }}</span>
          </el-menu-item>
        </el-menu>
      </el-scrollbar>
    </div>
    <!-- Right side: Chat box -->
    <div class="right-side">
      <!-- Chat header -->
      <div class="chat-header">
        <span v-if="currentUser">{{ currentUser.userName }}</span>
      </div>
      <!-- Chat messages -->
      <el-scrollbar class="chat-messages">
        <div class="messageBox" v-for="message in messages" :key="message.handle" :class="{ ownMessage: message.sendUser === loginUserId, otherMessage: message.sendUser !== loginUserId }">
          <div><img :src="message.sendUser === loginUserId ? loginUser.avatar : currentUser.avatar" alt=""></div>
          <div class="messageContent">{{ message.content }}</div>
          <!-- 这里逻辑我是为了时间格式化,请按照自己项目实际修改 -->
          <div class="messageTime">{{ message.createTime.replace('T', ' ') }}</div>
        </div>
      </el-scrollbar>
      <div class="chat-input">
        <el-input v-model="newMessage.content" placeholder="请输入聊天内容" autosize class="message-input"></el-input>
        <el-button type="primary" @click.native="sendMessage" class="send-button">发送</el-button>
      </div>
    </div>
  </div>
</template>

js逻辑

<script>
import {searchUserByUserName} from '../pc/../../api/user'
import {findMessageBySendUserAndReceiveUser, sendMessage} from '../pc/../../api/message'

export default {
  data () {
    return {
      intervalId: null, // 定时调用,实现实时获取聊天记录
      users: [],
      filteredUsers: [],
      currentUser: null, // 当前聊天人员用户信息
      loginUser: null, // 登录人员用户信息
      messages: [],
      newMessage: {
        handle: '',
        sendUser: '',
        receiveUser: '',
        content: '',
        is_read: '0',
        createTime: ''
      },
      loginUserId: '', // 登录人员userId
      searchUserName: '',
    }
  },
  methods: {
    async fetchMessages (userId) {
    // 传当前聊天人员的userId
      if (!userId) {
        return
      }
      if (this.loginUserId== null) {
        this.$message.error('登录用户编号获取失败,请重新登录!')
        return
      }
      findMessageBySendUserAndReceiveUser(userId, localCommon.userInfo.userId).then(res => {
        console.log('消息记录', res)
        if (res.header.code !== 0) {
          this.$message.error(res.header.message)
          return
        }
        // 赋值最终的聊天信息,根据自己项目调整赋值
        this.messages = res.value
      })
    },
    sendMessage () {
      if (!this.newMessage.content.trim()) {
        this.$message.warning('请输入聊天内容')
        return
      }
      if (this.loginUserId== null) {
        this.$message.error('登录用户编号获取失败,请重新登录!')
        return
      }
      this.newMessage.sendUser = this.loginUserId
      this.newMessage.receiveUser = this.currentUser.userId
      console.log('需要发送信息', this.newMessage)
      sendMessage(this.newMessage).then(res => {
        console.log('发送信息:', res)
        if (res.header.code !== 0) {
          this.$message.error(res.header.message)
          return
        }
        // 发送完之后获取聊天记录更新
        this.chooseUser(this.currentUser)
      })
    },
    // 设置不同用户的头像
    checkAvatar (message) {
      if (message.sendUser === this.loginUserId) {
        console.log('发送人头像:', this.currentUser)
        return this.currentUser.avatar
      } else {
        console.log('登录人头像:', this.loginUser)
        return this.loginUser.avatar
      }
    },
    chooseUser (user) {
      this.currentUser = user
      this.fetchMessages(user.userId)
    },
    searchUsers () {
      if (!this.searchUserName) {
        this.$message.error('用户名不能为空!')
        return
      }
      searchUserByUserName(this.searchUserName).then(res => {
        console.log('搜索用户:', res)
        if (res.header.code !== 0) {
          this.$message.error(res.header.message)
          return
        }
        this.filteredUsers = res.value
      })
    },
  },
  mounted () {
  // 定时自动
    this.intervalId = setInterval(() => {
      this.fetchMessages(this.currentUser.userId)
    }, 3000)
  },
  destroyed () {
    // 在组件销毁前清除定时器,防止内存泄漏
    clearInterval(this.intervalId)
  },
  created () {
  // 通过登录人的userId获取用户信息
      searchUserByUserName(this.loginUserId).then(res => {
        if (res.header.code === 0) {
          if (res.value) {
            this.loginUser = res.value[0]
          }
        }
      })
  }
}
</script>

以上的登录人userId,请根据自己实际项目进行赋值
✨✨✨✨✨✨

样式

<style scoped>
.chat-container {
  display: flex;
  height: 100%;
  background: linear-gradient(to bottom right, #FFFFFF, #ECEFF1);
}

.left-side {
  position: relative; /* Position relative for absolute positioning */
  flex: 1;
  padding: 20px;
  border-right: 1px solid #eaeaea;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.search-input {
  position: absolute;
  top: 20px;
  left: 20px;
  width: calc(100% - 40px);
  max-width: 300px;
}

.user-list-scroll {
  top: 40px;
  height: calc(100% - 40px);
  overflow-y: auto;
}

.right-side {
  flex: 3;
  display: flex;
  flex-direction: column;
}

.chat-header {
  padding: 20px;
  border-bottom: 1px solid #eaeaea;
  font-size: 1.2em;
  color: #37474F;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}
.chat-input {
  padding: 20px;
  display: flex;
  align-items: center;
}

.message-input {
  flex: 1;
  margin-right: 10px;
}

.send-button {
  flex-shrink: 0;
}

.user-item {
  display: flex;
  align-items: center;
  padding: 10px;
}

.user-item:hover {
  background-color: #E0E0E0;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.user-item .el-avatar {
  margin-right: 10px;
}

.user-item .el-list-item-content {
  flex: 1;
}
.editor {
  border-radius: 5px;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
.search-input {
  position: relative;
  z-index: 999;
}

.messageBox {
  display: flex;
  align-items: flex-start; /* 将头像和文本第一行对齐 */
  margin-bottom: 10px;
}

.messageBox img {
  width: 40px; /* 调整头像大小 */
  height: 40px;
  border-radius: 50%;
  margin-right: 10px;
  margin-left: 10px;
}

.messageContent {
  max-width: 70%; /* 调整发送信息宽度 */
  padding: 10px;
  border-radius: 8px;
  background-color: #f0f0f0;
  text-align: left; /* 文本左对齐 */
  word-wrap: break-word; /* 当文本过长时自动换行 */
}

.messageTime {
  font-size: 12px;
  color: #999;
  margin-left: 10px;
  margin-top: 5px; /* 将发送时间与文本分隔开 */
}

.ownMessage {
  flex-direction: row-reverse;
  align-items: flex-end; /* 将发送时间放置在最下方的贴右位置 */
}

.otherMessage {
  flex-direction: row;
  align-items: flex-end; /* 将发送时间放置在最下方的贴左位置 */
}
</style>

后端

pom.xml

如下是我项目中的pom依赖,根据实际项目引入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.pearl</groupId>
  <artifactId>SsoSystemApplication</artifactId>
  <version>1.0.0</version>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.2</version>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!--    工具类-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.12.0</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.76</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.3.8</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.18</version>
      <optional>true</optional>
    </dependency>
    <!--    swagger-->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
    </dependency>
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
    </dependency>
    <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>swagger-bootstrap-ui</artifactId>
      <version>1.9.6</version>
    </dependency>
    <!-- jwt支持 -->
    <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.4.0</version>
    </dependency>
    <!--    mysql数据库驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.26</version> <!-- 使用最新版本 -->
    </dependency>
    <!--    alibaba-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.16</version>
    </dependency>
    <!--    单元测试-->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.8.1</version> <!-- 根据需要调整版本 -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
<!--    webSocket-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
<!--    -->
    <dependency>
      <groupId>org.glassfish.tyrus</groupId>
      <artifactId>tyrus-server</artifactId>
      <version>1.17</version> <!-- 根据需要选择版本 -->
    </dependency>
  </dependencies>


  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <mainClass>com.pearl.SsoSystemApplication</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>

</project>

application.yml

对应的数据库连接逻辑需要调整为如下:

spring:
  datasource:
    mysql:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=false&rewriteBatchedStatements=true&useCompression=false&useSSL=false
      username: 账号
      password: 密码
      druid:
        connection-init-sqls: set names utf8mb4 # 初始化为utf8mb4
        

查询用户接口

实际上这个接口对于你们需要用的没有参考价值,需要根据自己的实际项目调整的,但是这边也给出代码示例

controller

  @GetMapping("/searchUserByUserName")
  public Response searchUserByUserId(@RequestParam("userName") String userName) {
    try (Connection conn = primeDB.create()) {
      return new Response(0, userService.searchUserByUserId(conn, userName), "检索成功!");
    } catch (Exception e) {
      return new Response(1, e.getMessage());
    }
  }

service

  public List<User> searchUserByUserId(Connection conn, String userName) throws Exception {
    try {
      AssertUtils.isError(StringUtils.isEmpty(userName), "用户编号不能为空!");
      // 我的项目的数据库连接代码
      UserDao userDao = new UserDao(conn);
      List<User> userList = userDao.selectByUserName(userName);
      // 只查有效状态账号的数据
      List<User> filteredUserList = userList.stream().filter(o -> o.getStatus() == 1).collect(
          Collectors.toList());
      return filteredUserList;
    } catch (Exception e) {
      throw new Exception(e.getMessage());
    }
  }

信息发送逻辑

controller

  @PostMapping("/sendMessage")
  public Response sendMessage(@RequestBody Message message) {
    try (Connection conn = primeDB.create()) {
      messageService.sendMessage(conn, message);
      return new Response(0, "发送成功!");
    } catch (Exception e) {
      return new Response(1, e.getMessage());
    }
  }

  @GetMapping("/findMessageBySendUserAndReceiveUser")
  public Response<List<Message>> findMessageBySendUserAndReceiveUser(
      @RequestParam("sendUserId") String sendUserId,
      @RequestParam("receiveUserId") String receiveUserId) {
    try (Connection conn = primeDB.create()) {
      return new Response<>(0,
          messageService.findMessageBySendUserAndReceiveUser(conn, sendUserId, receiveUserId),
          "查找成功!");
    } catch (Exception e) {
      return new Response<>(1, e.getMessage());
    }
  }

service

// 发送信息逻辑,请根据自己实际项目调整
  public void sendMessage(Connection conn, Message message) throws Exception {
    try {
      AssertUtils.isError(StringUtils.isEmpty(message.getSendUser()), "发送用户不能为空!");
      AssertUtils.isError(StringUtils.isEmpty(message.getReceiveUser()), "接收用户不能为空!");
      AssertUtils.isError(StringUtils.isEmpty(message.getContent()), "发送信息不能为空!");
      UserDao userDao = new UserDao(conn);
      MessageDao messageDao = new MessageDao(conn);
      User sendUser = userDao.selectbyUserId(message.getSendUser());
      AssertUtils.isError(null == sendUser, "发送用户不存在,发送信息失败!");
      AssertUtils.isError(sendUser.getStatus() != 1,
          "发送用户:" + message.getSendUser() + "状态已冻结,无法发送信息!");
      User receiveUser = userDao.selectbyUserId(message.getReceiveUser());
      AssertUtils.isError(null == receiveUser, "接收用户不存在,发送信息失败!");
      AssertUtils.isError(receiveUser.getStatus() != 1,
          "接收用户:" + message.getReceiveUser() + "状态已冻结,无法接收信息!");
      message.setHandle(UUID.randomUUID().toString());
      message.setIsRead("0");
      message.setCreateTime(LocalDateTime.now());
      messageDao.insert(message);
    } catch (Exception e) {
      throw new Exception(e.getMessage());
    }
  }

// 获取两个用户之间的聊天记录
  public List<Message> findMessageBySendUserAndReceiveUser(Connection conn, String sendUserId,
      String receiveUserId) throws Exception {
    try {
      AssertUtils.isError(StringUtils.isEmpty(sendUserId), "发送用户为空!");
      AssertUtils.isError(StringUtils.isEmpty(receiveUserId), "接收用户为空!");
      UserDao userDao = new UserDao(conn);
      User sendUser = userDao.selectbyUserId(sendUserId);
      AssertUtils.isError(null == sendUser, "发送用户不存在,发送信息失败!");
      User receiveUser = userDao.selectbyUserId(receiveUserId);
      AssertUtils.isError(null == receiveUser, "接收用户不存在,发送信息失败!");
      MessageDao messageDao = new MessageDao(conn);
      // 获取对方发送的信息,限制指定条数,防止聊天数量太多查询很慢
      List<Message> receiveMessageList = messageDao.selectBySendUserAndReceiveUserLimitLength(
          sendUserId,
          receiveUserId, 100);
      // 获取发送给对方的信息
      List<Message> sendMessageList = messageDao.selectBySendUserAndReceiveUserLimitLength(
          receiveUserId,
          sendUserId, 100);
      List<Message> allMessageList = new ArrayList<>();
      allMessageList.addAll(receiveMessageList);
      allMessageList.addAll(sendMessageList);
      // 将两个用户互相发送给对方的信息放到集合按照时间排序,即可实现聊天交互逻辑
      List<Message> sortedMessageList = allMessageList.stream()
          .sorted(Comparator.comparing(Message::getCreateTime))
          .collect(Collectors.toList());

      return sortedMessageList;
    } catch (Exception e) {
      throw new Exception(e.getMessage());
    }
  }

以上我们的基础的聊天功能就实现好了,可喜可贺🎉🎉🎉

最后

以上,如一开头所说,只实现了最基础的聊天功能

其实还能够做优化,如

  1. 用户区展示最新聊天记录
  2. 设置聊天记录已读未读
  3. 聊天内容是否可发图片 or 其他内容

    等等一系列调整,这边就不多赘述,给出基础的聊天逻辑供参考

🎈🎈🎈🎈🎈🎈

结语

以上为vue+springboot实现聊天功能,后面计划开一篇文章讲解如何通过websocket来进行实时通讯,来实现聊天功能

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Vue前端框架)和Spring Boot后端框架)结合起来实现websocket双工通信的步骤如下: 1. 首先,在Vue项目中安装`vue-native-websocket`插件。这个插件能够帮助我们在Vue中使用websocket。 2. 在Vue项目的根目录下创建一个文件,例如`webSocket.js`,在这个文件中,引入`vue-native-websocket`插件,并配置websocket服务的地址和端口号。 3. 在Vue项目的入口文件(例如`main.js`)中,引入`webSocket.js`文件,并将websocket插件注册到Vue实例中。 4. 在Vue组件中,使用`this.$socket`来访问websocket对象。可以使用`this.$socket.send()`方法发送消息给后端。 5. 在Spring Boot项目中,添加`spring-boot-starter-websocket`的依赖。 6. 创建一个继承自`WebSocketConfigurer`接口的类,并实现其中的`registerWebSocketHandlers`方法。在该方法中,注册一个`WebSocketHandler`来处理前端后端的websocket连接和消息传递逻辑。 7. 在`WebSocketHandler`中,重写`handleTextMessage`方法来处理接收到的文本消息。可以在这个方法中进行消息的处理逻辑,例如广播消息给所有连接的客户端。 8. 在Spring Boot的配置类(例如`Application.java`)中,添加`@EnableWebSocket`来启用websocket支持。 9. 启动Spring Boot项目,并运行Vue项目。此时,前端可以使用websocket连接到后端,并进行双工通信。前端可以通过`this.$socket.send()`方法发送消息给后端后端可以通过`WebSocketHandler`接收处理并响应消息给前端。 以上就是使用VueSpring Boot实现websocket双工通信的基本步骤。通过这种方式,前端后端可以实时地进行双向通信,方便实现一些实时推送、聊天室等功能。 ### 回答2: VueSpring Boot结合实现WebSocket双工通信的步骤如下: 1. 在Vue项目中安装Vue-socket.io插件,可以在Vue项目的根目录下运行以下命令进行安装: ``` npm install --save vue-socket.io ``` 2. 在Vue项目的main.js文件中引入Vue-socket.io插件,并配置socket连接: ```javascript import VueSocketIO from 'vue-socket.io' import SocketIO from 'socket.io-client' Vue.use(new VueSocketIO({ debug: true, connection: SocketIO('http://localhost:8080'), // 这里的地址需要修改为后端的IP地址和端口号 })) ``` 3. 在Vue组件中使用WebSocket进行通信,例如,在Vue组件的created钩子中: ```javascript created() { this.$socket.emit('register', { userId: 123 }) // 发送注册消息给后端 this.$socket.on('message', (data) => { // 监听后端发送的消息 console.log('收到消息:', data) }) } ``` 4. 在Spring Boot中编写WebSocket后端控制器,处理前端发送的消息,并实现双工通信,例如: ```java @Controller public class WebSocketController { @Autowired private SimpMessagingTemplate messagingTemplate; @MessageMapping("/register") public void registerUser(@Payload Map<String, Long> payload) { // 处理注册逻辑,例如保存用户ID等 Long userId = payload.get("userId"); // 广播消息给所有连接的用户 messagingTemplate.convertAndSend("/topic/message", "用户 " + userId + " 加入了聊天室"); } // 其他接口处理逻辑... } ``` 5. 在Spring Boot中配置WebSocket相关的bean,例如,在配置类中添加以下配置: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); // 消息代理前缀 registry.setApplicationDestinationPrefixes("/app"); // 应用消息前缀 } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); } } ``` 以上是VueSpring Boot实现WebSocket双工通信的基本步骤,当前端发送消息到后端时,后端可以处理并向所有连接的客户端发送广播消息,实现实时的双工通信。 ### 回答3: VueSpring Boot均提供了支持WebSocket的功能,通过结合VueSpring Boot,我们可以实现WebSocket双工通信。 首先,在Vue项目中使用Vue提供的WebSocket API建立与后端的WebSocket连接,可以使用Vue的mounted生命周期钩子函数来实现这一步骤。通过WebSocket连接后,我们可以使用Vue的WebSocket对象来发送数据给后端,同时监听后端的数据。 在后端,我们使用Spring Boot提供的WebSocket支持来处理前端的请求。首先,在Spring Boot的配置文件中,我们需要开启WebSocket功能。然后,我们可以通过创建一个WebSocketHandler类来处理前端的请求和发送消息给前端。在WebSocketHandler中,我们可以实现OnOpen、OnMessage、OnClose等方法来处理前端的连接、接收消息和关闭连接。在接收到消息后,我们可以编写相应的业务逻辑,如处理前端发送的数据,然后将处理结果发送给前端。 通过上述步骤,我们实现VueSpring Boot的WebSocket双工通信。前端可以通过Vue的WebSocket对象与后端进行实时的双向通信,后端可以处理前端的请求并发送相应的消息给前端。这使得实时的数据交互和通信成为可能,为应用程序添加了更多实时性和交互性。 需要注意的是,在实现WebSocket通信时,我们需要确保VueSpring Boot的版本兼容,并且正确配置相关的依赖和配置文件。同时,我们还需要考虑到安全性和性能等方面的因素,如认证和授权、连接数限制等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值