三、HttpServletResponse 类
  该类主要与将您写的程序将处理数据结果返回给浏览器的过程相关,下面也仅介绍该类的一些常用的函数,如果您需要更多的功能,请参数 HttpServletResponse.hpp 头文件。
/**
* 设置 HTTP 响应数据体的 Content-Type 字段值,可字段值可以为:
* text/html 或 text/html; charset=utf8 格式
* @param value {const char*} 字段值
*/
void setContentType(const char* value);
/**
* 设置 HTTP 响应数据体中字符集,当已经在 setContentType 设置
* 了字符集,则不必再调用本函数设置字符集
* @param charset {const char*} 响应体数据的字符集
*/
void setCharacterEncoding(const char* charset);
/**
* 设置 HTTP 响应头中的状态码:1xx, 2xx, 3xx, 4xx, 5xx
* @param status {int} HTTP 响应状态码, 如:200
*/
void setStatus(int status);
/**
* 添加 cookie
* @param name {const char*} cookie 名
* @param value {const char*} cookie 值
* @param domain {const char*} cookie 存储域
* @param path {const char*} cookie 存储路径
* @param expires {time_t} cookie 过期时间间隔,当当前时间加
*  该值为 cookie 的过期时间截(秒)
*/
void addCookie(const char* name, const char* value,
const char* domain = NULL, const char* path = NULL,
time_t expires = 0);
/**
* 发送 HTTP 响应头,用户应该发送数据体前调用此函数将 HTTP
* 响应头发送给客户端
*/
bool sendHeader(void);
/**
* 获得 HTTP 响应对象的输出流对象,用户在调用 sendHeader 发送
* 完 HTTP 响应头后,通过该输出流来发送 HTTP 数据体
* @return {ostream&}
*/
ostream& getOutputStream(void) const;
  setCharacterEncoding:该方法设置 HTTP 响应头的 HTTP 数据体的字符集,如果通过该函数设置了字符集,即使您在返回的 html 数据中重新设置了其它的字符集,浏览器也会优先使用 HTTP 响应头中设置的字符集,所以用户一定得注意这点;
  setContentType:该方法用来设置 HTTP 响应头中的 Content-Type 字段,对于 xml 数据则设置 text/xml,对 html 数据则设置 text/html,当然您也可以设置 image/jpeg 等数据类型;当然,您也可以直接通过该方法在设置数据类型的同时指定数据的字符集,如可以直接写:setContentType(“text/html; charset=utf8”),这个用法等同于:setContentType(“text/html”); setCharacterEncoding(“utf8”)
  setStatus:设置 HTTP 响应头的状态码(一般不用设置状态码,除非是您确实需要单独设置);
  addCookie:在 HTTP 响应头中添加 cookie 内容;
  sendHeader:发送 HTTP 响应头;
  getOutputStream:该函数返回输出流对象,您可以向输出流中直接写 HTTP 响应的数据体(关于 ostream 类的使用请参数头文件:include/ostream.hpp)。
  除了以上三个类外,还有一个类比较重要:HttpSession 类,该类主要实现与 session 会话相关的功能:
  四、HttpSession 类
  该类对象实例用户也不必创建与释放,在 HttpServet 类对象内容自动管理该类对象实例。主要用的方法有:
  /**
  * 获得客户端在服务端存储的对应 session 变量名,子类可以重载该方法
  * @param name {const char*} session 名,非空
  * @return {const char*} session 值,为空说明不存在或内部
  *  查询失败
  */
  virtual const char* getAttribute(const char* name) const;
  /**
  * 设置服务端对应 session 名的 session 值,子类可以重载该方法
  * @param name {const char*} session 名,非空
  * @param name {const char*} session 值,非空
  * @return {bool} 返回 false 说明设置失败
  */
  virtual bool setAttribute(const char* name, const char* value);
  只所以将这两个方法声明为虚方法,是因为 HttpSession 的 session 数据存储目前仅支持 memcached,您如果有精力的话可以实现一个子类用来支持其它的数据存储方式。当然您也可以在您实现的子类中实现自己的产生 session id 的方法,即实现如下虚方法:
  protected:
  /**
  * 创建某个 session 会话的 ID 号,子类可以重载该方法
  * @param buf {char*} 存储结果缓冲区
  * @param len {size_t} buf 缓冲区大小,buf 缓冲区大小建议
  *  64 字节左右
  */
  virtual void createSid(char* buf, size_t len);
  好了,上面说了一大堆类及类函数,下面还是以一个具体的示例来说明这些类的用法:
  五、示例
  下面的例子是一个 CGI 例子,编译后可执行程序可以直接放在 apache 的 cgi-bin/ 目录,用户可以用浏览器访问。
