【Linux/網絡】基於HTTP的簡易點餐系統小項目 持續更新~

一、整體架構

系統的整體分爲三個部分:服務器、商家客戶端、顧客客戶端

項目效果:

  1. 商家通過商家客戶端可以進行訂單管理和菜品管理;
  2. 顧客可以通過掃描餐桌上的二維碼進入顧客客戶端進行點餐,將訂單提交到服務器上由商家在客戶端上獲取到;

編程語言/開發平臺:

  1. 服務器:編程語言基於C++、開發平臺基於Linux(CentOS 7.3)(阿里雲輕量應用服務器)、MySQL
  2. 客戶端:HTML、CSS、JavaScript

二、服務器

一、HTTP服務器

1、創建數據庫

在MySQL數據庫中創建一個名爲 Order_System 的庫,並在中添加兩張表,分別爲:

  1. dish_table(菜品列表):dish_id 序號、name 菜名、price 價格
  2. order_table(訂單列表):order_id 訂單序號、table_id 桌號、time 時間、dish_id 菜品序號、state 訂單狀態(0表示進行中,1表示已完結)

創建庫 Order_System,並使用該庫

create database if not exists order_system;
use order_system;

創建菜品列表 dish_table (展現給顧客,由商家維護) 

create table if not exists dish_table(
dish_id int unsigned not null primary key auto_increment,
name varchar(50),
price int);

創建訂單列表 order_table (顧客提交,商家查看)

create table if not exists order_table(
order_id int unsigned not null primary key auto_increment,
table_id varchar(50),  
time varchar(50),      
dish_ids varchar(1024),
state int); 

2、服務端設計 (RESTful風格)

菜品管理API設計

1、新增菜品(商家)

請求:
POST /dish
{
 "name": "宮保雞丁",
 "price": 1800
}
響應:
HTTP/1.1 200 OK
{
 "ok": true,
 "dish_id": 1,
} 

2、查看所有菜品 (商家/顧客)

請求:
GET /dish
響應:
HTTP/1.1 200 OK
[
 {
 dish_id: 1,
 name: "宮保雞丁",
 price: 1800
 }
] 

 3、刪除菜品 (商家)

請求:
DELETE /dish/:dish_id
響應:
HTTP/1.1 200 OK
{
 "ok": true
} 

 4、修改菜品 (商家)

請求:
PUT /dish/:dish_id
{
 "name": "京醬肉絲",
 "price": 1900
}
響應:
HTTP/1.1 200 OK
{
 "ok": true
} 

訂單管理API設計

1、提交訂單(顧客)

請求:
POST /order
{
 "table_id": "1",
 "time": "2019-05-15 12:00",
 "dish_ids": [1, 2]
}
響應:
HTTP/1.1 200 OK
{
 "ok": true
} 

2、 修改訂單狀態(商家)

請求:
PUT /order/:order_id
{
 "state": 0,
}
響應:
HTTP/1.1 200 OK
{
 "ok": true
} 

3、獲取訂單 (商家)

請求:
GET /order
響應:
HTTP/1.1 200 OK
[
 {
 "order_id": 1,
 "table_id": "1",
 "time": "2019-05-15 12:00",
 "dishes": [
 {
 "dish_id": 1,
 "name": "宮保雞丁",
 "price": 1800
 },
 {
 "dish_id": 2,
 "name": "京醬肉絲",
 "price": 1900
 }
 ],
 "state": 0,
 "consume": 3700, // 表示該訂單的價格
 }
] 

2、封裝 API (Cpp) 

MySQL-API 官方手冊:https://dev.mysql.com/doc/

使用 JSON 作爲數據交互格式,JSON 出自 JavaScript,是一種非常方便的鍵值對數據組織格式, C++ 中可以使用 jsoncpp 這個庫來解析和構造 JSON 數據。

1、連接 / 斷開MySQL

//初始化MySQL
static MYSQL* MySQLInit(){
    //創建句柄  
    MYSQL* mysql = mysql_init(NULL);
    //建立連接
    if(mysql_real_connect(mysql,"127.0.0.1","root","","order_system",3306,NULL,0) == NULL){
        printf("Connect failed %s\n",mysql_error(mysql));
        return NULL;
    }
    //設置編碼格式
    mysql_set_character_set(mysql,"utf8");
    return mysql
}
//斷開MySQL
static void MySQLRelease(MYSQL* mysql){
    mysql_close(mysql);
}

