当前位置:   article > 正文

聊天广场(Vue+WebSocket+SpringBoot)

聊天广场(Vue+WebSocket+SpringBoot)

由于心血来潮想要做个聊天室项目 ,但是仔细找了一下相关教程,却发现这么多的WebSocket教程里面,很多都没有介绍详细,代码都有所残缺,所以这次带来一个比较完整得使用WebSocket的项目。

目录

一、效果展示

二、准备工作

一、前端框架,Vue + elementUI组件 +JsCookie

二、后端 SpringBoot + websocket包

三、前端代码

四、后端代码


一、效果展示

1.用户交流


二、准备工作

一、前端框架,Vue + elementUI组件 +JsCookie

新建一个vue项目

引入以下组件与依赖

npm i element-ui -S
npm install js-cookie

二、后端 SpringBoot + websocket包

创建SpringBoot项目后

在pom.xml文件中引入以下依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-websocket</artifactId>
  4. </dependency>

注意项目前端为8081端口,后端为8080端口,所以先运行后端再运行前端


三、前端代码

在App.vue中即可引入以下代码:

html:

  1. <template>
  2. <div id="Layout">
  3. <el-container>
  4. <el-aside width="200px">Aside</el-aside>
  5. <el-container>
  6. <el-header style="background-color: rgb(245, 245, 245); border-bottom: 1px solid grey;">
  7. <h3>聊天广场</h3>
  8. </el-header>
  9. <el-main style="background-color: rgb(244, 245, 247);
  10. min-height: 700px; max-height: 700px; ">
  11. <div id="chatContent" style="padding-left: 10px; line-height: normal; ">
  12. <!-- 循环输出对话内容 -->
  13. <el-scrollbar v-for="(message, index) in messages" :key="index">
  14. <div ref="scrollbar" v-if="message.sender !== senderName" class="chat-message" id="ChatContentCard" style=" background-color: white;
  15. margin-top: 20px;
  16. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
  17. ">
  18. <el-avatar :size="40"
  19. src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar>
  20. <div class="message-content" style="width: 100%;">
  21. <div style="text-align: left; text-indent: 1em;"> {{ message.sender }}</div>
  22. <div id="chatContentText">{{ message.text }}</div>
  23. </div>
  24. </div>
  25. <div ref="scrollbar" v-if="message.sender === senderName" id="myChatContentCard">
  26. <el-avatar :size="40"
  27. src="https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"></el-avatar>
  28. <div class="message-content" style="width: 100%;">
  29. <div style="text-align: left; text-indent: 1em;"> {{ message.sender }}</div>
  30. <div id="chatContentText">{{ message.text }}</div>
  31. </div>
  32. </div>
  33. </el-scrollbar>
  34. </div>
  35. </el-main>
  36. <!-- 底层交互框 -->
  37. <el-footer style="height: 190px; background-color: rgb(244, 245, 247); ">
  38. <div id="Gadget" style="background-color: rgb(244, 245, 247); height: 35px; margin-bottom: 10px;">
  39. <el-upload class="upload-demo" ref="upload" action="https://jsonplaceholder.typicode.com/posts/"
  40. :on-preview="handlePreview" :on-remove="handleRemove" :file-list="fileList" :auto-upload="false" style="float: left;">
  41. <el-button slot="trigger" size="small" type="primary"><i class="el-icon-picture-outline-round"></i></el-button>
  42. <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
  43. </el-upload>
  44. </div>
  45. <el-form @submit.native.prevent="sendMessage"
  46. style="background-color: rgb(244, 245, 247); height: 80%; width: 100%; position: relative;">
  47. <el-input v-model="messageInput" rows="4" resize="none" type="textarea" placeholder="请输入内容......."
  48. @keyup.enter="sendMessage" style="height: 100%; max-height: 60px; ">
  49. </el-input>
  50. <div style="text-align: right; background-color: rgb(244, 245, 247); margin-top: 34px;">
  51. <el-button type="primary" @click="sendMessage">发送</el-button>
  52. </div>
  53. </el-form>
  54. </el-footer>
  55. </el-container>
  56. </el-container>
  57. </div>
  58. </template>

