从 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

目录
相关文章
|
28天前
|
前端开发 JavaScript
从 0 开始实现一个网页聊天室 (小型项目)(下)
从 0 开始实现一个网页聊天室 (小型项目)
49 16
|
28天前
|
JavaScript Java 测试技术
基于微信小程序的二手物品交易平台ssm附带文章和源代码设计说明文档ppt
基于微信小程序的二手物品交易平台ssm附带文章和源代码设计说明文档ppt
15 0
|
1月前
|
存储 前端开发 JavaScript
网页应用与开发
网页应用与开发
22 1
|
8月前
|
Web App开发 搜索推荐 NoSQL
如何搭建一个集成导航与在线工具的个性化浏览器私有书签(附详细搭建教程)
在这个信息爆炸的时代,我们都希望拥有一个能够轻松解决多端、多浏览器的收藏和笔记同步问题的神奇工具。Mtab书签正是为此而设计的顶级应用。它将基础导航、记事本、在线小工具和多端同步集于一身,为用户提供了更便利的网络浏览体验,并解决了多端同步的烦恼。
191 0
如何搭建一个集成导航与在线工具的个性化浏览器私有书签(附详细搭建教程)
|
8月前
|
小程序 前端开发 安全
微信小程序之会议OA系统首页布局搭建与Mock数据交互
微信小程序之会议OA系统首页布局搭建与Mock数据交互
66 0
|
11月前
|
存储 编解码 前端开发
前端web入门-移动web-day10
前端web入门-移动web-day10
|
11月前
|
机器学习/深度学习 前端开发
前端web入门-移动web-day09
前端web入门-移动web-day09
|
缓存 移动开发 小程序
「小程序开发」关于网页与小程序的通信
用技术实现梦想,用梦想打开前端技术之门。分享我在小程序开发中,总结的关于网页与小程序的通信的解决方案。
204 1
「小程序开发」关于网页与小程序的通信
|
小程序 JavaScript
打造自己的音乐小程序(下)——后端设计与开发
打造自己的音乐小程序(下)——后端设计与开发
247 0