私人博客定制---服务器接口封装
實現服務器接口
我們用一個http服務器作為底層,但是c++中并沒有先成的http服務器,所以我在GitHub上找到一個牛人寫的http服務器,拿來直接用,節省本項目開發的時間
這是服務器的鏈接地址
上面有詳細的使用方法,本文就不再解釋具體如何實現,就直接用該cpp-httplib這個庫來進行開發
然后我們就要實現相應的接口了
和數據庫建立鏈接
在這一步中,連接很簡單,調用我們封裝好的數據庫API就行,但是斷開連接就比較麻煩,因為整個服務器一但啟動,他會進入到監聽狀態,所以必須等服務器關閉時,我們才能斷開連接,而我們一般在Linux下關閉服務器都是使用ctrl+c來進行關閉。ctrl+c是一個信號,所以我們可以當觸發這個信號時,就進行斷開連接操作。
using namespace httplib; using namespace blog_system; //1. 先和數據庫建立好鏈接 mysql = blog_system::MySQLInit(); signal(SIGINT,[](int){blog_system::MySQLRelease(mysql);exit(0);}); //2.創建相關數據庫處理對象 BlogTable blog_table(mysql); TagTable tag_table(mysql);我們在進行信號處理時,第二個參數,是一個回調函數,當第一個參數觸發時,執行后面回調函數里的內容,但是要寫一個函數太麻煩,這里使用c++11中提供的lambda表達式。這樣可以使代碼更簡潔,更容易進行維護。
實現新增博客
我們要先接受請求消息中的body,并把它轉化成json,也就是把HHTP中的我們看不懂或者是太難理解的請求,轉化為j我們能看懂或是看起來比較方便的json格式。
而我們要實現新增博客必須要經歷以下幾個步驟
查看所有博客
server.Get("/blog", [&blog_table](const Request& req, Response& resp) { printf("查看所有博客!\n"); Json::Reader reader; Json::FastWriter writer; Json::Value resp_json; //如果沒傳tag_id,返回的是空字符串 const std::string& tag_id = req.get_param_value("tag_id"); // 對于查看博客來說 API 沒有請求參數, 不需要解析參數和校驗了, 直接構造結果即可 // 1. 調用數據庫接口查詢數據 Json::Value blogs; bool ret = blog_table.SelectAll(&blogs, tag_id); if (!ret) { resp_json["ok"] = false; resp_json["reason"] = "查看博客失敗\n"; resp.status = 500; resp.set_content(writer.write(resp_json), "application/json"); return; } // 2. 構造響應結果 resp.set_content(writer.write(blogs), "application/json"); return; });查看一篇博客
查看一篇博客內容
查看blog_id,如果這里只寫blog_id,這個httplib的庫并不能識別,我又仔細看了
這個庫的文檔,他用了正則表達式,所以我又學習了一些正則表達式的內容
我們可以用\d+ 表示匹配一個數字,但是這里又可能會引發c++中的轉義字符,所以我們需要c++11中提供的R()使轉義字符不生效
學習正則表達式
刪除博客
server.Delete(R"(/blog/(\d+))", [&blog_table](const Request& req, Response& resp) {Json::Value resp_json;Json::FastWriter writer;// 1. 解析獲取 blog_id//使用 matches[1] 就能獲取到 blog_idint32_t blog_id = std::stoi(req.matches[1].str());printf("刪除 id 為%d 的博客!\n",blog_id);// 2. 調用數據庫接口刪除博客bool ret = blog_table.Delete(blog_id);if (!ret) {resp_json["ok"] = false;resp_json["reason"] = "刪除博客失敗!\n";resp.status = 500;resp.set_content(writer.write(resp_json), "application/json");return;}//3.包裝正確的響應resp_json["ok"] = true;resp.set_content(writer.write(resp_json), "application/json");return;});修改博客
修改博客就是重新插入新博客,所以我們又要校驗博客信息,當然再校驗之前還是需要對博客進行解析。
server.Put(R"(/blog/(\d+))", [&blog_table](const Request& req, Response& resp) {Json::Reader reader;Json::FastWriter writer;Json::Value req_json;Json::Value resp_json;// 1. 獲取到博客 idint32_t blog_id = std::stoi(req.matches[1].str());printf("修改 id為 %d的博客!\n",blog_id);// 2. 解析博客信息bool ret = reader.parse(req.body, req_json);if (!ret) {resp_json["ok"] = false;resp_json["reason"] = "解析博客失敗!\n";resp.status = 400;resp.set_content(writer.write(resp_json), "application/json");return ;}//一定要記得補充上 blog_id req_json["blog_id"] = blog_id; //從path中得到的id設置到json對象中// 3. 校驗博客信息if (req_json["title"].empty() || req_json["content"].empty()|| req_json["tag_id"].empty()) {// 請求解析出錯, 返回一個400響應resp_json["ok"] = false;resp_json["reason"] = "更新博客格式錯誤\n";resp.status = 400;resp.set_content(writer.write(resp_json), "application/json");return;}// 4. 調用數據庫接口進行修改ret = blog_table.Update(req_json);if (!ret) {resp_json["ok"] = false;resp_json["reason"] = "更新失敗!\n";resp.status = 500;resp.set_content(writer.write(resp_json), "application/json");return;}// 5. 封裝正確的數據resp_json["ok"] = true;resp.set_content(writer.write(resp_json), "application/json");return;});新增標簽
新增標簽跟新增博客是一樣的道理,都需要把依賴對象傳進來,然后先進行格式校驗,校驗前先進行解析,校驗完后再調用mysqlAPI,最后帶著結果返回。
server.Post("/tag", [&tag_table](const Request& req, Response& resp) { Json::Reader reader; Json::FastWriter writer; Json::Value req_json; Json::Value resp_json; printf("新增標簽!\n"); // 1. 請求解析成 Json 格式 bool ret = reader.parse(req.body, req_json); if (!ret) { resp_json["ok"] = false; resp_json["reason"] = "解析失敗\n"; resp.status = 400; resp.set_content(writer.write(resp_json), "application/json"); return ; } // 2. 校驗標簽格式 if (req_json["tag_name"].empty()) { resp_json["ok"] = false; resp_json["reason"] = "標簽格式有誤!\n"; resp.status = 400; resp.set_content(writer.write(resp_json), "application/json"); return; } // 3. 調用數據庫接口, 插入標簽 ret = tag_table.Insert(req_json); if (!ret) { resp_json["ok"] = false; resp_json["reason"] = "插入標簽失敗!\n"; resp.status = 500; resp.set_content(writer.write(resp_json), "application/json"); return; } // 4. 返回正確的結果 resp_json["ok"] = true; resp.set_content(writer.write(resp_json), "application/json"); });刪除標簽
server.Delete(R"(/tag/(\d+))", [&tag_table](const Request& req, Response& resp) { Json::Value resp_json; Json::FastWriter writer; // 1. 解析出 tag_id int tag_id = std::stoi(req.matches[1].str()); printf("要刪除的標簽id 為 %d\n",tag_id); // 2. 執行數據庫操作刪除標簽 bool ret = tag_table.Delete(tag_id); if (!ret) { resp_json["ok"] = false; resp_json["reason"] = "刪除所有標簽失敗\n"; resp.status = 500; resp.set_content(writer.write(resp_json), "application/json"); return; } // 3. 包裝正確的結果 resp_json["ok"] = true; resp.set_content(writer.write(resp_json), "application/json"); return; });獲取所有標簽
server.Get("/tag", [&tag_table](const Request& req, Response& resp) { printf("獲取所有標簽\n");Json::Reader reader;Json::FastWriter writer;Json::Value resp_json;// 1. 調用數據庫接口查詢數據Json::Value tags;bool ret = tag_table.SelectAll(&tags);if (!ret) {resp_json["ok"] = false;resp_json["reason"] = "查找所有標簽失敗\n";resp.status = 500;resp.set_content(writer.write(resp_json), "application/json");return;}// 2. 構造響應結果resp.set_content(writer.write(tags), "application/json");return; });獲取靜態文件目錄
server.set_base_dir("./wwwroot");總結
以上是生活随笔為你收集整理的私人博客定制---服务器接口封装的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成都大熊猫繁育基地购票须知
- 下一篇: 网络年代剧情介绍