C++ Web Framework Oat++ Component

在前面例子中,我们在 run 函数中定义一系列需要的组件。这就使得对象的初始化工作和业务代码耦合在一起,如下代码:

void run() {

    // 1. HttpRouter 组件对象
    auto router = oatpp::web::server::HttpRouter::createShared();
    router->route("GET", "/hello", std::make_shared<Handler>());

    // 2. HttpConnectionHandler 组件对象
    auto conn_handler = oatpp::web::server::HttpConnectionHandler::createShared(router);

    // 3. ConnectionProvider 组件对象
    auto address = oatpp::network::Address({"localhost", 8000, oatpp::network::Address::IP_4});
    auto conn_provider = oatpp::network::tcp::server::ConnectionProvider::createShared(address);

    oatpp::network::Server server(conn_provider, conn_handler);

    // 6. 启动服务等待连接
    server.run();
}

Oat++ 提供了两个宏 OATPP_CREATE_COMPONENTOATPP_COMPONENT 来将组件对象的初始化工作从 run 函数中剥离到一个单独的文件中,这使得通过替换组件来配置应用程序变得容易。

1. OATPP_CREATE_COMPONENT

接下来,我们使用这两个宏来实现这一部分工作。首先创建一个 AppComponent.hpp,在该文件中使用 OATPP_CREATE_COMPONENT 宏来初始化需要的组件对象,如下代码所示:

#ifndef APPCOMPONENT_HPP
#define APPCOMPONENT_HPP

#include "oatpp/core/macro/component.hpp"
#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/web/server/HttpRequestHandler.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"


class AppComponent{
public:

    // oatpp::base::Environment::Component<std::shared_ptr<oatpp::web::server::HttpRouter>> router = oatpp::base::Environment::Component<std::shared_ptr<oatpp::web::server::HttpRouter>>(lambda)
    // 将 lambda 函数的返回值作为参数构建 Component, 此时 Compnent 持有了构建的对象
    // 将构建好的所有 Component 存储到 unordered_map 容器中,需要的时候使用 OATPP_COMPONENT 从中获取
    // OATPP_COMPONENT 多次按照类型获取的对象是同一个
    // 注意:默认是根据类型来存储组件对象,如果同类型有多个对象可以尝试使用 NAME 来存储组件对象
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router)([]{
        return oatpp::web::server::HttpRouter::createShared();
    }());

    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpConnectionHandler>, conn_handler)([]{
        OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
        return oatpp::web::server::HttpConnectionHandler::createShared(router);
    }());

    // oatpp::network::ServerConnectionProvider 是 ConnectionProvider 的父类
    // 此处也可以写父类类型
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::tcp::server::ConnectionProvider>, conn_provider)([]{
        auto address = oatpp::network::Address({"localhost", 8000, oatpp::network::Address::IP_4});
        return oatpp::network::tcp::server::ConnectionProvider::createShared(address);
    }());

    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::parser::json::mapping::ObjectMapper>, object_mapper)([] {
        return oatpp::parser::json::mapping::ObjectMapper::createShared();
    }());

};

#endif

2. OATPP_COMPONENT

OATPP_CREATE_COMPONENT 执行之后,会预先创建好需要的对象,并存储到容器中,OATPP_COMPONENT 的作用就是从容器中取出组件对象,但是需要注意的是,取对象时是根据类型来获取,多次获取拿到的对象是同一个。

#include "oatpp/network/Server.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "AppComponent.hpp"

// 必须定义开始
#include OATPP_CODEGEN_BEGIN(DTO)
// 该类定义序列化内容,必须继承 DTO 类
class MessageDTO : public oatpp::DTO {

    // 初始化
    DTO_INIT(MessageDTO, DTO);

    // 定义字段
    DTO_FIELD(Int32, status);
    DTO_FIELD(String, result);
    DTO_FIELD(String, info);

};
// 必须定义结束
#include OATPP_CODEGEN_END(DTO)


class Handler : public oatpp::web::server::HttpRequestHandler {
public:
    std::shared_ptr<OutgoingResponse> handle(const std::shared_ptr<IncomingRequest>& request) override {
        (void)request;

        // 构建 MessageDTO 对象
        auto message = MessageDTO::createShared();
        message->status = 200;
        message->info = "Hello DTO";
        message->result = "OK";

        // 构建 ObjectMapper 对象,该对象用于序列化 MessageDTO 对象
        OATPP_COMPONENT(std::shared_ptr<oatpp::parser::json::mapping::ObjectMapper>, object_mapper);
        return ResponseFactory::createResponse(Status::CODE_200, message, object_mapper);
    }
};

void run() {

    // 0. 在 run 函数内作用域范围内注册组件对象
    AppComponent components;

    // 1. 使用 OATPP_COMPONENT 获得 HttpRouter 组件对象
    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
    router->route("GET", "/hello", std::make_shared<Handler>());

    // 2. 使用 OATPP_COMPONENT 获得 HttpConnectionHandler 组件对象
    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpConnectionHandler>, conn_handler);

    // 3. 使用 OATPP_COMPONENT 获得 ConnectionProvider 组件对象
    OATPP_COMPONENT(std::shared_ptr<oatpp::network::tcp::server::ConnectionProvider>, conn_provider);

    // 4. 构建服务对象
    oatpp::network::Server server(conn_provider, conn_handler);

    // 5. 服务启动信息
    const void *host = conn_provider->getProperty("host").getData();
    const void *port = conn_provider->getProperty("port").getData();
    OATPP_LOGI("Oat++ Demo", "http://%s:%s/hello", host, port);

    server.run();
}

int main() {

    oatpp::base::Environment::init();
    run();
    oatpp::base::Environment::destroy();

    return 0;
}
未经允许不得转载:一亩三分地 » C++ Web Framework Oat++ Component
评论 (0)

4 + 9 =