【项目实战】-基于SpringBoot+WebScoket实现一个聊天程序

1.项目简介

基于浏览器和后端SpringBoot在WebScoket基础上实现一个简单的网页聊天程序

1.1 项目设计

  1. 需求分析(简单理解客户需求有什么功能达到什么效果)
  2. 概念设计阶段(原型设计、数据设计模型-ER图)
  3. 详细设计阶段(UML设计图-用例图、时序图)
  4. 编码阶段(技术选型、基础架构做好)
  5. 软件测试阶段(黑盒、白盒测试-接口压力测试、并发编程测试)
  6. 项目部署–软件开发闭环

1.1 技术选型

  1. 前端: HTML+CSS+JavaScript 工具:VSCode
  2. 服务端:SpringBoot+WebScoket

2. 实现效果概述

3. 用例、时序展示

4. 框架构建实现

4.1 后端实现

1. SpringBoot项目构建

1.java运行环境配置

1.java-bin路径配置到环境变量path中
在这里插入图片描述
2.java-jre-bin配置到环境变量path中
在这里插入图片描述
然后使用cmd打开,运行java指令和javac指令有内容输出就代表环境变量配置好了

2. maven
1. 进入maven官网

https://maven.apache.org/
在这里插入图片描述

在这里插入图片描述

2. 下载完成解压maven包,然后将bin路径配置到path系统环境变量中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykbKYWFz-1681262704532)(笔记图片/image-20230411152129522.png)]
在这里插入图片描述

3. maven修改conf目录下,settings.xml文件

在这里插入图片描述
修改本地仓库目录

<?xml version="1.0" encoding="UTF-8"?>


 
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository>本地仓库位置复制到这里</localRepository>
  <pluginGroups>
  
  </pluginGroups>
  
  <proxies>
  
  </proxies>
  
  <servers>
  
  </servers>
  
  <mirrors>
       <mirror>
            <id>nexus-aliyun</id>
            <mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </mirror> 
  </mirrors>
  
  <profiles>
  
  </profiles>
  
</settings>

3. 使用idea构建springboot项目

在这里插入图片描述
创建项目后点击设置,从新设置maven仓库位置
在这里插入图片描述
运行启动类
在这里插入图片描述在这里插入图片描述
出现上图效果代表项目启动成功!

如果需要修改端口号,在resources目录下有一个application.properties的全局配置文件

# 设置SpringBoot启动的端口号
server.port=9010

2. SpringBoot集成WebScoket

概述WebSocket

使用目的:能够使用TCP方式实现快速和客户端服务器之间简历长久的Socket通信
全双工通信,且为长链接
一般就是适用于终端机器(安卓、ios、鸿蒙)、客户端网页脚本快速和服务端通信技术。
解决HTTP问题:不适合使用在实时通信场景

在这里插入图片描述

webScoket封装好的三种场景
  1. 单播(Unicast)

    1对1发送

  2. 广播(BroadCast)

    1对所有发送

  3. 组播(Mulitcast)

    1对特定一群

3.springBoot引入WebSocket依赖

在这里插入图片描述

<!-- 服务端WebSocket需要的依赖 -->      
 <dependency>           
   <groupId>org.springframework.boot</groupId>            
   <artifactId>spring-boot-starter-websocket</artifactId>       
</dependency>

<!--  引入web开发三个包 -->
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
        
<!-- 阿里fastjson -->
<dependency>
           <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.80</version>
</dependency>

在这里插入图片描述

4. 要配置一个聊天服务端

WebSocket配置类

package com.cqgyzyjsxy.liaotianservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.websocket.server.ServerEndpointConfig;

/**
 * 模块名称:
 * 模块类型:
 * 编码人:高靖博
 * 创建时间:2023/4/12
 * 联系电话:18587388612
 */

@Configuration
public class WebScoketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

聊天处理类

package com.cqgyzyjsxy.liaotianservice.config;

import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 模块名称: 聊天程序服务端WebSocket配置
 * 模块类型:
 * 编码人:高靖博
 * 创建时间:2023/4/12
 * 联系电话:18587388612
 */
// LiaoTianSocket springBoot组件放入Spring容器中
@Component
// 客户端要连接聊天服务器时,指定的服务端地址
// 客户端连接服务器聊天服务的地址案例: ws://服务器ip地址:服务端口号/qqserver
@ServerEndpoint("/qqserver/{qqNumber}")
public class LiaoTianSocket {

    static{
        System.out.println("----------------------------------");
        System.out.println("------   WebSocket服务启动   -------");
        System.out.println("---------                ----------");
        System.out.println("----------------------------------");
    }

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    /**
     * QQ号
     */
    private String qqNumber;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
    //  注:底下WebSocket是当前类名
    private static CopyOnWriteArraySet<LiaoTianSocket> webSockets =new CopyOnWriteArraySet<>();

