C++Web框架Drogon

2021-11-09 23:22:28 1746

Drogon是一个基于C++14/17的Http应用框架,使用Drogon可以方便的使用C++构建各种类型的Web应用服务端程序。

Drogon的主要应用平台是Linux,也支持Mac OS、FreeBSD和Windows。

它的主要特点如下:

  • 网络层使用基于epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见TFB Tests Results;
  • 全异步编程模式;
  • 支持Http1.0/1.1(server端和client端);
  • 基于template实现了简单的反射机制,使主程序框架、控制器(controller)和视图(view)完全解耦;
  • 支持cookies和内建的session;
  • 支持后端渲染,把控制器生成的数据交给视图生成Html页面,视图由CSP模板文件描述,通过CSP标签把C++代码嵌入到Html页面,由drogon的命令行工具在编译阶段自动生成C++代码并编译;
  • 支持运行期的视图页面动态加载(动态编译和加载so文件);
  • 非常方便灵活的路径(path)到控制器处理函数(handler)的映射方案;
  • 支持过滤器(filter)链,方便在控制器之前执行统一的逻辑(如登录验证、Http Method约束验证等);
  • 支持https(基于OpenSSL实现);
  • 支持websocket(server端和client端);
  • 支持Json格式请求和应答, 对Restful API应用开发非常友好;
  • 支持文件下载和上传,支持sendfile系统调用;
  • 支持gzip/brotli压缩传输;
  • 支持pipelining;
  • 提供一个轻量的命令行工具drogon_ctl,帮助简化各种类的创建和视图代码的生成过程;
  • 基于非阻塞IO实现的异步数据库读写,目前支持PostgreSQL和MySQL(MariaDB)数据库;
  • 基于线程池实现sqlite3数据库的异步读写,提供与上文数据库相同的接口;
  • 支持ARM架构;
  • 方便的轻量级ORM实现,支持常规的对象到数据库的双向映射操作;
  • 支持插件,可通过配置文件在加载期动态拆装;
  • 支持内建插入点的AOP

安装

Ubuntu 20.04

环境

sudo apt install git
sudo apt install gcc
sudo apt install g++
sudo apt install cmake

jsoncpp

sudo apt install libjsoncpp-dev

uuid

sudo apt install uuid-dev

OpenSSL

sudo apt install openssl
sudo apt install libssl-dev

zlib

sudo apt install zlib1g-dev

postgresql

sudo apt-get install postgresql-all

构建

cd $WORK_PATH
git clone https://github.com/an-tao/drogon
cd drogon
git submodule update --init
mkdir build
cd build
cmake ..
make && sudo make install

使用

drogon_ctl create project web-test

在clion中打开

入口函数

#include <drogon/drogon.h>
int main() {
    drogon::app().addListener("0.0.0.0", 80);
    drogon::app().run();
    return 0;
}

创建一个位于demo v1名称空间内且名称为User的控制器

drogon_ctl create controller -h demo::v1::User

demo_v1_User.h如下

#pragma once
#include <drogon/HttpController.h>
using namespace drogon;
namespace demo
{
    namespace v1
    {
        class User:public drogon::HttpController<User>
        {
        public:
            METHOD_LIST_BEGIN
                //use METHOD_ADD to add your custom processing function here;
                METHOD_ADD(User::login,"/token?userId={1}&passwd={2}",Post);
                METHOD_ADD(User::getInfo,"/{1}/info?token={2}",Get);
            METHOD_LIST_END
            //your declaration of processing function maybe like this:
            void login(const HttpRequestPtr &req,
                       std::function<void (const HttpResponsePtr &)> &&callback,
                       std::string &&userId,
                       const std::string &password);
            void getInfo(const HttpRequestPtr &req,
                         std::function<void (const HttpResponsePtr &)> &&callback,
                         std::string userId,
                         const std::string &token) const;
        };
    }
}

demo_v1_User.cc如下

#include "demo_v1_User.h"
using namespace demo::v1;
//add definition of your processing function here

void User::login(const HttpRequestPtr &req,
           std::function<void (const HttpResponsePtr &)> &&callback,
           std::string &&userId,
           const std::string &password)
{
    LOG_DEBUG<<"User "<<userId<<" login";
    //认证算法,读数据库,验证身份等...
    //...
    Json::Value ret;
    ret["result"]="ok";
    ret["token"]=drogon::utils::getUuid();
    auto resp=HttpResponse::newHttpJsonResponse(ret);
    callback(resp);
}
void User::getInfo(const HttpRequestPtr &req,
             std::function<void (const HttpResponsePtr &)> &&callback,
             std::string userId,
            const std::string &token) const
{
    LOG_DEBUG<<"User "<<userId<<" get his information";
    //验证token有效性等
    //读数据库或缓存获取用户信息
    Json::Value ret;
    ret["result"]="ok";
    ret["user_name"]="Jack";
    ret["user_id"]=userId;
    ret["gender"]=1;
    auto resp=HttpResponse::newHttpJsonResponse(ret);
    callback(resp);
}

运行

浏览器访问

http://localhost/demo/v1/user/token?userId=123&passwd=qwe

返回

{
    "result": "ok",
    "token": "48C77F7F6B5F46909ACAEDE6D75DAAC0"
}

http://localhost/demo/v1/user/123456/info?token=8922CE8AE70641AAA4BB03810C40F2F2

返回

{
    "gender": 1,
    "result": "ok",
    "user_id": "123456",
    "user_name": "Jack"
}




JsonCpp 编译安装使用

JsonCpp 编译安装使用

下载源码 https://github.com/open-source-parsers/jsoncpp打开cmake-gui填路径依次点击 configure / generate用visual studio打开 jsoncpp.sln根据用途编译对应目标visual studio 项目配置对应头文
2023-11-19

Crypto++ AES加密和解密

安装源码下载 https://cryptopp.com/#download用visual studio打开项目cryptlib项目属性中配置Debug/x64, C/C++ > 代码生成中 配置运行库为MDd, 要保持和引用项目一致生成目录x64\Output\Debug\cryptlib.lib下
2023-11-18

C++ 类型转换操作符重载

