前面的例子中,每一个请求的 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