C ++ 也可以搭建Web?高性能的 C++ Web 开发框架 CPPCMS + MySQL 实现快速入门案例

什么是CPPCMS?

CppCMS 是一个高性能的 C++ Web 开发框架,专为构建快速、动态的网页应用而设计,特别适合高并发和低延迟的场景。其设计理念类似于 Python 的 Django 或 Ruby on Rails,但针对 C++ 提供了更细粒度的控制和更高效的性能。

主要特点和优点

1. 高性能与并发处理

CppCMS 是为高性能需求而设计的。它支持大规模并发处理,能够在高负载下高效运行,特别适用于需要处理大量请求的场景。由于使用 C++ 编写,CppCMS 可以利用操作系统的原生线程和异步 I/O 操作,提供极低的延迟和高吞吐量。

2. 灵活的架构

框架的设计允许开发者完全控制应用程序的各个方面,包括 URL 路由、会话管理、缓存机制、和表单处理。你可以根据具体需求自定义应用程序的各个模块,从而适应各种特殊的应用场景。

3. 集成与兼容性

CppCMS 能轻松与其他 C++ 库和系统组件集成,充分利用现有的 C++ 生态系统。它支持 SQLite、MySQL、PostgreSQL 等多种数据库,并提供了与 C++ 标准库的无缝集成。

4. 模板系统

CppCMS 提供了一个高效的模板系统,支持静态和动态内容的渲染。开发者可以在模板中定义页面布局和内容,通过与后端代码的结合,实现动态网页的生成。

5. 国际化和本地化

框架内置了对国际化(i18n)和本地化(l10n)的支持,适合开发多语言应用。开发者可以轻松管理和应用不同语言的文本和格式设置。

适用场景

  • 高流量网站:如社交媒体平台、新闻门户网站等,需要处理大量用户请求。
  • 实时数据处理:如在线游戏服务器、实时消息传递系统,要求极低的响应时间。
  • 复杂后台服务:如需要提供高性能 RESTful API 或者后台服务的系统。

简单入门案例

1. 项目结构

在这里插入图片描述

2. CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(c_web)set(CMAKE_CXX_STANDARD 17)# 指定源文件
set(SOURCE_FILES src/main.cpp src/blog.cpp)# 手动设置 CppCMS 和 Booster 的头文件路径
include_directories(/usr/local/include)# 手动设置库文件路径
link_directories(/usr/local/lib)# 添加可执行文件
add_executable(c_web ${SOURCE_FILES})# 查找数据库
include_directories(/usr/include/cppconn /usr/include/mysql)
link_directories(/usr/lib/x86_64-linux-gnu)# 链接 CppCMS 和 Booster 库 MySQL
target_link_libraries(c_web cppcms booster mysqlcppconn)

说明:自行安装所需要的依赖库和定位库的位置,以下是获取手动安装的cppcms,其他通过apt安装的自行查找库依赖和位置。

获取编译器标志

pkg-config --cflags cppcms

获取链接器标志

pkg-config --libs cppcms

3. config.json

{"service": {"api": "http","port": 8080,"ip": "0.0.0.0"},"http": {"script": "","static": "/static"}
}

4. main.cpp

#include <cppcms/service.h>
#include <cppcms/applications_pool.h>
#include <cppcms/http_response.h>
#include <cppcms/url_dispatcher.h>
#include "blog.h"
#include <cppcms/json.h>int main(int argc, char* argv[]) {try {cppcms::service app(argc, argv);// 创建博客应用的实例并将其添加到应用程序池中app.applications_pool().mount(cppcms::applications_factory<blog>());// 运行服务app.run();}catch (std::exception const &e) {std::cerr << "Error: " << e.what() << std::endl;}
}

5. blog.h

#ifndef BLOG_H
#define BLOG_H
#include <cppcms/application.h>
#include <cppcms/http_response.h>
#include <cppcms/http_request.h>
#include <cppcms/url_dispatcher.h>
#include <cppcms/url_mapper.h>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
class blog : public cppcms::application {
public:blog(cppcms::service &srv);void index();void show_register();void handle_register();void show_login();void handle_login();std::unique_ptr<sql::Connection> connectToDatabase();void createDatabase(sql::Connection* con, const std::string& dbName);void createTable(sql::Connection* con);
private:void serve_html(const std::string &path);
};
#endif

