我之前写的session一般保存在服务器的内存里,那可以保存在缓存,或是数据库,那问题来了,不同地方,保存方式是不同的,所以需要定义不同的类,cache/redis/memcached类

session.py

  1. import config
  2. from hashlib import sha1
  3. import os
  4. import time
  5.  
  6. create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
  7.  
  8. class CacheSession:
  9. session_container = {}
  10. session_id = "__sessionId__"
  11.  
  12. def __init__(self, handler):
  13. self.handler = handler
  14. client_random_str = handler.get_cookie(CacheSession.session_id, None)
  15. if client_random_str and client_random_str in CacheSession.session_container:
  16. self.random_str = client_random_str
  17. else:
  18. self.random_str = create_session_id()
  19. CacheSession.session_container[self.random_str] = {}
  20.  
  21. expires_time = time.time() + config.SESSION_EXPIRES
  22. handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
  23.  
  24. def __getitem__(self, key):
  25. ret = CacheSession.session_container[self.random_str].get(key, None)
  26. return ret
  27.  
  28. def __setitem__(self, key, value):
  29. CacheSession.session_container[self.random_str][key] = value
  30.  
  31. def __delitem__(self, key):
  32. if key in CacheSession.session_container[self.random_str]:
  33. del CacheSession.session_container[self.random_str][key]
  34.  
  35. class RedisSession:
  36. def __init__(self, handler):
  37. pass
  38.  
  39. class MemcachedSession:
  40. def __init__(self, handler):
  41. pass

把session写死,如果更换session类型,就需要花大量的精力去修改,所以引出今天要说工厂方法模式,在session文件里再定义一个SessionFactory类

  1. class SessionFactory:
  2.  
  3. @staticmethod
  4. def get_session_obj(handler):
  5. obj = None
  6.  
  7. if config.SESSION_TYPE == "cache":
  8. obj = CacheSession(handler)
  9. elif config.SESSION_TYPE == "memcached":
  10. obj = MemcachedSession(handler)
  11. elif config.SESSION_TYPE == "redis":
  12. obj = RedisSession(handler)
  13. return obj

并在配置文件里写入你要使用的session类型,每次修改时只需修改配置文件

settings.py

  1. # Session类型:cache/redis/memcached
  2. SESSION_TYPE = "cache"
  3. # Session超时时间(秒)
  4. SESSION_EXPIRES = 60 * 20

在Tornado里,RequestHandler类提供一个initialize方法,用于在实例handler对象之前执行的,我们在这个方法里创建session对象,并赋给handler对象self.session这普通字段

request_handler.py

  1. import tornado.web
  2. from backend.session.session import SessionFactory
  3.  
  4. class BaseRequestHandler(tornado.web.RequestHandler):
  5.  
  6. def initialize(self):
  7.  
  8. self.session = SessionFactory.get_session_obj(self)

执行流程:

  前端访问url-->路由系统对应handler类-->执行initialize方法(创建self.session普通字段)-->执行session.py下SessionFactory的静态方法get_session_obj-->根据配置文件给定值,实例化session对象,并return

代码详解  

  1. from hashlib import sha1
  2. import os
  3. import time
  4. import config
  5.  
  6. #构造生成session随机字段串的函数
  7. create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
  8.  
  9. class SessionFactory:
  10. #静态方法直接由类调用
  11. @staticmethod
  12. def get_session_obj(handler):
  13. obj = None
  14.  
  15. if config.SESSION_TYPE == "cache":
  16. obj = CacheSession(handler)
  17. elif config.SESSION_TYPE == "memcached":
  18. obj = MemcachedSession(handler)
  19. elif config.SESSION_TYPE == "redis":
  20. obj = RedisSession(handler)
  21. return obj
  22.  
  23. class CacheSession:
  24. #用于存储session键值对的字典
  25. session_container = {}
  26. #指定前端存储cookie时key
  27. session_id = "__sessionId__"
  28.  
  29. def __init__(self, handler):
  30. self.handler = handler
  31. #前端cookie {"__sessionId__":"session随机字符串"}
  32. client_random_str = handler.get_cookie(CacheSession.session_id, None)
  33. #如果能获取到session随机字符串而且也在服务器内存里
  34. if client_random_str and client_random_str in CacheSession.session_container:
  35. #把获取的随机串赋给self.random_str
  36. self.random_str = client_random_str
  37. else:
  38. #没有就生成一个随机串
  39. self.random_str = create_session_id()
  40. #后台服务器{"session随机串":{...}}
  41. CacheSession.session_container[self.random_str] = {}
  42.  
  43. #设置过期时间
  44. expires_time = time.time() + config.SESSION_EXPIRES
  45. #并写入到cookie
  46. handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
  47.  
  48. def __getitem__(self, key):
  49. #self.session[key]
  50. ret = CacheSession.session_container[self.random_str].get(key, None)
  51. return ret
  52.  
  53. def __setitem__(self, key, value):
  54. #self.session[key] = value
  55. CacheSession.session_container[self.random_str][key] = value
  56.  
  57. def __delitem__(self, key):
  58. #del self.session[key]
  59. if key in CacheSession.session_container[self.random_str]:
  60. del CacheSession.session_container[self.random_str][key]
  61.  
  62. class RedisSession:
  63. def __init__(self, handler):
  64. pass
  65.  
  66. class MemcachedSession:
  67. def __init__(self, handler):
  68. pass

