1. 在include/public.hpp中添加加好友消息类型
#ifndef PUBLIC_H
#define PUBLIC_H
// server和client的公共文件
enum EnMsgType
{
LOGIN_MSG = 1, //登录消息
LOGIN_MSG_ACK, //登录响应消息
REG_MSG, //注册消息
REG_MSG_ACK, //注册响应消息
ONE_CHAT_MSG, //聊天消息
ADD_FRIEND_MSG //添加好友消息
};
#endif
2. 数据库层
用户登陆成功会把其好友列表返回回去,实际上好友列表一般是基于客户端的,因为好友列表信息一般比较多,如果每次用户登陆成功以后都通过服务器给用户返回,这样服务器压力太大。因为好友列表又不会变,用户下线后在上线之前好友列表肯定不会变动的,所以在下线的时候就把好友列表全部更新在本地文件,这里使业务更简化就不在本地存了。
我们给用户展现好友列表时,需要返回好友的id、name和state,需要做user表和friend表的联合查询
表中两个字段,一个是用户id,一个是用户的friend的id,这种关系不用写多次,所以用联合主键,两人是好友写一次就可以了。由于双向的好友关系我们只存储一次(即不能同时存在1-3,3-1),在查询friend表的过滤条件需要查看两个字段userid和friendid,这样才能完整的显示出某个用户的所有好友
SQL语句如下:
select user.id, user.name, user.state from user inner join friend on user.id=friend.friendid where friend.userid=%d
数据库层的include/server/model/friendmodel.hpp如下:
#ifndef FRIENDMODEL_H
#define FRIENDMODEL_H
#include "user.hpp"
#include <vector>
using namespace std;
//维护好友信息的操作接口方法
class FriendModel
{
public:
//添加好友关系
void insert(int userid, int friendid);
//返回用户好友列表
vector<User> query(int userid);
};
#endif
数据库层的src/server/model/friendmodel.cpp如下:
#include "friendmodel.hpp"
#include "db.h"
//添加好友关系
void FriendModel::insert(int userid, int friendid)
{
char sql[1024] = {0};
sprintf(sql, "insert into friend values(%d, %d)", userid, friendid);
MySQL mysql;
if (mysql.connect())
{
mysql.update(sql);
}
}
//返回用户好友列表
vector<User> FriendModel::query(int userid)
{
char sql[1024] = {0};
sprintf(sql, "select user.id, user.name, user.state from user inner join friend on user.id=friend.friendid where friend.userid=%d", userid);
vector<User> vec;
MySQL mysql;
if (mysql.connect())
{
MYSQL_RES *res = mysql.query(sql);
if (res != nullptr)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != nullptr)
{
User user;
user.setId(atoi(row[0]));
user.setName(row[1]);
user.setState(row[2]);
vec.push_back(user);
}
mysql_free_result(res);
}
}
return vec;
}
3. 业务层
在include/server/chatservice.hpp中添加FriendModel对象和addFriend方法
#include "friendmodel.hpp"
//添加好友业务
void addFriend(const TcpConnectionPtr &conn, json &js, Timestamp);
FriendModel _friendModel;
在src/server/chatservice.cpp中的ChatService构造函数中绑定加好友消息对应的回调函数
chatservice.cpp中实现addFriend方法
//添加好友业务
void ChatService::addFriend(const TcpConnectionPtr &conn, json &js, Timestamp)
{
int userid = js["userid"].get<int>();
int friendid = js["friendid"].get<int>();
//存储好友信息
_friendModel.insert(userid, friendid);
}
在login方法中实现登录成功后查询用户的好友信息并返回
4. 编译测试
编译成功后让zhang san登录{"msgid":1,"id":27,"password":"123456"}
zhang san添加li si好友
{"msgid":6,"userid":27,"friendid":28}
,查询数据库friend表
我们退出zhang san,然后重新登录,看服务器是否能正常返回好友列表