    // 用来存在线连接用户信息( 线程安全 )
    // key: QQ号  value: 每个客户端的session对象
    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();

    // 1. 当客户端连接时做什么事情
    @OnOpen
    public void onOpen(Session session,@PathParam(value="qqNumber") String qqNumber){
        System.out.println("--客户端连接[qq:"+qqNumber+"]--");
        this.session = session;
        this.qqNumber = qqNumber;
        sessionPool.put(qqNumber,session);
        webSockets.add(this);
    }

    // 2.当客户端发送消息给服务器时做什么事情
    // 参数message就是客户端给服务器发送的消息内容
    @OnMessage
    public void onMsg(String message){
        // 实现群发功能

        try {
            sendAllMsg(message);
        } catch (IOException e) {
            System.err.println("发送消息异常");
            e.printStackTrace();
        }
    }

    // 3.当客户端断开连接时要做什么事情
    @OnClose
    public void onClose(){
        System.out.println("客户端断开连接~!~!!");
    }

    // 4.当客户端发送消息、连接或断开连接时错误做什么事情
    @OnError
    public void onErr(Throwable error){
        error.printStackTrace();
        System.out.println("服务器或客户端异常!!!!");
    }

    /**
     * 群发功能
     * @param msg 群发的消息
     */
    public void sendAllMsg(String msg) throws IOException {
        System.out.println("--群发消息:"+msg);
        // 遍历所有已经连接到服务器的客户端对象
        for(LiaoTianSocket socket:webSockets){

            if(socket.session.isOpen()){// 判断客户端是否在线
                socket.session.getAsyncRemote().sendText(msg);
            }
        }
    }

}


4.2 前端实现

测试页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试</title>
    <style>
        /* 历史信息窗口样式 */
        .hsDiv{
            border:1px solid black;
            border-radius: 11px;
            width: 100%;
            height: 500px;
            overflow: auto;
            box-sizing: border-box;
            padding: 8px;
        }

        /* 消息的时间文字样式 */
        .time{
            font-size: 10px;
            color:gray;
        }

        /* 消息的文字内容样式 */
        .msgText{
            color:blue;
        }
        /* 发送人信息 */
        .person{
            font-size: 7px;
            color:black;   
        }
    </style>
</head>
<body>
    <span id="state">离线</span>
    <span id="qqNumber"></span>
    <input id="nickName" placeholder="定义一个你的昵称" />
    <button onclick="toConect()">连接</button>
    <hr/>
    <button onclick="sendMsg()">发送</button>
    <input id="msg" placeholder="请输入消息...." />
    <hr/>
    <!-- 历史信息框体 -->
    <div class="hsDiv" id="hsDiv">

        


    </div>

</body>

<script>
var qqNumber;

var webScoket;

var htmls = ""; // 所有历史信息html

var nikeName = ""; // 客户端昵称

// 连接到服务器
function toConect(){

    // 生成一个唯一的数字
    qqNumber  = parseInt(Math.random()*10000000000000);

    webScoket = new WebSocket("ws://localhost:9010/qqserver/"+qqNumber);

    // 定义一个连接成功的回调函数
    webScoket.onopen = function (){
        console.dir("-连接成功!");
        document.getElementById("state").innerHTML = "在线";
        document.getElementById("qqNumber").innerHTML = qqNumber;
        // 获取连接的昵称信息
        var nikeNames = document.getElementById("nickName").value;
        nikeName = nikeNames;
    }

    // 定义一个服务器发送消息给客户端的回调函数
    webScoket.onmessage = function(data){
        console.dir("-接收到消息:"+data.data);
        // QQ信息$消息内容$发送时间$昵称
        var msgArr = data.data.split("$");

        htmls += '<span class="time">时间:'+msgArr[2]+'</span><br/>'+
        '<span class="person">['+msgArr[3]+']</span><br/>'+
        '<span class="msgText">'+msgArr[1]+'</span>'+
        '<hr/>';

        // 动态html代码段添加进入聊天历史信息框中
        document.getElementById("hsDiv").innerHTML = htmls;

    }

}


// 发送消息方法
function sendMsg(){

    // 得到要发送的信息文字
    var msg = document.getElementById("msg").value;

   //  发送消息的格式:
   // QQ信息$消息内容$发送时间$昵称

   var nowDate = new Date();
   var sendMsgStr = qqNumber+"$"+msg+"$"+(nowDate.getFullYear() +"-"+nowDate.getMonth()+"-"+nowDate.getDate()+" "+nowDate.getHours()+":"+nowDate.getMinutes()+":"+nowDate.getSeconds()+"$"+nikeName)

    webScoket.send(sendMsgStr); // 消息发送给服务器了

}