// http_servlet.cpp : 定义控制台应用程序的入口点。
//
#include "lib_acl.hpp"
using namespace acl;
//////////////////////////////////////////////////////////////////////////
class http_servlet : public HttpServlet
{
public:
http_servlet(void)
{
}
~http_servlet(void)
{
}
// 实现处理 HTTP GET 请求的功能函数
virtual bool doGet(HttpServletRequest& req, HttpServletResponse& res)
{
return doPost(req, res);
}
// 实现处理 HTTP POST 请求的功能函数
virtual bool doPost(HttpServletRequest& req, HttpServletResponse& res)
{
// 获得某浏览器用户的 session 的某个变量值,如果不存在则设置一个
const char* sid = req.getSession().getAttribute("sid");
if (sid == NULL || *sid == 0)
req.getSession().setAttribute("sid", "xxxxxx");
// 再取一次该浏览器用户的 session 的某个属性值
sid = req.getSession().getAttribute("sid");
// 取得浏览器发来的两个 cookie 值
const char* cookie1 = req.getCookieValue("name1");
const char* cookie2 = req.getCookieValue("name2");
// 开始创建 HTTP 响应头
// 设置 cookie
res.addCookie("name1", "value1");
// 设置具有作用域和过期时间的 cookie
res.addCookie("name2", "value2", ".test.com", "/", 3600 * 24);
//      res.setStatus(400);  // 可以设置返回的状态码
// 两种方式都可以设置字符集
if (0)
res.setContentType("text/xml; charset=gb2312");
else
{
// 先设置数据类型
res.setContentType("text/xml");
// 再设置数据字符集
res.setCharacterEncoding("gb2312");
}
// 获得浏览器请求的两个参数值
const char* param1 = req.getParameter("name1");
const char* param2 = req.getParameter("name2");
// 创建 xml 格式的数据体
xml body;
body.get_root().add_child("root", true)
.add_child("sessions", true)
.add_child("session", true)
.add_attr("sid", sid ? sid : "null")
.get_parent()
.get_parent()
.add_child("cookies", true)
.add_child("cookie", true)
.add_attr("name1", cookie1 ? cookie1 : "null")
.get_parent()
.add_child("cookie", true)
.add_attr("name2", cookie2 ? cookie2 : "null")
.get_parent()
.get_parent()
.add_child("params", true)
.add_child("param", true)
.add_attr("name1", param1 ? param1 : "null")
.get_parent()
.add_child("param", true)
.add_attr("name2", param2 ? param2 : "null");
string buf;
body.build_xml(buf);
// 在http 响应头中设置数据体长度
res.setContentLength(buf.length());
// 发送 http 响应头
if (res.sendHeader() == false)
return false;
// 发送 http 响应体
if (res.write(buf) == false)
return false;
return true;
}
protected:
private:
};
//////////////////////////////////////////////////////////////////////////
int main(void)
{
#ifdef WIN32
acl::acl_cpp_init();  // win32 环境下需要初始化库
#endif
http_servlet servle;
// cgi 开始运行
servlet.doRun("127.0.0.1:11211");  // 开始运行,并设定 memcached 的服务地址为:127.0.0.1:11211
// 运行完毕,程序退出
return 0;
}