2、菜品管理API

class DishTable{
public:
    DishTable(MYSQL* mysql):
        _mysql(mysql)
    {}
    bool Insert(const Json::Value& dish){
        //拼寫MySQL語句
        char sql[1024 * 4] = {0};
        sprintf(sql,"insert into dish_table values(null,'%s',%d)"
            ,dish["name"].asCString(),dish["price"].asInt());
        //執行MySQL語句
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Dishtable insert failed! %s\n",mysql_error(_mysql));
            return false;
        }
        printf("Dishtable insert finished!\n");
        return true;
    }
    bool SelectAll(Json::Value* dishes){
        //拼寫MySQL語句
        char sql[1024 * 4] = {0};
        sprintf(sql,"select * from dish_table");
        //執行MySQL
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Dishtable selectall failed! %s\n",mysql_error(_mysql));
            return false;
        }
        //構造結果
        MYSQL_RES* result = mysql_store_result(_mysql);
        if(result == NULL{
            printf("Dishtable selectall result failed! %s\n",mysql_error(_mysql));
            return false;
        }
        //獲取行數
        int rows = mysql_num_rows(result);
        for(int i = 0;i < rows;++i){
            Json::Value dish;
            dish["dish_id"] = atoi(row[0]);
            dish["name"] = row[1];
            dish["price"] = atoi(row[2]);
            dishes->append(dish);
        }
        //釋放資源!!!!!!!
        mysql_free_result(result);
        printf("Dishtable selectall finished!\n");
        return true;
    }
    bool SelectOne(int32_t dish_id,Json::Value* dish){
        char sql[1024 * 4] = {0};
        sprintf(sql,"select * from dish_table where dish_id=%d",dish_id);
        int ret = mysql_query(_mysq,sql);
        if(ret != 0){
            printf("Dishtable selectone failed! %s\n",mysql_error(_mysql));
            return false;
        }
        MYSQL_RES* result = mysql_store_result(_mysql);
        if(result == NULL){
            printf("Dishtable selectone result failed! %s\n",mysql_error(_mysql));
        }
        int rows = mysql_num_rows(result);
        if(rows != 1){
            printf("The number of rows is not one! rows=%d\n",rows);
            return false;
        }
        for(int i = 1;i < rows;++i){
            (*dish)["dish_id"] = atio(rows[0]);
            (*dish)["name"] = rows[1];
            (*dish)["price"] = atoi(rows[2]);
            break;
        }
        //釋放數據!!!!!!!!!
        mysql_free_result(result);
        printf("Dishtable selectone finished!\n");
        return true;
    }
    bool Update(const Json::Value& dish){
        char sql[1024 * 4] = {0};
        sprintf(sql,"update dish_table set name='%s',price=%d where dish_id=%d",
            dish["name"].asCString(),dish["price"].asInt(),dish["dish_id"].asInt());
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Dishtable update failed! %s\n",mysql_error(_mysql));
            return false;
        }
        printf("Dishtable update finished!\n");
        return true;
    }
    bool Delete(int dish_id){
        char sql[1024 * 4] = {0};
        sprintf(sql,"delete from dish_table where dish_id=%d",dish_id);
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Dishtable delete failed! %s\n",mysql_error(_mysql));
            return false;
        }
        printf("Dishtable delete finished!\n");
        return true;
    }
private:
    MYSQL* _mysql;
};

3、訂單管理API

