数据库的操作和业务代码分离开,在业务层只能看到对象,看不到数据库的操作。我们要定义一些相关的ORM类,和数据库的表一一对应的,才能把数据库读出来的字段合成一个对象提供给业务层使用
我们在inlcude/server下创建一个文件夹:model
首先我们在inlcude/server/model文件夹下创建文件:user.hpp
#ifndef USER_H
#define USER_H
#include <string>
using namespace std;
class User
{
public:
User(int id = -1, string name = "", string pwd = "", string state = "offline")
{
this->id = id;
this->name = name;
this->password = pwd;
this->state = state;
}
void setId(int id) { this->id = id; }
void setName(string name) { this->name = name; }
void setPwd(string pwd) { this->password = pwd; }
void setState(string state) { this->state = state; }
int getId() { return this->id; }
string getName() { return this->name; }
string getPwd() { return this->password; }
string getState() { return this->state; }
private:
int id;
string name;
string password;
string state;
};
#endif
我们在inlcude/server/model文件夹下再创建文件:usermodel.hpp
UserModel是User表的数据操作类,和业务不相关,针对表的CRUD
#ifndef USERMODEL_H
#define USERMODEL_H
#include "user.hpp"
//User表的数据操作类,和业务不相关,针对表的CRUD
class UserModel
{
public:
//User表的增加方法
bool insert(User &user);
};
#endif
在src/server下创建一个文件夹:model
在src/server/model下创建文件:usermodel.cpp
#include "usermodel.hpp"
#include "db.h"
#include <iostream>
using namespace std;
bool UserModel::insert(User &user)
{
// 1. 组装sql语句
char sql[1024] = {0};
// 此处刚注册,还没有登录,肯定是offline,我们在User类的构造函数里state默认为offline
sprintf(sql, "insert into user(name, password, state) values('%s', '%s', '%s')",
user.getName().c_str(), user.getPwd().c_str(), user.getState().c_str());
MySQL mysql;
if (mysql.connect()) // 2. 连接数据库
{
if (mysql.update(sql)) // 3. 发送sql语句插入数据
{
//获取插入成功的用户数据生成的主键id
user.setId(mysql_insert_id(mysql.getConnection()));
return true;
}
}
return false;
}
完善include/public.hpp
#ifndef PUBLIC_H
#define PUBLIC_H
//server和client的公共文件
enum EnMsgType
{
LOGIN_MSG = 1, //登录消息
REG_MSG, //注册消息
REG_MSG_ACK //注册响应消息
};
#endif
完善include/server/chatservice.hpp
完善src/server/chatservice.cpp中的reg方法
#include "chatservice.hpp"
#include "public.hpp"
#include <muduo/base/Logging.h>
#include<string>
using namespace std;
using namespace muduo;
//获取单例对象的接口函数
ChatService* ChatService:: instance()
{
static ChatService service;
return &service;
}
//注册消息以及对应的回调操作
ChatService :: ChatService()
{
_msgHandlerMap.insert({LOGIN_MSG, bind(&ChatService::login, this,_1,_2,_3)});
_msgHandlerMap.insert({REG_MSG, bind(&ChatService::reg,this,_1,_2,_3)});
}
//获取消息对应的处理器
MsgHandler ChatService::getHandler(int msgid)
{
//记录错误日志,msgid没有对应的事件处理回调
auto it = _msgHandlerMap.find(msgid);
if(it == _msgHandlerMap.end()){
//返回一个默认的处理器,空操作
return [=](const TcpConnectionPtr &conn, json &js, Timestamp){
LOG_ERROR << "msgid:"<<msgid<<" can not find handler!";
};
}
else{
return _msgHandlerMap[msgid];
}
}
//处理登录业务
void ChatService :: login(const TcpConnectionPtr &conn, json &js, Timestamp)
{
LOG_INFO<<"do login service!!!";
}
//处理注册业务
void ChatService :: reg(const TcpConnectionPtr &conn, json &js, Timestamp)
{
string name = js["name"];
string pwd = js["password"];
User user;
user.setName(name);
user.setPwd(pwd);
bool state = _userModel.insert(user);
if(state)
{
//注册成功
json responce;
responce["msgid"] = REG_MSG_ACK;
//errno=0响应成功,不为0那肯定还有errmsg说明错误消息
responce["errno"] = 0;
responce["id"] = user.getId();
conn->send(responce.dump());
}
else{
//注册失败
json responce;
responce["msgid"] = REG_MSG_ACK;
responce["errno"] = 1;
conn->send(responce.dump());
}
}
在chat/CMakeLists.txt中加入model的头文件搜索路径
在src/server/CMakeLists.txt中加入model的源文件编译路径
编译并测试一下注册功能
检查数据库是否插入成功
若出现问题,可以打开查询日志开关:set global general_log = "on";
show global variables like 'general%';
查看查询日志位置
查看查询日志