三、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; } |