可能是因为公司里写代码用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