从 0 开始实现一个网页聊天室 (小型项目)(上)

简介: 从 0 开始实现一个网页聊天室 (小型项目)

实现功能

  1. 用户注册和登录
  2. 好友列表展示
  3. 会话列表展示: 显示当前正在进行哪些会话 (单聊 / 群聊) , 选中好友列表中的某个好友, 会生成对应的会话
  4. 实时通信, A给B发送消息, B的聊天界面 / 会话界面能立刻显示新的消息


TODO:

  1. 添加好友功能
  2. 用户头像显示
  3. 传输图片 / 表情包
  4. 历史消息搜索
  5. 消息撤回

相关技术


网络通信: WebSocket

Spring + SpringBoot + SpringMVC + MyBatis

HTML + CSS + JS

数据库设计

项目的基本框架

前端页面

注册和登录页面

聊天界面

后端代码

实体类

User

本类表示一个用户的信息, 对应数据库的 user 表

@Data
public class User {

    private int userId;
    private String username = "";
    private String password = "";

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

Friend

使用一个 Friend 对象表示一个好友

// 使用一个 Friend 对象表示一个好友, 对应数据库的 friend 表
@Data
public class Friend {
    private int friendId;
    private String friendName;

    public Friend() {
    }

    public Friend(int friendId, String friendName) {
        this.friendId = friendId;
        this.friendName = friendName;
    }
}

Message

本类表示一条消息的相关信息, 对应数据库的表 message + 字段: fromname

(没有 postTime 是因为: 在查询的时候就是一次性查出所有的时间, 按照时间结果排序后返回, 我们这里就不需要再获取时间了)

// 本类表示一条消息的相关信息
// (没有 postTime 是因为: 在查询的时候就是一次性查出所有的时间, 按照时间结果排序后返回, 我们这里就不需要再获取时间了)
@Data
public class Message {
    private Integer messageId;
    private int fromId;
    private String fromName;
    private int sessionId;
    private String content;

    public Message() {
    }

    public Message( int fromId, String fromName, int sessionId, String content) {
        this.fromId = fromId;
        this.fromName = fromName;
        this.sessionId = sessionId;
        this.content = content;
    }
}

MessageSession

使用该类表示一个会话, 对应数据库的 message_session + message_session_user

// 使用该类表示一个会话
@Data
public class MessageSession {
    private int sessionId;
    private List<Friend> friends;
    private String lastMessage;
}

MessageSessionUserItem

该类对象表示 message_session_user 表里的一个记录

// 该类对象表示 message_session_user 表里的一个记录
@Data
public class MessageSessionUserItem {
    private int sessionId;
    private int userId;

    public MessageSessionUserItem() {
    }

    public MessageSessionUserItem(int sessionId, int userId) {
        this.sessionId = sessionId;
        this.userId = userId;
    }
}

MessageRequest

WebSocket 请求

自定义格式, 用于网络通信中接受请求

// WebSocket请求
@Data
public class MessageRequest {
    private String type = "message";
    private int sessionId;
    private String content;
}

MessageResponse

WebSocket 响应

自定义格式, 用于网络通信中返回响应

// WebSocket响应
@Data
public class MessageResponse {
    private String type = "message";
    private int fromId;
    private String fromName;
    private int sessionId;
    private String content;

    public MessageResponse() {
    }