抽屉之Tornado实战(6)--session工厂(工厂方法模式)的更多相关文章

  1. 抽屉之Tornado实战(1)--分析与架构

    抽屉之Tornado实战(1)--分析与架构   项目模拟地址:http://dig.chouti.com/ 知识点应用: AJAX  用于偷偷发请求 原生ajax jQuery  ajax($.aj ...

  2. 抽屉之Tornado实战(9)--装饰器实现用户登录状态验证

    当然今天讲的验证,不只Tornado会用,以后用到web框架都会用到,最常见的场景就是只有用户登陆了才能执行某些操作,所以在执行这些操作前要先做登陆状态的验证. 比如:点赞,发布,评论等需要验证,都需 ...

  3. 抽屉之Tornado实战(5)--点赞与评论树

    点赞 点赞的过程:数字增加,并在后台点赞表记录数据 需要发过去的数据:用户id,新闻id 用户id从session里获得,那新闻id怎么获取呢?这想到分页是循环新闻列表来展示内容,循环的新闻id可以做 ...

  4. 抽屉之Tornado实战(7)--form表单验证

    在这里,我们把form表单验证的代码进行工具化了,以后稍微修改一下参数就可以拿来用了 先贴上代码 forms.py from backend.form import fields class Base ...

  5. 抽屉之Tornado实战(4)--发帖及上传图片

    对于链接,点击获取标题时,本质发送ajax请求,然后去链接抓取信息,发布又是发送ajax请求 发布信息,还要有发布者的信息,并在信息表需要记录发布者的用户名,发布者的头像,发布者的id,而这些信息可以 ...

  6. 抽屉之Tornado实战(3)--注册

    知识点应用:标签绑定事件,jQuery获取用户值-->AJAX发送数据-->后台路由系统-->业务逻辑处理-->ORM数据操作-->write返回-->AJAX回调 ...

  7. 抽屉之Tornado实战(2)--数据库表设计

    经过我们上次分析,数据库要有最基本的四张表,用户表,消息表,类型表,点赞表,评论表,接下来我们看着怎么设计吧 首先我们要清楚,表设计的代码是写在models下的 用户表 #一张表对应一个类 class ...

  8. Tornado实战

    抽屉之Tornado实战(1)--分析与架构 抽屉之Tornado实战(2)--数据库表设计 抽屉之Tornado实战(3)--注册 抽屉之Tornado实战(4)--发帖及上传图片 抽屉之Torna ...

  9. Javascript设计模式理论与实战:工厂方法模式

    本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用.在之前的<Javascript设计模式理论与实战:简单工厂模 ...

随机推荐

  1. WebService学习总结——调用第三方提供的webService服务

    互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的Web应用中显示,下面就以获取天气预报数据. 气象中心的管理系统将收 ...

  2. Java知多少(34)final关键字:阻止继承和多态

    在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final ...

  3. html页面工具-htmlUnit

    HtmlUnit测试工具的推出,创意非常好.是一款给java开发用的browser.说它是browser,其实它是对html建模并且提供API来访问页面,点击链接等等的java类库.     这样的测 ...

  4. PI SQL 语句

    insert [piarchive]..[picomp2](tag,time,value) values('ppnie_test','t',100) INSERT into pipoint..clas ...

  5. Linux目录详细说明大全(推荐)

    Linux目录详细说明大全,方便你以后合理规划及管理 "/" : 根目录Linux文件系统的入口.也是最高级,最重要的的目录.除衍生出其它目录,还和系统的开机,还原,系统修复有的, ...

  6. MySQL主从介绍 准备工作 配置主 配置从 测试主从同步

    配置主: • 安装mysql • 修改my.cnf,增加server-id=130和log_bin=xiaobo1 • 添加环境变量 Vim /root/.bash_profile PATH=$PAT ...

  7. 用Physijs在场景中添加物理效果

    1.创建可用Physijs的基本Three.js场景 创建一个可用Physijs的Three.js场景非常简单,只要几个步骤即可.首先我们要包含正确的文件, 需要引入physi.js文件.实际模拟物理 ...

  8. A股ROE连续3年超过15%的股票排名

    R连续3年,12个季度的滚动ROE,都超过15%的股票排名,个股滚动ROE = 最近4个季度的归母净利润 / ((期初归母净资产 + 期末归母净资产) / 2). 查看更多ROE连续3年超过15%的股 ...

  9. duilib进阶教程 -- 在MFC中使用duilib (1)

    由于入门教程的反响还不错,因此Alberl就以直播的形式来写<进阶教程>啦,本教程的前提: 1.请先阅读<仿迅雷播放器教程> 2.要有一定的duilib基础,如果还没,请先阅读 ...

  10. Inside The C++ Object Model(一)

    ============================================================================1-1. 关键字struct和class的一点区 ...