Oat++:现代C++高性能Web框架入门指南
什么是Oat++?
Oat++(也称为oatpp)是一个轻量级、高性能的现代C++ Web框架,专为构建可扩展的RESTful API和Web服务而设计。它采用纯C++17标准编写,不依赖任何外部库,提供了简洁直观的API,让开发者能够快速构建高效的网络应用程序。
核心特性
1. 零依赖设计
Oat++完全基于C++标准库构建,无需安装额外的第三方依赖,简化了部署和跨平台开发。
2. 高性能异步I/O
内置基于事件循环的异步I/O模型,支持高并发连接处理,适合构建高性能服务器应用。
3. 类型安全的API
利用C++模板和现代C++特性,提供编译时类型检查,减少运行时错误。
4. 简洁的声明式API
通过简单的代码即可定义REST端点,自动处理HTTP请求/响应序列化。
5. 跨平台支持
支持Linux、macOS、Windows等主流操作系统。
快速开始
安装Oat++
# 使用vcpkg安装 vcpkg install oatpp # 或使用CMake直接从源码构建 git clone https://github.com/oatpp/oatpp.git cd oatpp mkdir build && cd build cmake .. make install
第一个Oat++应用
下面是一个简单的”Hello World” REST API示例:
#include "oatpp/web/server/HttpConnectionHandler.hpp"
#include "oatpp/network/Server.hpp"
#include "oatpp/network/tcp/server/ConnectionProvider.hpp"
#include "oatpp/web/server/HttpRouter.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"
#include OATPP_CODEGEN_BEGIN(DTO)
// 定义数据传输对象(DTO)
class MessageDto : public oatpp::DTO {
DTO_INIT(MessageDto, DTO)
DTO_FIELD(String, message);
DTO_FIELD(Int32, status);
};
#include OATPP_CODEGEN_END(DTO)
// 创建控制器
class MyController : public oatpp::web::server::api::ApiController {
public:
MyController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper) {}
public:
// 定义端点
ENDPOINT("GET", "/hello", getHello) {
auto dto = MessageDto::createShared();
dto->message = "Hello World!";
dto->status = 200;
return createDtoResponse(Status::CODE_200, dto);
}
ENDPOINT("GET", "/hello/{name}", getHelloWithName,
PATH(String, name)) {
auto dto = MessageDto::createShared();
dto->message = "Hello " + name + "!";
dto->status = 200;
return createDtoResponse(Status::CODE_200, dto);
}
};
// 应用组件配置
class AppComponent {
public:
// 创建连接提供者
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
return oatpp::network::tcp::server::ConnectionProvider::createShared({"0.0.0.0", 8000, oatpp::network::Address::IP_4});
}());
// 创建路由器
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
return oatpp::web::server::HttpRouter::createShared();
}());
// 创建连接处理器
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
return oatpp::web::server::HttpConnectionHandler::createShared(router);
}());
// 创建对象映射器
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper)([] {
return oatpp::parser::json::mapping::ObjectMapper::createShared();
}());
};
// 主函数
void run() {
// 注册组件
AppComponent components;
// 获取路由器并添加控制器
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
auto controller = std::make_shared<MyController>(
OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper)
);
router->addController(controller);
// 获取连接处理器
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, connectionHandler);
// 获取连接提供者
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, connectionProvider);
// 创建服务器
oatpp::network::Server server(connectionProvider, connectionHandler);
OATPP_LOGI("MyApp", "Server running on port %s", connectionProvider->getProperty("port").toString()->c_str());
// 运行服务器
server.run();
}
int main() {
// 初始化环境
oatpp::base::Environment::init();
// 运行应用
run();
// 清理环境
oatpp::base::Environment::destroy();
return 0;
}
CMakeLists.txt 配置
cmake_minimum_required(VERSION 3.10)
project(my_oatpp_app)
set(CMAKE_CXX_STANDARD 17)
# 查找Oat++包
find_package(oatpp REQUIRED)
# 添加可执行文件
add_executable(${PROJECT_NAME} main.cpp)
# 链接Oat++库
target_link_libraries(${PROJECT_NAME}
oatpp
oatpp-swagger
pthread
)
实用示例:TODO列表API
下面是一个更完整的示例,展示如何构建一个简单的TODO列表REST API:
#include "oatpp/web/server/HttpConnectionHandler.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include <unordered_map>
#include <mutex>
#include OATPP_CODEGEN_BEGIN(DTO)
// TODO项DTO
class TodoDto : public oatpp::DTO {
DTO_INIT(TodoDto, DTO)
DTO_FIELD(Int64, id);
DTO_FIELD(String, title);
DTO_FIELD(String, description);
DTO_FIELD(Boolean, completed);
DTO_FIELD(String, createdAt);
};
// 创建TODO请求DTO
class CreateTodoDto : public oatpp::DTO {
DTO_INIT(CreateTodoDto, DTO)
DTO_FIELD(String, title);
DTO_FIELD(String, description);
};
// 更新TODO请求DTO
class UpdateTodoDto : public oatpp::DTO {
DTO_INIT(UpdateTodoDto, DTO)
DTO_FIELD(String, title);
DTO_FIELD(String, description);
DTO_FIELD(Boolean, completed);
};
#include OATPP_CODEGEN_END(DTO)
// 简单的内存存储
class TodoStore {
private:
std::unordered_map<int64_t, std::shared_ptr<TodoDto>> todos;
int64_t nextId = 1;
std::mutex mutex;
public:
std::shared_ptr<TodoDto> createTodo(const std::shared_ptr<CreateTodoDto>& dto) {
std::lock_guard<std::mutex> lock(mutex);
auto todo = TodoDto::createShared();
todo->id = nextId++;
todo->title = dto->title;
todo->description = dto->description;
todo->completed = false;
todo->createdAt = "2024-01-01T00:00:00Z"; // 实际应用中应该使用真实时间
todos[todo->id] = todo;
return todo;
}
std::shared_ptr<TodoDto> getTodo(int64_t id) {
std::lock_guard<std::mutex> lock(mutex);
auto it = todos.find(id);
if (it != todos.end()) {
return it->second;
}
return nullptr;
}
std::vector<std::shared_ptr<TodoDto>> getAllTodos() {
std::lock_guard<std::mutex> lock(mutex);
std::vector<std::shared_ptr<TodoDto>> result;
for (const auto& pair : todos) {
result.push_back(pair.second);
}
return result;
}
bool updateTodo(int64_t id, const std::shared_ptr<UpdateTodoDto>& dto) {
std::lock_guard<std::mutex> lock(mutex);
auto it = todos.find(id);
if (it != todos.end()) {
if (dto->title) it->second->title = dto->title;
if (dto->description) it->second->description = dto->description;
if (dto->completed) it->second->completed = dto->completed;
return true;
}
return false;
}
bool deleteTodo(int64_t id) {
std::lock_guard<std::mutex> lock(mutex);
return todos.erase(id) > 0;
}
};
// TODO控制器
class TodoController : public oatpp::web::server::api::ApiController {
private:
TodoStore todoStore;
public:
TodoController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper) {}
public:
// 创建TODO
ENDPOINT("POST", "/todos", createTodo,
BODY_DTO(std::shared_ptr<CreateTodoDto>, dto)) {
auto todo = todoStore.createTodo(dto);
return createDtoResponse(Status::CODE_201, todo);
}
// 获取所有TODO
ENDPOINT("GET", "/todos", getAllTodos) {
auto todos = todoStore.getAllTodos();
auto response = oatpp::web::protocol::http::outgoing::Response::createShared(
Status::CODE_200,
getDefaultObjectMapper()->writeToString(todos)
);
response->putHeader("Content-Type", "application/json");
return response;
}
// 获取单个TODO
ENDPOINT("GET", "/todos/{id}", getTodo,
PATH(Int64, id)) {
auto todo = todoStore.getTodo(id);
if (todo) {
return createDtoResponse(Status::CODE_200, todo);
}
return createResponse(Status::CODE_404, "Todo not found");
}
// 更新TODO
ENDPOINT("PUT", "/todos/{id}", updateTodo,
PATH(Int64, id),
BODY_DTO(std::shared_ptr<UpdateTodoDto>, dto)) {
if (todoStore.updateTodo(id, dto)) {
auto todo = todoStore.getTodo(id);
return createDtoResponse(Status::CODE_200, todo);
}
return createResponse(Status::CODE_404, "Todo not found");
}
// 删除TODO
ENDPOINT("DELETE", "/todos/{id}", deleteTodo,
PATH(Int64, id)) {
if (todoStore.deleteTodo(id)) {
return createResponse(Status::CODE_204, "");
}
return createResponse(Status::CODE_404, "Todo not found");
}
};
高级特性
中间件支持
Oat++支持中间件模式,可以轻松添加认证、日志记录等功能:
class LoggingMiddleware : public oatpp::web::server::handler::RequestInterceptor {
public:
std::shared_ptr<OutgoingResponse> intercept(const std::shared_ptr<IncomingRequest>& request) override {
OATPP_LOGI("Request", "%s %s",
request->getStartingLine().method.toString()->c_str(),
request->getStartingLine().path.toString()->c_str());
return nullptr; // 继续处理请求
}
};
数据库集成
Oat++可以轻松集成各种数据库。以下是使用oatpp-orm和oatpp-sqlite的示例:
#include "oatpp-sqlite/orm.hpp"
#include OATPP_CODEGEN_BEGIN(DTO)
class UserDto : public oatpp::DTO {
DTO_INIT(UserDto, DTO)
DTO_FIELD(Int64, id);
DTO_FIELD(String, username);
DTO_FIELD(String, email);
DTO_FIELD(String, created_at);
};
#include OATPP_CODEGEN_END(DTO)
class DatabaseComponent {
public:
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::provider::Provider<oatpp::sqlite::Connection>>, dbConnectionProvider)([] {
auto connectionProvider = std::make_shared<oatpp::sqlite::ConnectionProvider>("test.db");
return oatpp::sqlite::ConnectionPool::createShared(connectionProvider, 10);
}());
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::sqlite::Executor>, dbExecutor)([] {
OATPP_COMPONENT(std::shared_ptr<oatpp::provider::Provider<oatpp::sqlite::Connection>>, connectionProvider);
return std::make_shared<oatpp::sqlite::Executor>(connectionProvider);
}());
};
性能优势
Oat++在设计上注重性能: - 零拷贝数据序列化 - 高效的内存管理 - 基于事件循环的异步处理 - 最小化的运行时开销
适用场景
- 高性能API服务器 - 需要处理大量并发请求的REST API
- 微服务架构 - 轻量级服务间的通信
- 嵌入式系统 - 资源受限环境中的Web服务
- 实时应用 - 需要低延迟响应的应用
总结
Oat++为C++开发者提供了一个现代化、高性能的Web开发框架。它结合了现代C++的最佳实践和Web开发的需求,使得构建高性能网络应用变得更加简单和高效。无论是构建简单的REST API还是复杂的企业级应用,Oat++都能提供强大的支持。
通过其简洁的API设计、零依赖架构和出色的性能表现,Oat++正在成为C++ Web开发领域的重要选择之一。如果你正在寻找一个既保持C++性能优势又提供现代Web开发体验的框架,Oat++绝对值得尝试。




还没有评论,来说两句吧...