class ordertable{
public:
    ordertable(MYSQL* mysql):
        _mysql(mysql)
    {}
    bool SelectAll(Json::Value* orders) {
         char sql[1024 * 4] = {0};
         sprintf(sql,"select * from order_table");
         int ret = mysql_query(_mysql,sql);
         if(ret != 0){
            printf("Ordertable selectall failed! %s\n",mysql_error(_mysql));
            return false;
         }
         MYSQL_RES* result = mysql_store_result(_mysql);
         if(result == NULL){
             printf("Ordertable selectall result failed! %s\n",mysql_error(_mysql));
             return false;
         }
         int rows = mysql_num_rows(result);
         for(int i = 0;i < rows;++i){
            MYSQL_ROW row = mysql_fetch_row(result);
            Json::Value order;
            order["order_id"] = atoi(row[0]);
            order["table_id"] = row[1];
            order["time"] = row[2];
            order["dish_ids_str"] = row[3];
            order["state"] = atoi(row[4]);
            order->append(order); 
        }
        //釋放資源
        mysql_free_result(result);
        printf("Ordertable selectall finished!\n");
        return true;
    }
    bool Insert(const Json::Value& order) {
        char sql[1024 * 4] = {0};
        sprintf(sql,"insert into order_table values(null,'%s','%s','%s',%d)",
            order["table_id"].asCString(),order["time"].asCString(),
            order["dishes"].asCString(),order["state"].asInt());
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Ordertable insert failed! %s\n",mysql_error(_mysql));
            return false;
        }
        printf("Ordertable insert finished!\n");
        return true;
    }
    bool ChangeState(const Json::Value& order) {
        char sql[1024 * 4] = {0};
        sprintf(sql,"update order_table set state=%d where dish_id=%d",
            order["state"].asInt(),order["disd_id"].asInt());
        int ret = mysql_query(_mysql,sql);
        if(ret != 0){
            printf("Ordertable changestate failed! %s\n",mysql_error(_mysql));
            return false;
        }
        printf("Ordertable changestate finished!\n");
        return true;
    } 
private:
    MYSQL* _mysql;
};

3、構造HTTP請求

運用到了GitHub上面一位大佬的庫:https://github.com/ClivenZ/cpp-httplib

不得不說這個庫還是很強大的,而且大佬寫了很詳細得使用手冊,值得借鑑,主體就是這樣的:

#include <httplib.h>

int main(void)
{
    using namespace httplib;

    Server svr;

    svr.Get("/hi", [](const Request& req, Response& res) {
        res.set_content("Hello World!", "text/plain");
    });

    svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
        auto numbers = req.matches[1];
        res.set_content(numbers, "text/plain");
    });

    svr.Get("/stop", [&](const Request& req, Response& res) {
        svr.stop();
    });

    svr.listen("localhost", 1234);
}

這裏面遇到了兩個知識點:正則表達式、lamad表達式(C++11):

正則表達式:https://www.cnblogs.com/guozht/p/7610877.html

lambda表達式:https://blog.csdn.net/fjzpdkf/article/details/50249287

 

三、服務端

1、幾個前端小知識

HTML:

超文本標記語言,標準通用標記語言的下一個應用。HTML不是以一種編程語言,而是一種標記語言,是製作網頁所必備的。“超文本”就是指頁面內可以包含圖片、鏈接、音樂、程序等非文字元素。

CSS:

層疊樣式表是一種用來表現HTML等文件樣式的計算機語言,說簡單一點就是用來支撐一個網頁的顏值的。

JavaScript:

JS是一種直譯式腳本語言,是一種動態類型、弱類型、基於原型的語言,在HTML中使用,用來給網頁增加動態功能。

jQuery:

jQuery是一個快速、間接的JS框架,提供一種簡便的JS設計模式,優化HTML文檔操作、時間處理、動畫設計和Ajax進行交互。

Ajax:

Ajax的本意就是異步JavaScript和XML,是指一種創建交互式網頁應用的網頁開發技術。主要是用於創建快速動態網頁的技術,特點是在無需重新加載整個網頁的情況下,就能更新部分網頁的技術。

通過在後臺與服務器進行少量的數據交換,Ajax可以使網頁實現異步更新。

Vue.js:

Vue是一套構建用戶界面的漸進式JavaScript框架,Vue可以自底向上逐層應用,Vue的核心庫只關注視圖層,方便與第三方庫或既有項目進行整合。

2、資料推薦

w3cshcool:https://www.w3school.com.cn/

Vue官方文檔:https://cn.vuejs.org/

 

 

發佈了79 篇原創文章 · 獲贊 30 · 訪問量 9970
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章