    public MessageResponse(int fromId, String fromName, int sessionId, String content) {
        this.fromId = fromId;
        this.fromName = fromName;
        this.sessionId = sessionId;
        this.content = content;
    }
}

数据库

FriendMapper

用户好友的相关操作

@Mapper
public interface FriendMapper {
    // 查询用户好友列表
    List<Friend> selectFriendList(@Param("userId") int userId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.java_chatroom.model.FriendMapper">

    <select id="selectFriendList" resultType="com.example.java_chatroom.model.Friend">
        select userId as friendId, username as friendName
        from user
        where userId in
        (select friendId from friend where userId = #{userId})
    </select>
</mapper>

MessageMapper

消息的相关操作

@Mapper
public interface MessageMapper {

    // 获取指定会话的最后一条消息
    String getLastMessageBySessionId(@Param("sessionId") int sessionId);

    // 获取指定会话的历史消息 (限制100条)
    List<Message> getMessagesBySessionId(@Param("sessionId") int sessionId);

    // 插入一条消息到数据库表中
    void add(@Param("message") Message message);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.java_chatroom.model.MessageMapper">

    <select id="getLastMessageBySessionId" resultType="java.lang.String">
        select content from message
        where sessionId = #{sessionId}
        order by postTime desc
        limit 1
    </select>

    <select id="getMessagesBySessionId" resultType="com.example.java_chatroom.model.Message">
        select
            messageId, sessionId, fromId, content, username as fromName
        from
            message, user
        where
            sessionId = #{sessionId}
            and fromId = userId
        order by
            postTime desc
        limit 100 offset 0
    </select>

    <insert id="add">
        insert into message values(null, #{message.fromId}, #{message.sessionId}, #{message.content}, now());
    </insert>
</mapper>

MessageSessionMapper

会话的相关操作

@Mapper
public interface MessageSessionMapper {
    // 1.根据 userId 获取到该用户在哪些会话中存在, 返回结果是一组 sessionId.
    List<Integer> getSessionIdsByUserId(@Param("userId") int userId);

    // 2. 根据 sessionId 查询这个会话包含哪些用户(刨除掉最初的 user)
    List<Friend> getFriendsBySessionId(@Param("sessionId") int sessionId,@Param("selfUserId") int selfUserId);

    // 3. 新增会话记录, 返回会话 id
    int addMessageSession(@Param("messageSession") MessageSession messageSession);

    // 4.给 message_session_user 表新增对应记录
    int addMessageSessionUser(@Param("messageSessionUserItem") MessageSessionUserItem messageSessionUserItem);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.java_chatroom.model.MessageSessionMapper">

    <select id="getSessionIdsByUserId" resultType="java.lang.Integer">
        select sessionId from message_session
        where sessionId in
            ( select sessionId from message_session_user
             where userId = #{userId} )
        order by lastTime desc
    </select>

    <select id="getFriendsBySessionId" resultType="com.example.java_chatroom.model.Friend">
        select userId as friendId, username as friendName
        from user
        where userId in
            ( select userId from message_session_user
                where sessionId = #{sessionId}
                and userId != #{selfUserId} )
    </select>

    <insert id="addMessageSession" useGeneratedKeys="true" keyProperty="messageSession.sessionId">
        insert into message_session values(null, now())
    </insert>

    <insert id="addMessageSessionUser">
        insert into message_session_user values(
            #{messageSessionUserItem.sessionId},
            #{messageSessionUserItem.userId}
        )
    </insert>
</mapper>

从 0 开始实现一个网页聊天室 (小型项目)(下):https://developer.aliyun.com/article/1520799

目录
相关文章
|
7月前
|
数据安全/隐私保护
那些酷炫的网页你也可以做到——第六篇,小型公司web开发
那些酷炫的网页你也可以做到——第六篇,小型公司web开发
|
4月前
|
前端开发 开发者 开发框架
JSF与Bootstrap,打造梦幻响应式网页!让你的应用跨设备,让用户爱不释手!
【8月更文挑战第31天】在现代Web应用开发中,响应式设计至关重要,以确保不同设备上的良好用户体验。本文探讨了JSF(JavaServer Faces)与Bootstrap框架的结合使用,展示了如何构建响应式网页。JSF是一个基于Java的Web应用框架,提供丰富的UI组件和表单处理功能;而Bootstrap则是一个基于HTML、CSS和JavaScript的前端框架,专注于实现响应式设计。通过结合两者的优势,开发者能够更便捷地创建自适应布局,提升Web应用体验。然而,这种组合也有其局限性,如JSF组件库较小和较高的学习成本等,因此在选择开发框架时需综合考虑具体需求和应用场景。
54 0
|
5月前
|
开发框架 前端开发 JavaScript
循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面
循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面
|
7月前
|
前端开发 JavaScript
从 0 开始实现一个网页聊天室 (小型项目)(下)
从 0 开始实现一个网页聊天室 (小型项目)
96 16
|
6月前
|
前端开发 JavaScript 容器
程序与技术分享:BeetleX之快速构建Web多房间聊天室
程序与技术分享:BeetleX之快速构建Web多房间聊天室
47 0
|
Web App开发 搜索推荐 NoSQL
如何搭建一个集成导航与在线工具的个性化浏览器私有书签(附详细搭建教程)
在这个信息爆炸的时代,我们都希望拥有一个能够轻松解决多端、多浏览器的收藏和笔记同步问题的神奇工具。Mtab书签正是为此而设计的顶级应用。它将基础导航、记事本、在线小工具和多端同步集于一身,为用户提供了更便利的网络浏览体验,并解决了多端同步的烦恼。
263 0
如何搭建一个集成导航与在线工具的个性化浏览器私有书签(附详细搭建教程)
|
7月前
|
存储 前端开发 JavaScript
网页应用与开发
网页应用与开发
49 1
|
7月前
|
存储 前端开发 JavaScript
实现一个网页聊天室
实现一个网页聊天室
|
小程序 Java Maven
通过后端数据交互,实现【会议Oa小程序】首页数据渲染
通过后端数据交互,实现【会议Oa小程序】首页数据渲染
|
NoSQL 前端开发 JavaScript
DjangoChannels_vue前端搭建简易版的网页聊天功能
DjangoChannels_vue前端搭建简易版的网页聊天功能
190 1