【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 篇原创文章 · 获赞 28 · 访问量 7740

猜你喜欢

转载自blog.csdn.net/weixin_43753894/article/details/98753803