6. blog.cpp

#include "blog.h"
#include <fstream>blog::blog(cppcms::service &srv) : cppcms::application(srv) {dispatcher().map("GET", "/", &blog::index, this);dispatcher().map("GET", "/register", &blog::show_register, this);dispatcher().map("POST", "/register", &blog::handle_register, this);dispatcher().map("GET", "/login", &blog::show_login, this);dispatcher().map("POST", "/login", &blog::handle_login, this);
}std::unique_ptr<sql::Connection> blog::connectToDatabase() {sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();std::unique_ptr<sql::Connection> con(driver->connect("tcp://127.0.0.1:3306", "root", "123456"));con->setSchema("blog");return con;
}void blog::index() {serve_html("./views/index.html");
}void blog::show_register() {serve_html("./views/register.html");
}void blog::createDatabase(sql::Connection* con, const std::string& dbName) {std::unique_ptr<sql::Statement> stmt(con->createStatement());stmt->execute("CREATE DATABASE IF NOT EXISTS " + dbName);stmt->execute("USE " + dbName);
}void blog::createTable(sql::Connection* con) {std::unique_ptr<sql::Statement> stmt(con->createStatement());stmt->execute("CREATE TABLE IF NOT EXISTS users (""id INT AUTO_INCREMENT PRIMARY KEY,""username VARCHAR(255) NOT NULL,""password VARCHAR(255) NOT NULL,""email VARCHAR(255) NOT NULL"")");
}void blog::handle_register() {std::string username = request().post("username");std::string password = request().post("password");std::string email = request().post("email");try {auto con = connectToDatabase();createDatabase(con.get(), "blog");createTable(con.get());std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("INSERT INTO users(username, password, email) VALUES (?, ?, ?)"));pstmt->setString(1, username);pstmt->setString(2, password);pstmt->setString(3, email);pstmt->executeUpdate();response().out() << "<p>User registered successfully: " << username << "</p>"<< "<p>Registered password: " << password << "</p>"<< "<p>Registered email: " << email << "</p>";} catch (sql::SQLException &e) {response().out() << "<p>Error registering user: " << e.what() << "</p>";}
}void blog::show_login() {serve_html("./views/login.html");
}void blog::handle_login() {std::string username = request().post("username");std::string password = request().post("password");try {auto con = connectToDatabase();std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("SELECT password FROM users WHERE username = ?"));pstmt->setString(1, username);std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());if (res->next()) {std::string stored_password = res->getString("password");if (stored_password == password) {response().out() << "<p>Logged in successfully as: " << username << "</p>";} else {response().out() << "<p>Invalid password.</p>";}} else {response().out() << "<p>User not found.</p>";}} catch (sql::SQLException &e) {response().out() << "<p>Error: " << e.what() << "</p>";}
}void blog::serve_html(const std::string &path) {std::ifstream file(path);if (file.is_open()) {std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());response().out() << content;} else {response().status(404);response().out() << "Page not found";}
}

