天天看點

重拾cgi——頁面模闆

可能是因為公司裡寫代碼用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