</script>

</html>

在这里插入图片描述

gitee 仓库源码
https://gitee.com/gdones/cqgy-webqq/blob/master/README.md

### 回答1: Spring Boot的WebSocket实现支持简单的即时聊天应用程序的构建,可以在服务器和客户端之间双向传输消息。主要步骤如下:1. 添加WebSocket依赖 2. 实现WebSocketConfigurer接口,并重写registerWebSocketHandlers()方法 3. 编写WebSocket消息处理器 4. 测试WebSocket应用程序 ### 回答2: 实现Spring Boot中的WebSocket聊天功能代码可以按照以下步骤进行: 1. 首先,确保你的项目中已添加了相关的依赖,包括`spring-boot-starter-websocket`和`spring-boot-starter-thymeleaf`。可以在`pom.xml`中添加如下依赖: ```xml <dependencies> <!-- Spring Boot WebSocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- Spring Boot Thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> ``` 2. 创建一个`WebSocketConfig`类,用于配置WebSocket: ```java import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { private final WebSocketHandler webSocketHandler; public WebSocketConfig(WebSocketHandler webSocketHandler) { this.webSocketHandler = webSocketHandler; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler, "/chat").setAllowedOrigins("*"); } } ``` 3. 创建一个`WebSocketHandler`类,实现WebSocket的处理逻辑: ```java import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; import java.io.IOException; import java.util.ArrayList; import java.util.List; @Component public class ChatWebSocketHandler implements WebSocketHandler { private List<WebSocketSession> sessions = new ArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(new TextMessage(message.getPayload().toString())); } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { sessions.remove(session); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { session.close(); } @Override public boolean supportsPartialMessages() { return false; } } ``` 4. 创建一个`ChatController`类,用于处理聊天页面的请求: ```java import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class ChatController { @GetMapping("/chat") public String chat() { return "chat"; } } ``` 5. 创建一个`chat.html`文件,作为聊天页面的视图: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Chat</title> </head> <body> <div id="messageContainer"></div> <script> var socket = new WebSocket("ws://" + location.host + "/chat"); socket.onmessage = function (event) { var messageContainer = document.getElementById('messageContainer'); var message = document.createElement('p'); message.innerHTML = event.data; messageContainer.appendChild(message); }; document.onkeydown = function (event) { if (event.keyCode === 13) { var input = document.querySelector('input[name="message"]'); socket.send(input.value); input.value = ''; } }; </script> </body> </html> ``` 6. 启动应用,并在浏览器中访问`http://localhost:8080/chat`,即可看到聊天页面。在多个浏览器窗口中打开该页面,它们之间可以实时互相发送消息并显示在页面上。 这是一个简单的Spring Boot实现WebSocket聊天功能的代码示例,你可以根据实际需求进行调整和扩展。 ### 回答3: Spring Boot通过Spring WebSocket提供了实现WebSocket的功能。下面是实现基本聊天功能的Spring Boot WebSocket的代码。 1. 创建一个Spring Boot项目,并添加以下Maven依赖到pom.xml文件中: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> ``` 2. 创建一个WebSocket配置类,用于配置WebSocket相关的Bean。 ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new ChatHandler(), "/chat").setAllowedOrigins("*"); } } ``` 3. 创建一个WebSocket处理程序,用于处理来自客户端的WebSocket消息。 ```java public class ChatHandler extends TextWebSocketHandler { private List<WebSocketSession> sessions = new ArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } } ``` 4. 创建一个Controller类,用于处理聊天页面的请求。 ```java @Controller public class ChatController { @GetMapping("/chat") public String chat() { return "chat"; } } ``` 5. 在templates目录下创建一个chat.html文件,用于展示聊天页面。 ```html <!DOCTYPE html> <html> <head> <title>Chat</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script> var socket = new WebSocket("ws://localhost:8080/chat"); socket.onmessage = function(event) { var message = event.data; $("#chat").append('<p>' + message + '</p>'); } function sendMessage() { var message = $("#message").val(); socket.send(message); $("#message").val(""); } </script> </head> <body> <input type="text" id="message"><button onclick="sendMessage()">Send</button> <div id="chat"></div> </body> </html> ``` 以上代码实现一个简单的聊天功能,客户端向服务端发送消息并显示在页面中,同时服务端将消息广播给所有客户端。通过访问http://localhost:8080/chat可以打开聊天页面。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘的高先生

编写不易,感谢大佬的赏赐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值