7. login.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Login</title><!-- 引入 FontAwesome 图标库 --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"><style>/* 全局样式 */body {font-family: 'Helvetica Neue', Arial, sans-serif;background-color: #fdfdfd;color: #333;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-image: url('https://source.unsplash.com/1600x900/?nature,water');background-size: cover;background-position: center;}/* 表单容器 */.form-container {background-color: rgba(255, 255, 255, 0.9);padding: 30px 40px;border-radius: 10px;box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);max-width: 400px;width: 100%;box-sizing: border-box;backdrop-filter: blur(10px);}/* 标题 */.form-container h1 {text-align: center;margin-bottom: 20px;font-size: 26px;color: #555;font-weight: 300;}/* 表单项 */.form-group {position: relative;margin-bottom: 20px; /* 调整了间距,减小输入框间的距离 */}.form-group input {width: 100%;padding: 12px 40px 12px 40px; /* 调整了内边距,确保图标和标签都能正确显示 */border: 1px solid #ddd;border-radius: 5px;box-sizing: border-box;font-size: 16px;background-color: #fdfdfd;transition: border-color 0.3s ease;}.form-group input:focus {border-color: #888;outline: none;}.form-group label {position: absolute;left: 40px;top: 50%;transform: translateY(-50%);color: #aaa;font-size: 16px;transition: all 0.3s ease;pointer-events: none;}.form-group input:focus + label,.form-group input:not(:placeholder-shown) + label {top: -10px;left: 40px;font-size: 12px;color: #555;background-color: white;padding: 0 5px;}.form-group .fa {position: absolute;left: 15px; /* 图标距离输入框左侧的距离 */top: 50%;transform: translateY(-50%);color: #888;font-size: 18px; /* 调整了图标大小 */}/* 提交按钮 */.form-group button {width: 100%;padding: 12px 15px;background-color: #333;border: none;border-radius: 5px;color: white;font-size: 16px;cursor: pointer;transition: background-color 0.3s ease;font-weight: 500;}.form-group button:hover {background-color: #555;}/* 响应式设计 */@media (max-width: 480px) {.form-container {padding: 20px 30px;}.form-container h1 {font-size: 22px;}.form-group input {padding: 10px 30px 10px 30px; /* 在小屏幕上调整内边距,确保输入框不拥挤 */}.form-group .fa {left: 10px; /* 在小屏幕上调整图标位置 */}.form-group label {left: 35px; /* 在小屏幕上调整标签位置 */}}</style>
</head>
<body><div class="form-container"><h1>Login</h1><form method="post" action="/login"><div class="form-group"><i class="fa fa-user"></i><input type="text" id="username" name="username" placeholder=" " required><label for="username">Username</label></div><div class="form-group"><i class="fa fa-lock"></i><input type="password" id="password" name="password" placeholder=" " required><label for="password">Password</label></div><div class="form-group"><button type="submit">Login</button></div></form><div class="toggle-link"><a href="/register">Don't have an account? Register</a></div></div>
</body>
</html>

8. register.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Register</title><!-- 引入 FontAwesome 图标库 --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"><style>/* 全局样式 */body {font-family: 'Helvetica Neue', Arial, sans-serif;background-color: #fdfdfd;color: #333;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-image: url('https://source.unsplash.com/1600x900/?nature,water');background-size: cover;}/* 表单容器 */.form-container {background-color: rgba(255, 255, 255, 0.9);padding: 20px 40px;border-radius: 10px;box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);max-width: 400px;width: 100%;box-sizing: border-box;backdrop-filter: blur(10px);}/* 标题 */.form-container h1 {text-align: center;margin-bottom: 20px;font-size: 26px;color: #555;font-weight: 300;}/* 表单项 */.form-group {position: relative;margin-bottom: 25px;}.form-group input {width: 100%;padding: 12px 15px 12px 40px;border: 1px solid #ddd;border-radius: 5px;box-sizing: border-box;font-size: 16px;background-color: #fdfdfd;transition: border-color 0.3s ease;}.form-group input:focus {border-color: #888;outline: none;}.form-group label {position: absolute;left: 40px;top: 50%;transform: translateY(-50%);color: #aaa;font-size: 16px;transition: all 0.3s ease;pointer-events: none;}.form-group input:focus + label,.form-group input:not(:placeholder-shown) + label {top: -10px;left: 40px;font-size: 12px;color: #555;background-color: white;padding: 0 5px;}.form-group .fa {position: absolute;left: 10px;top: 50%;transform: translateY(-50%);color: #888;}/* 提交按钮 */.form-group button {width: 100%;padding: 12px 15px;background-color: #333;border: none;border-radius: 5px;color: white;font-size: 16px;cursor: pointer;transition: background-color 0.3s ease;font-weight: 500;}.form-group button:hover {background-color: #555;}/* 响应式设计 */@media (max-width: 480px) {.form-container {padding: 15px 20px;}.form-container h1 {font-size: 22px;}}</style>
</head>
<body><div class="form-container"><h1>Register</h1><form method="post" action="/register"><div class="form-group"><i class="fa fa-user"></i><input type="text" id="username" name="username" placeholder=" " required><label for="username">Username</label></div><div class="form-group"><i class="fa fa-envelope"></i><input type="email" id="email" name="email" placeholder=" " required><label for="email">Email</label></div><div class="form-group"><i class="fa fa-lock"></i><input type="password" id="password" name="password" placeholder=" " required><label for="password">Password</label></div><div class="form-group"><button type="submit">Register</button></div></form><div class="toggle-link"><a href="/login">Already have an account? Login</a></div></div>
</body>
</html>

