前面的例子中,每一个请求的 URL 都对应了一个 HttpRequestHandler 类,并实现该类中 handle 函数,如下代码:
class Handler1 : public oatpp::web::server::HttpRequestHandler { public: std::shared_ptr<OutgoingResponse> handle(const std::shared_ptr<IncomingRequest>& request) override { (void)request; return ResponseFactory::createResponse(Status::CODE_200, "Hello Handler1"); } }; class Handler2 : public oatpp::web::server::HttpRequestHandler { public: std::shared_ptr<OutgoingResponse> handle(const std::shared_ptr<IncomingRequest>& request) override { (void)request; return ResponseFactory::createResponse(Status::CODE_200, "Hello Handler2"); } };
如果我们设计更多的 URL 就需要写更多的 HttpRequestHandler 类,比较麻烦。控制器(Cotroller)可以简化这部分代码。先增加一个 Controller.hpp 文件,代码如下:
#ifndef CONTROLLER_HPP #define CONTROLLER_HPP #include "oatpp/web/server/api/ApiController.hpp" #include "oatpp/core/macro/codegen.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp" // 1. 必须增加这一行代码 #include OATPP_CODEGEN_BEGIN(ApiController) class Controller : public oatpp::web::server::api::ApiController { public: Controller(const std::shared_ptr<ObjectMapper>& object_mapper) : oatpp::web::server::api::ApiController(object_mapper) {} public: // 注意: 定义多个处理函数时,第三个参数名字不能重复 ENDPOINT("GET", "/hello", root) { return ResponseFactory::createResponse(Status::CODE_200, "hello oat++"); } // 获得 PATH 参数 ENDPOINT("GET", "/path/{param}", get_path_param, PATH(String, param)) { String message = "hello " + param; return ResponseFactory::createResponse(Status::CODE_200, message); } // 获得 QUERY 参数 ENDPOINT("GET", "/query", get_query_param, QUERY(Int32, age), QUERY(String, name)) { // QUERY 第二个参数名对应 ? 后的请求参数名 String message = "name=" + name + ", age=" + std::to_string(age); return ResponseFactory::createResponse(Status::CODE_200, message); } // 获得 HEADER ENDPOINT("GET", "/header", get_header_param, HEADER(String, user_agent, "User-Agent")) { // QUERY 第二个参数名对应 ? 后的请求参数名 String message = user_agent; return ResponseFactory::createResponse(Status::CODE_200, message); } }; // 2. 必须增加这一行代码 #include OATPP_CODEGEN_END(ApiController) #endif
run 函数代码如下:
#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/parser/json/mapping/ObjectMapper.hpp" #include "Cotroller.hpp" void run() { // 1. 创建路由对象 auto router = oatpp::web::server::HttpRouter::createShared(); auto object_mapper = oatpp::parser::json::mapping::ObjectMapper::createShared(); // 构建控制器对象 auto controller = std::make_shared<Controller>(object_mapper); // 设置控制器到路由器 router->addController(controller); // 2. 连接处理对象 // 服务器接受得到连接之后,交给 HttpConnectionHandler 来处理连接 auto conn_handler = oatpp::web::server::HttpConnectionHandler::createShared(router); // 3. 套接字监听参数 auto address = oatpp::network::Address({"localhost", 8000, oatpp::network::Address::IP_4}); auto conn_provider = oatpp::network::tcp::server::ConnectionProvider::createShared(address); // 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("url1", "http://%s:%s/hello", host, port); OATPP_LOGI("url2", "http://%s:%s/path/abc", host, port); OATPP_LOGI("url3", "http://%s:%s/query?age=18&name=obama", host, port); OATPP_LOGI("url4", "http://%s:%s/header", host, port); // 6. 启动服务等待连接 server.run(); } int main() { oatpp::base::Environment::init(); run(); oatpp::base::Environment::destroy(); return 0; }
程序输出结果:
I |2023-02-11 00:31:47 1676046707449597| url1:http://localhost:8000/hello I |2023-02-11 00:31:47 1676046707449817| url2:http://localhost:8000/path/abc I |2023-02-11 00:31:47 1676046707449825| url3:http://localhost:8000/query?age=18&name=obama I |2023-02-11 00:31:47 1676046707449832| url4:http://localhost:8000/header