文档章节

使用 acl_cpp 的 HttpServlet 类及 google 的 ctemplate 库编写 WEB 应用

郑树新
 郑树新
发布于 2014/09/03 12:10
字数 1199
阅读 16
收藏 0

      文章《用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 模板:test.htm

 

<!--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.htm

 

<!--include.htm-->
<div>
{{INCLUDE_VAR}}
</div>

 

      ctemplate 模板说明(摘自 marising 的《C++模板引擎Ctemplate的介绍》,该文中还有关于 ctemplate 更为高级的说明):

 

      ctemplate大体上分为两个部分,一部分是模板,另一部分是数据字典。模板定义了界面展现的形式(V),数据字典就是填充模板的数据(M),你自己写业务逻辑去控制界面展现(C),典型的MVC模型。

      ctemplate模板中有四中标记,对应的数据字典也有不同的处理方式:

      1)变量,{{变量名}},用两个大括号包含的就是变量名,在c++代码中,可以对变量赋值,任何类型的值都可以(如字符,整数,日期等)。

      2)片断,{{#片断名}},片断在数据字典中表现为一个子字典,字典是可以分级的,根字典下面有多级子字典。片断可以处理条件判断和循环。

      3)包含,{{>模板名}}包含指的是一个模板可以包含其他模板,对应的也是一个字字典。

      4)注释,{{!注释名}},包含注释。

 

 

       二、使用 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);
}

 

       三、使用 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++的模板引擎

© 著作权归作者所有

郑树新

郑树新

粉丝 104
博文 87
码字总数 161171
作品 2
昌平
程序员
私信 提问
用C++实现类似于JAVA HttpServlet 的编程接口

互联网刚兴起时,很多项目都是用 C /Perl 语言写的一大堆 CGI,一些老程序员可谓是偿尽了编程的苦,因为那时国内的技术水平普遍比较低,如果你会 CGI 编程,就已经算是行业中人了,如果你对 ...

郑树新
2014/08/23
0
0
acl 网络通信服务器框架 3.1.0 版本发布

acl 3.1.0 版本发布了,acl 是 one advanced C/C++ library 的简称,主要包括网络通信库以及服务器框架库等功能,支持 Linux/Windows/Solaris/FreeBsd/MacOS 平台;整个 acl 项目主要包含三个...

郑树新
2015/02/08
2.9K
2
acl redis C++ 库被 redis 官方收录

acl 库中的新增模块 redis C++ 客户端库被 redis 官方正式收录,参见 http://redis.io/clients 中的 C++ 部分,其中 “redis-client for C++” 库即为 acl redis C++ 客户端库。acl 中的 re...

郑树新
2015/03/09
7.2K
10
acl.3.2.2 发布, 跨平台网络通信与服务器框架

acl 3.2.2 版本发布了,acl 是 one advanced C/C++ library 的简称,主要包括网络通信库以及服务器框架库等功能,支持 Linux/Windows/Solaris/FreeBsd/MacOS 平台;整个 acl 项目主要包含四个...

郑树新
2016/11/01
1K
2
使用 acl 库编写多线程应用程序

在 《利用ACL库开发高并发半驻留式线程池程序》 中介绍了如何使用 C 版本的 acl 线程库编写多线程程序,本文将会介绍如何使用 C++ 版本的 acl 线程库编写多线程程序,虽然 C++ 版 acl 线程库...

郑树新
2014/08/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Jenkins系列_插件安装及报错处理

进入Jenkins之后我们可以进行插件的安装,插件管理位于以下模块: 发现上面报了一堆错误,是因为插件的依赖没有安装好,那么这一节,就先把这些错误解决掉吧。解决完成后,也就基本会使用插件...

shzwork
今天
2
0
mysql mysql的所有查询语句和聚合函数(整理一下,忘记了可以随时看看)

查询所有字段 select * from 表名; 查询自定字段 select 字段名 from 表名; 查询指定数据 select * from 表名 where 条件; 带关键字IN的查询 select * from 表名 where 条件 [not] in(元素...

edison_kwok
昨天
9
0
解决多线程并行加载缓存问题(利用guava实现)

依赖 com.google.guava:guava:20.0 import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import j......

暗中观察
昨天
3
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
昨天
2
0
组装一台工作游戏两用机

一、配置清单如下: 分类 项目 价格(元) 主板 华硕(ASUS)TUF Z370-PLUS GAMING II 电竞特工 Z370二代 支持9代CPU 1049 CPU 英特尔(Intel) i7 8700K 酷睿六核 盒装CPU处理器 2640 风扇 九...

mbzhong
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部