9. 验证测试

9.1 启动命令

cmake ./
make
./c_web -c ./config.json

在这里插入图片描述

说明:光标闪烁即启动成功了。

9.2 注册测试

在这里插入图片描述

9.3 注册结果

在这里插入图片描述

9.4 登录测试

在这里插入图片描述

9.5 登录结果

在这里插入图片描述

10. 总结

基于·Ubutun系统,通过 CppCMS + MySQL 实现简单的数据库连接和测试工作,即注册和登录操作完成快速入门。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用 1. 建议按文章顺序从头看是看 第一篇&#xff1a;一文大白话讲清楚啥是个webpack第二篇&#xff1a;一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建然后看本篇&#xff0c;Loader的配置…

速通Docker === 网络

目录 Docker网络详解 容器之间直接通信的弊端 &#xff08;一&#xff09;启动容器 &#xff08;二&#xff09;进入容器并发起请求 &#xff08;三&#xff09;请求流程 &#xff08;四&#xff09; 弊端分析 一、Docker网络基础 &#xff08;一&#xff09;容器IP分配…

Kafka 日志存储 — 日志索引

每个日志分段文件对应两个索引文件&#xff1a;偏移量索引文件用来建立消息偏移量到物理地址之间的映射&#xff1b;时间戳索引文件根据指定的时间戳来查找对应的偏移量信息。 1 日志索引 Kafka的索引文件以稀疏索引的方式构造消息的索引。它并不保证每个消息在索引文件中都有…

空调可视化监控与管理系统

随着智能化技术的不断发展&#xff0c;空调系统作为现代建筑、工业和商业场所的核心设备&#xff0c;正在从传统管理模式向智能化管理迈进。无论是大型商业楼宇、工业厂房&#xff0c;还是数据中心的精密空调&#xff0c;如何通过智能监控和高效管理降低能耗、提升运行效率&…

3.3 OpenAI GPT-4, GPT-3.5, GPT-3 模型调用:开发者指南

OpenAI GPT-4, GPT-3.5, GPT-3 模型调用:开发者指南 OpenAI 的 GPT 系列语言模型,包括 GPT-4、GPT-3.5 和 GPT-3,已经成为自然语言处理领域的标杆。无论是文本生成、对话系统,还是自动化任务,开发者都可以通过 API 调用这些强大的模型来增强他们的应用。本文将为您详细介…

用户中心项目教程(五)---MyBatis-Plus完成后端初始化+测试方法

文章目录 1.数据库的链接和创建2.建库建表语句3.引入依赖4.yml配置文件5.添加相对路径6.实体类的书写7.Mapper接口的定义8.启动类的指定9.单元测试10运行时的bug 1.数据库的链接和创建 下面的这个就是使用的我们的IDEA链接这个里面的数据库&#xff1a; 接下来就是输入这个用户…

Azure Synapse Dedicated SQL Pool实用命令语句

一、数据管理相关命令 1. 数据加载 COPY 命令&#xff1a;用于从外部存储&#xff08;如 Azure Blob 存储&#xff09;加载数据到 Dedicated SQL Pool 中。 COPY INTO [dbo].[target_table] FROM https://<storage_account>.blob.core.windows.net/<container>/…

products页面出现多选框后,能够直接将勾选的products删除吗?而不用跳转到flow再删除。例如将勾选的products传给flow

在标准的「Opportunity Products」(机会产品) 相关列表上&#xff0c;Salesforce 并不直接支持多选后一次性删除的功能。如果你想要在“同一页面”直接勾选然后删除&#xff0c;而不跳转到单独的 Flow 界面&#xff0c;通常需要借助自定义开发的方式来实现。下面给你几种可行的…

AI软件栈:中间表示

概念 编译器通常可以分为前端、优化器和后端三个部分中间表示属于变异过程中表达源程序的方法,作为单独的表示语言。将不同的前端语言(例如C、python、Java等)描述转换为中间表示。优化器对中间表示进行转换和优化,输出新的中间表示。后端将优化后的中间表示转换为特定硬件…

C++:深入理解const_iterator的应用

