cppcms中的session

问题:

如果打开cppcms的reference文档,在吹泡泡cms::sessions namespace下存在如下几个类:

class   encryptor;  // 泛型session cookies 加密接口. 

class   encryptor_factory;  // 顾名思义,建立新加密器的接口

class   session_cookies; // 使用加密的或者签名的cookies的session_api实现。

class   session_dual; // session_api的客户端和服务器端存储实现

class   session_sid; // 用session_storage和唯一session id存储session数据的session_api实现。

  class  session_server_storage //是一个允许用户实现自定义session storage(如数据库)的抽象类。

class   session_storage_factory //建立session storage对象的工厂类。

 

但是session_cookies, session_dual, 和session_sid三个实现的接口类session_api却不在cppcms::sessions namespace下,另外,在cppcms::application调用的session()返回的session_interface类引用也同样不在namespace下。在service中定义的session_pool也不在此命名空间内。为什么呢?这几个类虽然都跟session有关系,互相之间又是如何关联的呢?

 

小结:

打开service.cpp浏览代码,先看构造函数service::service(int argc,char *argv[]) :

	impl_(new impl::service())
{
	impl_->args_.assign(argv,argv+argc);        //pimp idiom, args的类型vector<std::string>
	json::value val = load_settings(argc,argv); //读取并解析config.js中的json配置参数
	impl_->settings_.reset(new json::value()); //重置
	impl_->settings_->swap(val); //按照config.js的配置修改Impl的设定。
	setup(); //安装service.
}

 再看setup成员函数

 

void service::setup()
{
	impl_->cached_settings_.reset(new impl::cached_settings(settings()));
	impl::setup_logging(settings());
	impl_->id_=0;
	int reactor=reactor_type(settings().get("service.reactor","default"));
	impl_->io_service_.reset(new io::io_service(reactor));
	impl_->sig_.reset(new io::stream_socket(*impl_->io_service_));
	impl_->breaker_.reset(new io::stream_socket(*impl_->io_service_));

	int apps=settings().get("service.applications_pool_size",threads_no()*2);
	impl_->applications_pool_.reset(new cppcms::applications_pool(*this,apps));
	impl_->views_pool_.reset(new cppcms::views::manager(settings()));
	impl_->cache_pool_.reset(new cppcms::cache_pool(settings()));
	impl_->session_pool_.reset(new cppcms::session_pool(*this));
	if(settings().get("file_server.enable",false)) {
		applications_pool().mount(applications_factory<cppcms::impl::file_server>(),mount_point(""));
	}
}

 这个成员函数执行过程中,在倒数第二步重置了session_pool. 当扮演controller角色的application main函数调用app.run()函数后,cppcms后面又做了什么跟session相关的动作呢?我们且再看下run成员函数。

 

void service::run()
{
	run_prepare(); //->依次调用函数generator(), forwarder(), session_pool().init(), start_acceptor().

	impl::daemonizer godaemon(settings()); 
	
	if(prefork()) { // prefork() 用以设置系统signal及handler
		return;
	}

	thread_pool(); // make sure we start it 

	if(impl_->prefork_acceptor_.get())
		impl_->prefork_acceptor_->start();
	
	after_fork_exec();
	run_acceptor();
	setup_exit_handling();
	
	run_event_loop(); 
}

根据上述代码,我们再继续查看session_pool.cpp代码中的init成员函数

 

void session_pool::init()
{
	service &srv=*service_;
	if(backend_.get())
		return;

	std::string location=srv.settings().get("session.location","none");

	if((location == "client" || location=="both") && !encryptor_.get()) {
		... ...
	}
	if((location == "server" || location == "both") && !storage_.get()) {
		... ...
	}
	if(location == "server") {
		std::auto_ptr<session_api_factory> f(new sid_factory(this));
		backend(f);
	}
	else if(location == "client") {
		std::auto_ptr<session_api_factory> f(new cookies_factory(this));
		backend(f);
	}
	else if(location == "both") {
		unsigned limit=srv.s.ettings().get("session.client_size_limit",2048);
		std::auto_ptr<session_api_factory> f(new dual_factory(limit,this));
		backend(f);
	}
	else if(location == "none")
		;
	else 
		throw cppcms_error("Unknown location");

	service_->after_fork(boost::bind(&session_pool::after_fork,this));
}

不过上述代码比较冗长一些,但是还好,逻辑看起来还是比较清晰的。顺序上,大致是如下逻辑;

1. 判断是否已经有session了?如果有,返回。

2. 如果1.没有,则根据config.js中session section的配置,进行各种scenario的判断和处理;

I.    session存放在client端或者both(既存放在client端也存放在server端),同时没有配置encryptor

II.   session存放在server端或者both,但没有配置session storage

III.  session只存放在server端,那么通过sid_factory创建session_sid

        IV.  session只存放在client端,那么通过cookies_factory创建session_cookies

   V.    session存在在both端,那么通过dual_factory创建session_dual

        VI.   session的location如果是none, 啥也不做。

        VII.  其他情况,抛出unknown location异常。

针对scenario I, II, 还有进一步的处理,此处忽略。

从上述的各种scenario处理情况来看,逻辑上大致分三种情况,即

1. 如果存放在client端的话,必须对session存放的数据按照配置的加密算法进行加密。

2. 如果存在server端的话,server负责产生一个session id.

3. 如果存在both端的话,session_sid, session_cookies都需要被创建。

 

这样我们可以看出cppcms中有关session的一些端倪了。实际上,session_pool是cppcms框架中用来管理session的核心组件,session_pool中包含了三个auto_ptr,分别指向session_api_factory, encryptor_factory和session_storage_factory。session_api_factory用以创建实际操作session的类。根据不同的操作,cppcms中一共有三种session操作类,它们是session_cookies, session_sid, session_dual。session_storage_factory用以创建针对不同s媒介的storage,包含memory, cookie, database, network等。encryptor_factory主要创建加密器用以针对存储在客户端的session数据应该实施必要的加密措施。

 

那么上述的那三个session操作类,操作对象是什么呢?当然是session了!对,不过在cppcms里,session是被封装在session_interface中的。

 

之所以没有把session_api, session_interface, session_pool这三个类放在cppcms::sessions namespace下,个人认为可能是作者有意想把跟http session在框架中独立出来,放在了cppcms域中。而组成session_pool的核心组件类才被放入到cppcms::sessions域中。

你可能感兴趣的:(session)