文章《用C++實現相似於JAVA HttpServlet 的編程接口》中講述瞭如何使用 acl_cpp 庫之 HTTP 模塊編寫象 Java Servlet 同樣的 WEB 應用。其中也講到了 acl_cpp HTTP 模塊中有關 Http Session、Cookie 的使用方法。而做爲 WEB 編程中很是重要的網頁模板引擎在 acl_cpp 並未實現。本文將結合谷歌的 ctemplate 庫,講解如何使用 acl_cpp 的 WEB 類庫和谷歌的 ctemplate 模板引擎庫來實現相似於 Java Servet + Velocity 的 WEB 應用。固然,用戶也能夠根據須要使用其它的模板引擎,如:CTPP(俄羅斯人寫的)、Teng。關於 C++ 的模板引擎能夠參考 《基於C++的模板引擎》。html
1、HTML 模板:test.htmc++
<!--test.htm--> <html> <head> <title> {{NAME}} </title> </head> {{!This is a example of template.}} <body> SID: {{SID}} <br> COOKIE: {{COOKIE}} <br> PARAM: {{PARAM}} <br> <br> Hello {{NAME}}, You have just won ${{VALUE}}! <table border=1> {{#IN_TABLE}} <tr> <td> {{ITEM}} </td> <td> {{TAXED_VALUE}} </td> </tr> {{/IN_TABLE}} </table> <br> {{!Include child template.}} {{>INCLUDED_TEMPLATE}} </body> </html>
下面是內嵌在 test.htm 中的子模板:include.htmgit
<!--include.htm--> <div> {{INCLUDE_VAR}} </div>
ctemplate 模板說明(摘自 marising 的《C++模板引擎Ctemplate的介紹》,該文中還有關於 ctemplate 更爲高級的說明):github
ctemplate大致上分爲兩個部分,一部分是模板,另外一部分是數據字典。模板定義了界面展示的形式(V),數據字典就是填充模板的數據(M),你本身寫業務邏輯去控制界面展示(C),典型的MVC模型。web
ctemplate模板中有四中標記,對應的數據字典也有不一樣的處理方式:編程
1)變量,{{變量名}},用兩個大括號包含的就是變量名,在c++代碼中,能夠對變量賦值,任何類型的值均可以(如字符,整數,日期等)。瀏覽器
2)片段,{{#片段名}},片段在數據字典中表現爲一個子字典,字典是能夠分級的,根字典下面有多級子字典。片段能夠處理條件判斷和循環。服務器
3)包含,{{>模板名}}包含指的是一個模板能夠包含其餘模板,對應的也是一個字字典。cookie
4)註釋,{{!註釋名}},包含註釋。session
2、使用 ctemplate 庫來替換 test.htm 模板中的參數,同時將子模板 include.htm 包含進 test.htm 中,功能實現以下:
#include <string> #include "ctemplate/template.h" using namespace ctemplate; // 打開模板文件將其中的標記進行替換,而後生成 HTML 頁面 bool create_html(std::string* out, const char* sid, const char* cookie, const char* param) { // 調用 google ctemplate 模板引擎生成頁面 // 建立父模板 TemplateDictionary dict("example"); // 設置模板中的參數值 dict.SetValue("SID", sid ? sid : "null"); dict.SetValue("COOKIE", cookie ? cookie : "null"); dict.SetValue("PARAM", param ? param : "null"); dict.SetValue("NAME", "John Smith"); int winnings = rand() % 100000; dict.SetIntValue("VALUE" , winnings); // 設置模板中的片段 // 建立表格:10 行 for (int i = 0; i < 10; i++) { TemplateDictionary *dict1 = dict.AddSectionDictionary("IN_TABLE"); dict1->SetValue("ITEM", "Lihaibo"); dict1->SetFormattedValue("TAXED_VALUE", "%.2f", winnings * 0.83); } // 容許顯示錶格內容 dict.ShowSection( "IN_TABLE" ); // 建立 dict 模板的子模板 TemplateDictionary *dict3 = dict.AddIncludeDictionary("INCLUDED_TEMPLATE"); // 設置子模板文件名 dict3->SetFilename("include.htm" ); // 替換子模板中的標記 dict3->SetValue("INCLUDE_VAR", "This is a include template."); // 根據 test.htm 頁面模板建立 HTML 頁面,並返回 return ExpandTemplate("test.htm", DO_NOT_STRIP, &dict, out); }
3、使用 acl::HttpServlet 類編寫 HTTP 處理過程
#include "lib_acl.hpp" #include <string> class http_servlet : public acl::HttpServlet { public: http_servlet(void) { } ~http_servlet(void) { } // HTTP GET 請求過程 virtual bool doGet(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { return doPost(req, res); } // HTTP POST 請求過程 virtual bool doPost(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { // 得到 session const char* sid = req.getSession().getAttribute("sid"); if (sid == NULL || *sid == 0) req.getSession().setAttribute("sid", "xxxxxx"); sid = req.getSession().getAttribute("sid"); // 取得瀏覽器 cookie const char* cookie = req.getCookieValue("name"); // 取得請求參數 const char* param = req.getParameter("name"); // 建立 HTTP 響應頭過程 // 添加 cookie res.addCookie("name", "value"); // 以 acl_master 框架控制方式或單獨服務運行時必須設置狀態位 res.setStatus(200); // 設置 Content-Type 字段 res.setContentType("text/html"); // 設置字符集 res.setCharacterEncoding("gb2312"); std::string buf; create_html(&buf, sid, cookie, param); // 生成 HTML 頁面 // 發送 http 響應頭 if (res.sendHeader() == false) return false; // 發送 http 響應體 if (res.getOutputStream().write(buf.c_str(), buf.length()) == -1) return false; return true; } };
int main(void) { http_servlet servlet; servlet.doRun("127.0.0.1:11211"); // 開始運行,並假設 memcached 監聽於 127.0.0.1:11211 return 0; }
由上面的例子能夠看出,使用 acl::HttpServlet 類庫及 ctemplate 模板庫編寫 WEB 應用仍是比較簡單的,這是一種典型的 MVC 的設計示例,要比傳統的 CGI 編程簡易很多並且功能更爲強大。
下載:http://sourceforge.net/projects/acl/
svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code
github:https://github.com/zhengshuxin/acl
QQ 羣:242722074
bbs:http://www.aclfans.com
用C++實現相似於JAVA HttpServlet 的編程接口
使用 acl_cpp 的 HttpServlet 類及服務器框架編寫WEB服務器程序
更多文章...
模板引擎參考文章: