C++高性能服务器框架----Servlet模块

发布时间:2026/5/15 15:14:35

C++高性能服务器框架----Servlet模块 Servlet模块HTTP Servlet包括两部分第一部分是Servlet对象每个Servlet对象表示一种处理HTTP消息的方法第二部分是ServletDispatch它包含一个请求路径到Servlet对象的映射用于指定一个请求路径该用哪个Servlet来处理。1. 主要功能提供HTTP请求路径到处理类的映射用于规范化的HTTP消息处理流程。2. 功能演示一个简单的服务器由ServletDispatch完成uri对应的逻辑处理代码语言javascriptAI代码解释johnsonli::http::HttpServer::ptr server(new johnsonli::http::HttpServer(true)); johnsonli::Address::ptr addr johnsonli::Address::LookupAnyIPAddress(0.0.0.0:8020); while(!server-bind(addr)) { sleep(2); } // /sylar/xx映射 auto dsp server-getServletDispatch(); dsp-addServlet(/sylar/xx, [](johnsonli::http::HttpRequest::ptr req , johnsonli::http::HttpResponse::ptr rsp , johnsonli::http::HttpSession::ptr session){ rsp-setBody(req-toString()); return 0; }); // /sylar/*映射 dsp-addGlobServlet(/sylar/*, [](johnsonli::http::HttpRequest::ptr req , johnsonli::http::HttpResponse::ptr rsp , johnsonli::http::HttpSession::ptr session){ rsp-setBody(Glob:\r\n req-toString()); return 0; }); server-start();3. 模块介绍3.1 Servlet基类用于封装处理请求的方法代码语言javascriptAI代码解释class Servlet { public: typedef std::shared_ptrServlet ptr; Servlet(const std::string name) :m_name(name) {} virtual ~Servlet() {} /** * brief 处理请求 * param[in] request HTTP请求 * param[in] response HTTP响应 * param[in] session HTTP连接 * return 是否处理成功 */ virtual int32_t handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) 0; const std::string getName() const { return m_name;} protected: std::string m_name; // servlet名称 };3.2 FunctionServlet继承Servlet封装了一个回调函数m_cb用于具体的逻辑处理代码语言javascriptAI代码解释class FunctionServlet : public Servlet { public: /// 智能指针类型定义 typedef std::shared_ptrFunctionServlet ptr; /// 函数回调类型定义 typedef std::functionint32_t (johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) callback; /** * brief 构造函数 * param[in] cb 回调函数 */ FunctionServlet(callback cb); virtual int32_t handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) override; private: /// 回调函数 callback m_cb; };handle方法处理逻辑实际上是调用的m_cb回调函数代码语言javascriptAI代码解释int32_t FunctionServlet::handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) { //调用回调 return m_cb(request, response, session); }3.3 NotFoundServlet对于没有uri映射的Servlet统一使用这个进行默认处理返回一个404页面代码语言javascriptAI代码解释/** * brief NotFoundServlet(默认返回404) */ class NotFoundServlet : public Servlet { public: typedef std::shared_ptrNotFoundServlet ptr; NotFoundServlet(const std::string name); virtual int32_t handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) override; private: std::string m_name; std::string m_content; }; int32_t NotFoundServlet::handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) { response-setStatus(johnsonli::http::HttpStatus::NOT_FOUND); response-setHeader(Server, sylar/1.0.0); response-setHeader(Content-Type, text/html); response-setBody(m_content); return 0; }3.4 ServletDispatch继承Servlet用于管理所有uri到Servle的映射unordered_mapstd::string, Servlet::ptr代码语言javascriptAI代码解释class ServletDispatch : public Servlet { public: typedef std::shared_ptrServletDispatch ptr; typedef RWMutex RWMutexType; ServletDispatch(); virtual int32_t handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) override; // addServlet, delServlet, addGlobServlet, delGlobServlet, ... private: /// 读写互斥量 RWMutexType m_mutex; /// 精准匹配servlet MAP /// uri(/sylar/xxx) - servlet std::unordered_mapstd::string, Servlet::ptr m_datas; /// 模糊匹配servlet 数组 /// uri(/sylar/*) - servlet std::vectorstd::pairstd::string, Servlet::ptr m_globs; /// 默认servlet所有路径都没匹配到时使用 Servlet::ptr m_default; };handle方法通过request的uri找到对应的Servlet然后执行其对应的业务逻辑处理方法handle代码语言javascriptAI代码解释int32_t ServletDispatch::handle(johnsonli::http::HttpRequest::ptr request , johnsonli::http::HttpResponse::ptr response , johnsonli::http::HttpSession::ptr session) { auto slt getMatchedServlet(request-getPath()); if(slt) { slt-handle(request, response, session); } return 0; }如何完成映射这里有三种映射的方式一个是精确匹配一个是模糊匹配如果都没有匹配到还有一个默认的servlet处理NotFoundServlet。代码语言javascriptAI代码解释/// 精准匹配servlet MAP /// uri(/sylar/xxx) - servlet std::unordered_mapstd::string, Servlet::ptr m_datas; /// 模糊匹配servlet 数组 /// uri(/sylar/*) - servlet std::vectorstd::pairstd::string, Servlet::ptr m_globs; /// 默认servlet所有路径都没匹配到时使用 Servlet::ptr m_default;精确匹配优先级大于模糊匹配代码语言javascriptAI代码解释Servlet::ptr ServletDispatch::getMatchedServlet(const std::string uri) { RWMutexType::ReadLock lock(m_mutex); //先找m_datas优先级更高 auto mit m_datas.find(uri); if(mit ! m_datas.end()) { return mit-second; } //再找m_globs for(auto it m_globs.begin(); it ! m_globs.end(); it) { if(!fnmatch(it-first.c_str(), uri.c_str(), 0)) { return it-second; } } return m_default; }3.5 HttpServer中使用Servlet当服务器收到一个请求时将请求给ServletDispatch由ServletDispatch负责uri的不同处理。代码语言javascriptAI代码解释class HttpServer : public TcpServer { public: // ... ServletDispatch::ptr getServletDispatch() const { return m_dispatch;} void setServletDispatch(ServletDispatch::ptr v) { m_dispatch v;} private: // ... ServletDispatch::ptr m_dispatch; // Servlet分发器 };handleClient中的一些改变由ServletDispatch负责uri对应的业务逻辑处理代码语言javascriptAI代码解释void HttpServer::handleClient(Socket::ptr client) { HttpSession::ptr session(new HttpSession(client)); do{ auto req session-recvRequest(); if(!req) { LOG_DEBUG(g_logger) recv http request fail, errno errno errstr strerror(errno) cliet: *client keep_alive m_isKeepalive; break; } HttpResponse::ptr rsp(new HttpResponse(req-getVersion() ,req-isClose() || !m_isKeepalive)); //servlet dispatch负责处理对应的请求 m_dispatch-handle(req, rsp, session); session-sendResponse(rsp); }while(m_isKeepalive); }

相关新闻