示例template <typename T> operator T () const { } Poco库中的使用Var.hPoco::Dynamic::Var template <typename T> operator T () const { VarHolder* pHolder =
2022-08-30

CMake 链接静态库 示例

现有库lib-a, lib-b可执行文件final链接情况lib-b 静态链接 lib-a, final静态链接lib-b 和 lib-a, 且final同样静态编译lib-aCMakeLists.txtcmake_minimum_required(VERSION 3.19) project(lib
2022-08-24

CMake 链接 OpenSSL 静态库

示例CMakeLists.txt如下cmake_minimum_required(VERSION 3.5) project(test CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unu
2022-08-23

C++ 获取当前时间并格式化

#include <chrono> #include <ctime> #include <iomanip> #include <sstream> using namespace std; int main(int argc, char **argv) { // 获取本地时间 au
2022-08-20

C++ 获取Windows环境变量

#include <windows.h> string getValue(const char* env) { string value = ""; char valueArr[1024] = { 0 }; unsigned int pathSize = GetEnvi
2022-02-10

C++Web框架Drogon

Drogon是一个基于C++14/17的Http应用框架,使用Drogon可以方便的使用C++构建各种类型的Web应用服务端程序。Drogon的主要应用平台是Linux,也支持Mac OS、FreeBSD和Windows。它的主要特点如下:网络层使用基于epoll(macOS/FreeBSD下是kq
2021-11-09

C++ Web 框架 Oat++

Oat++轻量、跨平台、高性能、完全零依赖Oat++ 主页:https://oatpp.ioOat++ 文档:https://oatpp.io/docs/startGitHub 地址:https://github.com/oatpp/oatpp其主要特性有:随处运行Oat++ 没有任何依赖性,可以很
2021-10-25
Java JNI 调用 C++方法 基于 IDEA Visual Stutio 2019

Java JNI 调用 C++方法 基于 IDEA Visual Stutio 2019

JNIJava Native Interface首先写一个java类package com.test; public class JNI { //native关键字 public native int add(int a, int b); } 执行javah命令注意路径我的JN
2021-07-20

Visual Studio 2019 文件编码问题

Visual Studio 对 utf-8 的支持相当差.cpp/.h 文件先调出高级保存选项菜单, 具体百度设置文件字符编码为utf-8还不够, 还要在项目 => 属性 => C/C++ => 所有选项 => 附加选项 中 设置 /utf-8.rc 文件默认编码gbk, 加了特殊字符无法显示然后改
2021-07-18

Visual Studio 2019编译QT5.12.0 x64

下载源码https://download.qt.io/archive/qt/5.12/5.12.0/single/编译工具Perlhttps://strawberryperl.com/download/5.26.3.1/strawberry-perl-5.26.3.1-64bit-portable.
2021-07-14

C++中友元函数不能重载的运算符

C++规定有四个运算符 =, ->, [], () 不可以是全局域中的重载(即不能重载为友员函数)当把赋值运算符重载为类的友员函数,在程序中执行类对象的赋值语句时,程序就会出现两种矛盾的选择。1、因为它认为类中并没有重载赋值运算符的成员函数,所以它根据C++的规则,会去调用相应的构造函数。2、但是在
2021-07-11

C++复制构造函数几种特殊情况

一int main() { Test cc; //会调用拷贝构造函数 将cc赋值给dd, 因为dd不存在(没有初始化), 所以需要调用拷贝构造函数进行初始化 Test dd = cc; cout << &cc << endl; cout << &dd << e
2021-07-05

freemarker 时间显示不正常 设置时区

项目在本地开发的时候显示正常,部署上服务器就一直差8个小时,最后发现freemarker官方文档有这样的说明time_zone:时区的名称来显示并格式化时间。 默认情况下,使用JVM的时区。 也可以是 Java 时区 API 接受的值,或者 "JVM default" (从 FreeMarker 2
2020-03-28
IDEA 2019.1 xml 不高亮

IDEA 2019.1 xml 不高亮

前几天更新了idea后,发现xml里的代码都没有了高亮,变得跟记事本一个德性了打开setting ,搜索 File Types,找到xml项, 查看下方的匹配格式,果然没有xml,(idea真是厉害)点击右方的+,输入*.xml,点击ok,解决问题
2020-03-28

npm install 淘宝镜像

npm install --registry=https://registry.npm.taobao.org
2020-03-28
Java中方法的参数传递机制

Java中方法的参数传递机制

来看一段代码 public class Man { private String name; private Integer age; public String getName() { return name; } publi
2020-03-28
基于自定义注解手写权限控制

基于自定义注解手写权限控制

方法一: AOP 方法二: 拦截器项目结构项目依赖<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-w
2020-03-28

Docker 部署 详细全过程 附代码

Docker 部署本站 全过程环境:CentOS7.61. 安装Docker其他版本CentOS可以参考这个https://help.aliyun.com/document_detail/187598.html查看本机内核版本,内核版本需高于 3.10uname -r 确保 yum 包最新yum u
2020-03-28

SpringBoot 启动普通java工程

引入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
2020-03-28

Vue.js DOM操作

<template> <input type="button" @click="reply($event)" value="回复"> </template> export default { methods: { replyFun(e) {
2020-03-29
CentOS7编译调试OpenJDK12

CentOS7编译调试OpenJDK12

1. 下载源码https://hg.openjdk.java.net/jdk/jdk12点击左侧的browse,再点击zip,就可以下载zip格式的源码压缩包。unzip xxx.zip 解压文件2. 安装jdkyum install java-11-openjdk-devel -y3. 运行con
2020-04-23
编写自己的Spring Boot Starter

编写自己的Spring Boot Starter

1.新建一个maven项目命名规则统一是xxx-spring-boot-starter完整pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"
2020-06-29