使用 acl_cpp 的 HttpServlet 類及 google 的 ctemplate 庫編寫 WEB 應用

      文章《用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://weibo.com/zsxxsz

     原文地址

       下載: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服務器程序

      acl_cpp web 編程之文件上傳

      更多文章...

 

     模板引擎參考文章

     ctemplate 下載地址

     嘗試使用google-template模板引擎

     C++模板引擎Ctemplate的介紹

     基於C++的模板引擎

相關文章
相關標籤/搜索