`
tiny.strimp
  • 浏览: 29430 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Agile Web Development with Rails 3nd Edition学习笔记-把Sessions放进数据库

阅读更多
depot在线商店需要一个能保存用户选购的各种各样的商品的地方,而对于Web程序而言,每个页面和请求的生命周期都是瞬间了,彼此之间没有任何的状态记录。当用户在一个页面选择了一样商品,再去另一个页面选择另一样商品的时候,上一个页面的数据已经荡然无存了。就像狗熊掰苞米,掰一个放在胳肢窝下,再掰一个放在胳肢窝下,之前的那个就没有了。(哈哈!这个比喻也许不那么恰当。
那么,我们怎么保存用户选购的商品呢?答案是选用Session机制来保存类似的数据。一般来说,Session的数据可以使用一个文件保存在Server端,或是通过Cookies保存在浏览器端。如果把数据保存在Server端的文件中,对于只在一台Web服务器上部署depot的情况而言,这就足够了。但是如果用户很多,我们需要部署多台depot服务器时,就有问题了。由于负载均衡的关系,可能用户在第一个页面选购商品的时候,实际访问的是服务器A,而当用户进入另一个页面选购商品时,实际访问的服务器就变成B了。这样,之前保存在服务器A上的Session文件就无法访问了。
对于这个问题,其实个人认为有三个解决方案:
  1.把Session信息保存在浏览器端的cookies中;
  2.将Session信息保存在一个所有服务器都能访问的共享文件服务器上;
  3.将Session信息保存在depot的数据库中。
对于1方案,现在有很多浏览器的用户出于安全角度考虑,会将浏览器的Cookie功能关闭。这样我们就没办法使用Cookie来保存用户选择的商品,这也意味着我们的网站不能正常的工作了。虽然,这是Rails的默认设置......
对于2方案,这是我的一个想法,不知道是否能实现,这个可以当作一个问题点留待后面实验。
对于3方案,deopt的数据库是所有depot的Web服务器都要访问的地方,里面的数据对于所有depot的Web服务器都是共享的,一致的。所以保存在这里是最方便最理想的地方了。这一篇我们就来看看如何通过Rails做到这件事。
首先,我们需要在depot的数据库中创建一个用来保存Session信息的表。我们叫它sessions。我们仍然使用migration的方式创建它。
执行下面的命令来创建Migration使用的rb文件:
引用
rake db:sessions:create

然后执行下面的命令来提交给数据库:
引用
rake db:migrate

现在通过MySQL Administrator工具来查看我们的数据库,一个新的sessions的表已经创建好了。再通过Table Editor来查看这个表中的字段,我们可以看到有如下的字段被创建:
Column NameData TypeNOT NULLAUTO INCFlagsDefault ValueComments
idINTEGERtruetrueNULL
session_idVARCHAR(255)truefalseNULL
dataTEXTfalsefalseNULL
created_atDATETIMEfalsefalseNULL
updated_atDATETIMEfalsefalseNULL
truefalse

由于Rails的默认设置是使用Cookie来保存Session的信息,所以,我们现在要告诉Rails使用数据库来保存Session信息而不是Cookie。
在depot的工程下找到config/environment.rb文件,并在文件中找到如下内容的位置:
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rake db:sessions:create")
# config.action_controller.session_store = :active_record_store

我们看到这段内容的最后一行使用active_record_store保存Session的设置被注释掉了,那么我们现在就去掉前面的“#”来激活这个功能。修改后的内容如下:
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rake db:sessions:create")
config.action_controller.session_store = :active_record_store

接下来,有一个问题需要解决。一般来说,当Session的信息被保存在Cookie中时,使用服务器的主机名和Session名作为id来保存数据的。当一台Web服务器上运行着两个Web应用的时候,这样的信息保存在用户的浏览器端是没有问题的,因为用户的浏览器将这个数据送给了实际连接的应用。但是如果保存在服务器端共享的数据库中就无法分清是哪个应用的Session信息了。(书上是这样说的,但是没有明白的一点是:难道部署在同一台Web服务器上的两个应用会使用同一个数据库吗?)Rails为这个问题做了一些处理。当使用rails命令创建一个新的应用的时候,它会生成一个包含该应用名字的Cookie名来作为id保存Session的信息。这个名字就保存在刚才我们修改过的config/environment.rb文件中。打开这个文件,你可以看到类似如下内容的部分:
config.action_controller.session = {
  :session_key => '_depot_session',
  :secret      => '56118287c84e33312b78ab8c3f2e20865bf14d3077ba96f7f0292a13422dc2ef5d3a62c280ec097a105e67c6525a032ca6e0878e47bdecdb662f876dcea44f3d'
}

为了使用这一特性,我们需要对app/controllers/application.rb文件做一点小小的修改。打开该文件,找到如下代码行:
protect_from_forgery # :secret => 'a4209f7c6bd8ec935052abba28c86abc'

这里,我们要做的就是把中间那个注释用的“#”删除掉即可。修改后的代码如下:
protect_from_forgery :secret => 'a4209f7c6bd8ec935052abba28c86abc'

现在启动你的服务,你将会在你的数据库中看到Session数据被保存在了数据库中。当你用你的浏览器打开你的网站的页面时,会有一条新的Session记录被保存到了数据库中。
问题:
1.服务启动的时候保存进数据库的那条Session信息是什么?是哪个Session的?这时没有用户访问网站啊
2.尝试了一下,在用浏览器打开网页使得数据中产生了一条Session记录后,关闭浏览器,这条Session记录没有被清除掉。再关闭Web服务,所有的Session记录都没有被清除掉。那么,这些Session记录什么时候才会被清除掉?难道会永远保留在数据库中吗?多占地方啊!

好了,到现在为止,我们已经能把Session的数据保存在数据库中了。之后我们就可以考虑继续添加我们的购物管理功能了。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics