日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 默认站点!

默认站点

當前位置: 首頁 >

私人博客定制---服务器接口封装

發(fā)布時間:2023/11/30 25 豆豆
默认站点 收集整理的這篇文章主要介紹了 私人博客定制---服务器接口封装 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

實現(xiàn)服務器接口

我們用一個http服務器作為底層,但是c++中并沒有先成的http服務器,所以我在GitHub上找到一個牛人寫的http服務器,拿來直接用,節(jié)省本項目開發(fā)的時間
這是服務器的鏈接地址
上面有詳細的使用方法,本文就不再解釋具體如何實現(xiàn),就直接用該cpp-httplib這個庫來進行開發(fā)

https://github.com/yhirose/cpp-httplib.git

然后我們就要實現(xiàn)相應的接口了

  • 首先我們先要讓我們的服務器和數(shù)據(jù)庫連通,所以我們先要進行數(shù)據(jù)庫客戶端的初始化和釋放
  • 第二步我們就要設置一些自定義的路由(此處的路由并不是IP里的路由,而是指的是http中對應的方法+path對應到相應的處理函數(shù)上),要實現(xiàn)新增博客,查看博客等在數(shù)據(jù)庫里所對應的相應的功能
  • 第三步,我們要設置靜態(tài)文件目錄,把我們將來寫好的網(wǎng)頁放到這個目錄里
  • 和數(shù)據(jù)庫建立鏈接

    在這一步中,連接很簡單,調(diào)用我們封裝好的數(shù)據(jù)庫API就行,但是斷開連接就比較麻煩,因為整個服務器一但啟動,他會進入到監(jiān)聽狀態(tài),所以必須等服務器關(guān)閉時,我們才能斷開連接,而我們一般在Linux下關(guān)閉服務器都是使用ctrl+c來進行關(guān)閉。ctrl+c是一個信號,所以我們可以當觸發(fā)這個信號時,就進行斷開連接操作。

    using namespace httplib; using namespace blog_system; //1. 先和數(shù)據(jù)庫建立好鏈接 mysql = blog_system::MySQLInit(); signal(SIGINT,[](int){blog_system::MySQLRelease(mysql);exit(0);}); //2.創(chuàng)建相關(guān)數(shù)據(jù)庫處理對象 BlogTable blog_table(mysql); TagTable tag_table(mysql);

    我們在進行信號處理時,第二個參數(shù),是一個回調(diào)函數(shù),當?shù)谝粋€參數(shù)觸發(fā)時,執(zhí)行后面回調(diào)函數(shù)里的內(nèi)容,但是要寫一個函數(shù)太麻煩,這里使用c++11中提供的lambda表達式。這樣可以使代碼更簡潔,更容易進行維護。

    實現(xiàn)新增博客

    我們要先接受請求消息中的body,并把它轉(zhuǎn)化成json,也就是把HHTP中的我們看不懂或者是太難理解的請求,轉(zhuǎn)化為j我們能看懂或是看起來比較方便的json格式。
    而我們要實現(xiàn)新增博客必須要經(jīng)歷以下幾個步驟

  • 首先我們肯定要接受http的請求消息,這里就是一個Post請求
  • 我們要對這個消息進行校驗,但是http的格式并不好讓我們進行校驗,所以我們要先把http的格式轉(zhuǎn)化為json格式,方便我們進行校驗
  • 校驗完后,我們就可以調(diào)用我們封裝好的mysql的API對數(shù)據(jù)進行操作
  • 最后我們還要封裝正確的返回結(jié)果,給用戶友好的提示
  • 這里我們并不使用異常處理,我們使用錯誤判定,這樣更好,雖然代碼比較亂,但是可以很容易理解。而且c++中異常處理比較差,功能比較有限
  • 不光是這個接口,我們每個博客接口都必須捕捉到blog_table這個對象
  • server.Post("/blog", [&blog_table](const Request& req, Response& resp) {printf("新增博客!\n");//創(chuàng)建一些我們需要用到的對象Json::FastWriter writer; //寫對象Json::Reader reader; //讀取對象Json::Value req_json; //請求對象 Json::Value resp_json; //響應對象//1.獲取到請求中的body并解析成json//parse函數(shù)中第一個參數(shù)是需要解析的字符串//第二個參數(shù)是把解析后的字符串放到哪個對象中//第三個參數(shù)是注釋,默認是true,所以我就不管了bool ret = reader.parse(req.body,req_json);if(!ret){//解析出錯,給用戶提示printf("解析請求失敗! %s\n",req.body.c_str());//構(gòu)造一個相應對象,告訴客戶端出錯了resp_json["ok"] = false;resp_json["reason"] = "提交的數(shù)據(jù)格式有誤!\n";resp.status = 400;//返回給客戶端,第二個參數(shù)設置反回的數(shù)據(jù)類型resp.set_content(writer.write(resp_json), "application/json");return;}//2. 進行參數(shù)校驗//這些字段如果缺任何一個,都代表有錯if (req_json["title"].empty() || req_json["content"].empty()|| req_json["tag_id"].empty() || req_json["create_time"].empty()) {resp_json["ok"] = false;resp_json["reason"] = "博客的格式出錯!\n";resp.status = 400;resp.set_content(writer.write(resp_json), "application/json");return; }//3.調(diào)用數(shù)據(jù)庫接口進行操作ret = blog_table.Insert(req_json);if (!ret) {printf("插入博客失敗!\n");resp_json["ok"] = false;resp_json["reason"] = "插入失敗!\n";resp.status = 500;resp.set_content(writer.write(resp_json), "application/json");return;}//4.封裝正確的返回結(jié)果resp_json["ok"] = true;resp.set_content(writer.write(resp_json), "application/json");return;});

    查看所有博客

    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 沒有請求參數(shù), 不需要解析參數(shù)和校驗了, 直接構(gòu)造結(jié)果即可 // 1. 調(diào)用數(shù)據(jù)庫接口查詢數(shù)據(jù) 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. 構(gòu)造響應結(jié)果 resp.set_content(writer.write(blogs), "application/json"); return; });

    查看一篇博客

    查看一篇博客內(nèi)容
    查看blog_id,如果這里只寫blog_id,這個httplib的庫并不能識別,我又仔細看了
    這個庫的文檔,他用了正則表達式,所以我又學習了一些正則表達式的內(nèi)容
    我們可以用\d+ 表示匹配一個數(shù)字,但是這里又可能會引發(fā)c++中的轉(zhuǎn)義字符,所以我們需要c++11中提供的R()使轉(zhuǎn)義字符不生效
    學習正則表達式

    server.Get(R"(/blog/(\d+))", [&blog_table](const Request& req, Response& resp) {//1.解析獲取到blog_idint32_t blog_id = std::stoi(req.matches[1].str());printf("查看id為 %d 的博客!\n",blog_id);Json::Value resp_json;Json::FastWriter writer;//2.直接調(diào)用數(shù)據(jù)庫操作bool ret = blog_table.SelectOne(blog_id, &resp_json);if (!ret) {resp_json["ok"] = false;resp_json["reason"] = "查看指定博客失敗!\n";resp.status = 404;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.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. 調(diào)用數(shù)據(jù)庫接口刪除博客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. 調(diào)用數(shù)據(jù)庫接口進行修改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. 封裝正確的數(shù)據(jù)resp_json["ok"] = true;resp.set_content(writer.write(resp_json), "application/json");return;});

    新增標簽

    新增標簽跟新增博客是一樣的道理,都需要把依賴對象傳進來,然后先進行格式校驗,校驗前先進行解析,校驗完后再調(diào)用mysqlAPI,最后帶著結(jié)果返回。

    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. 調(diào)用數(shù)據(jù)庫接口, 插入標簽 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. 返回正確的結(jié)果 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. 執(zhí)行數(shù)據(jù)庫操作刪除標簽 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. 包裝正確的結(jié)果 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. 調(diào)用數(shù)據(jù)庫接口查詢數(shù)據(jù)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. 構(gòu)造響應結(jié)果resp.set_content(writer.write(tags), "application/json");return; });

    獲取靜態(tài)文件目錄

    server.set_base_dir("./wwwroot");

    總結(jié)

    以上是默认站点為你收集整理的私人博客定制---服务器接口封装的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得默认站点網(wǎng)站內(nèi)容還不錯,歡迎將默认站点推薦給好友。