可能是因為公司裡寫代碼用velocity習慣了,找了google的ctemplate來實作類似的功能。ctemplate相對velocity比較簡單,隻有變量替換,簡單的引用、循環。這裡有ctemplate的詳細文檔,相對來說,就是不能在模闆上有太多的邏輯。
首先,前一篇裡面貼了dispatcher,通過apache中設定環境變量,設定模闆跟路徑:
[cce lang=”cpp”]
ctemplate::template::settemplaterootdirectory(input.getenv(“template_path”));
[/cce]
然後,通過綁定的處理函數,調用真正的處理uri的函數後,将輸出的dictionary對象,和模闆合并:
std::string templatepath;
if(context.dict) //has dict
{
//get template
templatepath = context.dict->name() + ".tpl";
//expend
std::string out;
bool expandresult = ctemplate::expandtemplate(templatepath, ctemplate::strip_whitespace, context.dict.get(), &out);
if(expandresult) //good, we expend template success
context.ostream << cgicc::httphtmlheader();
context.ostream << out;
}
else //oops, we response 500
context.ostream << cgicc::httpstatusheader(500, "internal server error");
context.ostream << "fail to expand template: " << templatepath;
else
//如果沒有字典,由對應的函數自己輸出
這裡是有字典輸出的邏輯。擷取根字典的名字,加上字尾,在根路徑中查找對應的模闆。然後調用ctemplate的函數,将模闆展開。最後,将展開後的内容,通過流輸出。
如果沒有字典輸出,預設當成處理函數中已經自己進行了輸出(這裡主要是為了讓處理函數自己輸出json内容)
另外一個分支,如果沒有綁定,那麼直接輸出模闆内容:
// find if there is a template
std::string templatepath = path.substr(1) + ".tpl";
if(ctemplate::mutable_default_template_cache()->loadtemplate(templatepath, ctemplate::strip_whitespace))
bool expandresult = ctemplate::expandtemplate(templatepath, ctemplate::strip_whitespace,
_emptydict.get(), &out);
else //not bind and not find a template file
context.ostream << cgicc::httpstatusheader(404, "not find");
context.ostream << "not find";
如果沒有綁定,用一個空的字典,展開模闆,也就是直接輸出模闆。如果這都沒有找到,那麼就傳回404。
一個綁定函數的例子:
void handle(context &context)
std::vector<volume> volumes;
//fixme: mock資料
volume v1 ("1", "a", "cover_1.png", 5);
volume v2 ("2", "b", "cover_2.png", 1);
volumes.push_back(v1);
volumes.push_back(v2);
boost::shared_ptr<ctemplate::templatedictionary> listpagedict(new ctemplate::templatedictionary("list"));
for(int i = 0; i < volumes.size(); ++i)
ctemplate::templatedictionary *listsection = listpagedict->addsectiondictionary("list_sections");
listsection->setintvalue("id", volumes[i].id());
listsection->setvalue("name", volumes[i].name());
listsection->setvalue("cover_img_path", volumes[i].cover_path());
context.dict = listpagedict;
對應的模闆檔案:
[cce]
< !doctype html>
< html>
<head>
<meta charset="utf-8" />
<title>title</title>
</head>
<body>
<ol>
{{#list_sections}}
<li>name: {{name}}</li>
{{/list_sections}}
</ol>
</body>
< /html>
最後輸出就是剛在volume對象的name字段。
轉載自:https://coolex.info/blog/341.html