在 C 的标准模板库&#xff08;STL&#xff09;中&#xff0c;迭代器&#xff08;iterator&#xff09;是操作容器的重要工具&#xff0c;用于在容器的元素上进行遍历或操作。const_iterator 是迭代器的一种&#xff0c;用于只读访问容器中的元素&#xff0c;而不能修改它们的值…

LeetCode hot 力扣热题100 二叉树的最大深度

class Solution { public:int maxDepth(TreeNode* root) {if (root nullptr) {return 0;}int l_depth maxDepth(root->left);int r_depth maxDepth(root->right);return max(l_depth, r_depth) 1;} }; 代码作用 该函数通过递归计算二叉树的最大深度&#xff08;从根节…

Mysql InnoDB B+Tree是什么?

“mysql中常用的数据库搜索引擎InnoDB,其索引通过BTree的方式进行构建。” 实在想不起来BTree是怎么一回事了。以点带线&#xff0c;将涉及到的数据结构一起复习一下。 文章目录 数据结构定义红黑树定义使命 BTree定义使命 BTree定义 InnoDB BTree 旋转与调整二叉排序树插入删…

MATLAB基础应用精讲-【数模应用】粒子群与遗传算法相结合(PSO-GA)应用(附MATLAB代码实现)

目录 前言 几个高频面试题目 遗传算法、粒子群优化算法和强化学习对比 1 遗传算法(Genetic Algorithm, GA) 2 粒子群优化算法(Particle Swarm Optimization, PSO) 3 强化学习(Reinforcement Learning, RL) 4 遗传算法、粒子群优化算法和强化学习在智能方面的比较。…

对人型机器人的研究和展望

目录 概述 1 核心软硬件部件 1.1 运动控制部分 1.1.1 减速机 1.1.2 编码器 1.1.3 直流无刷电机 1.2 智能仿生手 1.3 控制板卡 2 人型机器人的应用 3 未来展望 概述 如果现在有人问&#xff1a;当前那个行业最火&#xff1f;毫无疑问答案肯定是人型机器人了。当前各类机…

Flask:后端框架使用

文章目录 1、介绍2、demo演示3、Flask请求和响应 3.1 演示demo3.2 request获取请求体数据3.3 requests发送请求3.4 响应返回和接收 4、特殊路由 4.1 路由重定向4.2 路由拦截器 1、介绍 Flask是由python语言编写的轻量级Web应用框架&#xff0c;主要应用于后端框架&#xff…

递归算法学习v2.3

目标和 设置全局变量&#xff1a; class Solution {int ret,path,aim;public int findTargetSumWays(int[] nums, int target) {aim target;dfs(nums,0);return ret;}public void dfs(int[] nums,int pos){if(pos nums.length){if(path aim){ret ;}return;}path nums[pos…

红黑树封装map和set(c++版)

前言 在前面&#xff0c;我们介绍了c中map和set库的使用&#xff0c;也实现了一颗简单的红黑树。那么现在我们就利用这两部分的知识&#xff0c;实现一个简单的myMap和mySet。 源码阅读 在我们实现之前&#xff0c;我们可以阅读一些标准库的实现&#xff0c;学习标准库的实现…

Windows 服务程序实现鼠标模拟

cpp #include <windows.h> #include <fstream> #include <string> #include <tchar.h> #include <thread> #include <vector> #define SERVICE_NAME _T("MouseSimulationService") // 全局变量 SERVICE_STATUS g_Servi…

ui设计公司分享:浅色 UI 设计

在数字化产品琳琅满目的今天&#xff0c;用户对于界面的要求早已不止于功能的实现&#xff0c;更追求一种舒适、无压的交互体验。而浅色UI设计&#xff0c;凭借其独特的魅力&#xff0c;正逐渐成为众多设计师营造优质体验的首选。 一、浅色UI设计的视觉优势 &#xff08;一&a…

Nacos:使用PgSQL数据源

数据源插件开源仓库地址&#xff1a;nacos-datasource-extend-plugins 一、PostgreSQL数据库安装 1、本文使用Docker进行数据库的安装&#xff0c;使用docker命令拉取的PG14版本的数据库&#xff1a; docker pull postgres:14.6 2、创建PG容器并启动&#xff0c;映射了5432…