script:

  1. <script>
  2. import Cookies from 'js-cookie';
  3. export default {
  4. computed: {
  5. senderName() {
  6. return Cookies.get('account') || '游客';
  7. }
  8. },
  9. name: 'App',
  10. data() {
  11. return {
  12. messages: [],
  13. messageInput: '',
  14. ws: null,
  15. fileList: []
  16. };
  17. },
  18. mounted() {
  19. this.initWebSocket();
  20. },
  21. beforeDestroy() {
  22. this.closeWebSocket();
  23. },
  24. methods: {
  25. initWebSocket() {
  26. this.ws = new WebSocket('ws://localhost:8080/chat');
  27. this.ws.onopen = () => {
  28. console.log('Connected to server.');
  29. };
  30. this.ws.onmessage = (event) => {
  31. try {
  32. let messageData;
  33. if (isJson(event.data)) {
  34. messageData = JSON.parse(event.data);
  35. } else {
  36. messageData = { text: event.data };
  37. }
  38. this.messages.push({
  39. sender: messageData.sender || 'Anonymous',
  40. text: messageData.text,
  41. });
  42. // 使用Vue.nextTick确保DOM更新后再执行滚动操作
  43. this.$nextTick(() => {
  44. // 确保scrollbar存在且已渲染
  45. if (this.$refs.scrollbar) {
  46. // 直接滚动到底部,不需要使用contentSize
  47. // this.$refs.scrollbar.$el.scrollTop = this.$refs.scrollbar.$el.scrollHeight;
  48. }
  49. });
  50. } catch (error) {
  51. console.error('Error parsing message:', error);
  52. }
  53. };
  54. // 辅助函数,检查字符串是否可能是JSON格式
  55. function isJson(str) {
  56. try {
  57. JSON.parse(str);
  58. } catch (e) {
  59. return false;
  60. }
  61. return true;
  62. }
  63. this.ws.onerror = (error) => {
  64. console.error('WebSocket error:', error);
  65. };
  66. this.ws.onclose = () => {
  67. console.log('Disconnected from server.');
  68. };
  69. },
  70. sendMessage() {
  71. console.log('调用sendMessage');
  72. const senderName = Cookies.get('account');
  73. if (senderName === null) {
  74. this.senderName = "游客";
  75. }
  76. if (this.messageInput.trim() !== '') {
  77. this.ws.send(JSON.stringify({ sender: senderName, text: this.messageInput }));
  78. this.messageInput = ''; // 清空输入框
  79. }
  80. },
  81. closeWebSocket() {
  82. if (this.ws && this.ws.readyState === WebSocket.OPEN) {
  83. this.ws.close();
  84. }
  85. },
  86. // 文件上传函数
  87. submitUpload() {
  88. this.$refs.upload.submit();
  89. },
  90. handleRemove(file, fileList) {
  91. console.log(file, fileList);
  92. },
  93. handlePreview(file) {
  94. console.log(file);
  95. }
  96. },
  97. };
  98. </script>

css:

  1. <style scoped>
  2. .chat-message {
  3. display: flex;
  4. align-items: center;
  5. margin-bottom: 10px;
  6. }
  7. .message-content {
  8. margin-left: 10px;
  9. }
  10. #Layout {
  11. line-height: normal;
  12. }
  13. /* 添加动画关键帧 */
  14. @keyframes slideInFromLeft {
  15. 0% {
  16. transform: translateX(-100%);
  17. opacity: 0;
  18. }
  19. 100% {
  20. transform: translateX(0);
  21. opacity: 1;
  22. }
  23. }
  24. #ChatContentCard {
  25. min-height: 80px;
  26. width: 50%;
  27. /* 应用动画 */
  28. animation: slideInFromLeft 0.3s ease-in-out forwards;
  29. border-radius: 30px
  30. }
  31. #chatContentText {
  32. width: 99%;
  33. overflow-wrap: break-word;
  34. }
  35. .el-header,
  36. .el-footer {
  37. background-color: #B3C0D1;
  38. color: #333;
  39. text-align: center;
  40. line-height: 60px;
  41. }
  42. .el-aside {
  43. background-color: #D3DCE6;
  44. color: #333;
  45. text-align: center;
  46. line-height: 200px;
  47. }
  48. .el-main {
  49. background-color: #E9EEF3;
  50. color: #333;
  51. text-align: center;
  52. line-height: 160px;
  53. }
  54. body>.el-container {
  55. margin-bottom: 40px;
  56. }
  57. .el-container:nth-child(5) .el-aside,
  58. .el-container:nth-child(6) .el-aside {
  59. line-height: 260px;
  60. }
  61. .el-container:nth-child(7) .el-aside {
  62. line-height: 320px;
  63. }
  64. #myChatContentCard{
  65. display: flex;
  66. align-items: center;
  67. margin-bottom: 10px;
  68. margin-left: 50%;
  69. min-height: 80px;
  70. width: 50%;
  71. /* 应用动画 */
  72. animation: slideInFromRight 0.3s ease-in-out forwards;
  73. border-radius: 30px;
  74. background-color: rgb(149, 236, 105);
  75. margin-top: 20px;
  76. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
  77. }
  78. @keyframes slideInFromRight {
  79. 0% {
  80. transform: translateX(100%);
  81. opacity: 0;
  82. }
  83. 100% {
  84. transform: translateX(0);
  85. opacity: 1;
  86. }
  87. }
  88. </style>

注意: 这个项目中如果script需要进行修改,由于我这里完成了一个登陆系统,所以采用了对Cookie的使用,而如果只是体验的话,只需要把Cookie去掉将其改为游客+随机字符串去替代即可。

前端启动

npm run serve


四、后端代码

WebSocket配置:

1.WebSocketConfig.java

  1. @Configuration
  2. @EnableWebSocket
  3. public class WebSocketConfig implements WebSocketConfigurer {
  4. @Override
  5. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
  6. registry.addHandler(new ChatWebSocketHandler(), "/chat").setAllowedOrigins("*");
  7. }
  8. }

 2.ChatWebSocketHandler.java

  1. @Slf4j
  2. public class ChatWebSocketHandler extends TextWebSocketHandler {
  3. private static final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());
  4. @Override
  5. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  6. sessions.add(session);
  7. broadcast("欢迎新的小伙伴加入");
  8. }
  9. @Override
  10. protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
  11. broadcast(message.getPayload());
  12. }
  13. private void broadcast(String message) {
  14. log.info("服务器广播数据:"+message);
  15. sessions.forEach(session -> {
  16. try {
  17. session.sendMessage(new TextMessage(message));
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. });
  22. }
  23. @Override
  24. public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
  25. sessions.remove(session);
  26. }
  27. }

 后端启动:

 


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/795382
推荐阅读
相关标签
  

闽ICP备14008679号