我之前写的 session 一般保存在服务器的内存里, 那可以保存在缓存, 或是数据库, 那问题来了, 不同地方, 保存方式是不同的, 所以需要定义不同的类, cache/Redis/Memcached 类
session.py
- import config
- from hashlib import sha1
- import os
- import time
- create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
- class CacheSession:
- session_container = {}
- session_id = "__sessionId__"
- def __init__(self, handler):
- self.handler = handler
- client_random_str = handler.get_cookie(CacheSession.session_id, None)
- if client_random_str and client_random_str in CacheSession.session_container:
- self.random_str = client_random_str
- else:
- self.random_str = create_session_id()
- CacheSession.session_container[self.random_str] = {}
- expires_time = time.time() + config.SESSION_EXPIRES
- handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
- def __getitem__(self, key):
- ret = CacheSession.session_container[self.random_str].get(key, None)
- return ret
- def __setitem__(self, key, value):
- CacheSession.session_container[self.random_str][key] = value
- def __delitem__(self, key):
- if key in CacheSession.session_container[self.random_str]:
- del CacheSession.session_container[self.random_str][key]
- class RedisSession:
- def __init__(self, handler):
- pass
- class MemcachedSession:
- def __init__(self, handler):
- pass
把 session 写死, 如果更换 session 类型, 就需要花大量的精力去修改, 所以引出今天要说工厂方法模式, 在 session 文件里再定义一个 SessionFactory 类
- class SessionFactory:
- @staticmethod
- def get_session_obj(handler):
- obj = None
- if config.SESSION_TYPE == "cache":
- obj = CacheSession(handler)
- elif config.SESSION_TYPE == "memcached":
- obj = MemcachedSession(handler)
- elif config.SESSION_TYPE == "redis":
- obj = RedisSession(handler)
- return obj
并在配置文件里写入你要使用的 session 类型, 每次修改时只需修改配置文件
settings.py
- # Session 类型: cache/Redis/Memcached
- SESSION_TYPE = "cache"
- # Session 超时时间(秒)
- SESSION_EXPIRES = 60 * 20
在 Tornado 里, RequestHandler 类提供一个 initialize 方法, 用于在实例 handler 对象之前执行的, 我们在这个方法里创建 session 对象, 并赋给 handler 对象 self.session 这普通字段
request_handler.py
- import tornado.web
- from backend.session.session import SessionFactory
- class BaseRequestHandler(tornado.Web.RequestHandler):
- def initialize(self):
- self.session = SessionFactory.get_session_obj(self)
执行流程:
前端访问 url-->路由系统对应 handler 类 -->执行 initialize 方法 (创建 self.session 普通字段)--> 执行 session.py 下 SessionFactory 的静态方法 get_session_obj-->根据配置文件给定值, 实例化 session 对象, 并 return
代码详解
- from hashlib import sha1
- import os
- import time
- import config
- # 构造生成 session 随机字段串的函数
- create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
- class SessionFactory:
- #静态方法直接由类调用
- @staticmethod
- def get_session_obj(handler):
- obj = None
- if config.SESSION_TYPE == "cache":
- obj = CacheSession(handler)
- elif config.SESSION_TYPE == "memcached":
- obj = MemcachedSession(handler)
- elif config.SESSION_TYPE == "redis":
- obj = RedisSession(handler)
- return obj
- class CacheSession:
- #用于存储 session 键值对的字典
- session_container = {}
- #指定前端存储 cookie 时 key
- session_id = "__sessionId__"
- def __init__(self, handler):
- self.handler = handler
- #前端 cookie {"__sessionId__":"session 随机字符串"}
- client_random_str = handler.get_cookie(CacheSession.session_id, None)
- #如果能获取到 session 随机字符串而且也在服务器内存里
- if client_random_str and client_random_str in CacheSession.session_container:
- #把获取的随机串赋给 self.random_str
- self.random_str = client_random_str
- else:
- #没有就生成一个随机串
- self.random_str = create_session_id()
- #后台服务器{"session 随机串":{...}}
- CacheSession.session_container[self.random_str] = {}
- #设置过期时间
- expires_time = time.time() + config.SESSION_EXPIRES
- #并写入到 cookie
- handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
- def __getitem__(self, key):
- #self.session[key]
- ret = CacheSession.session_container[self.random_str].get(key, None)
- return ret
- def __setitem__(self, key, value):
- #self.session[key] = value
- CacheSession.session_container[self.random_str][key] = value
- def __delitem__(self, key):
- #del self.session[key]
- if key in CacheSession.session_container[self.random_str]:
- del CacheSession.session_container[self.random_str][key]
- class RedisSession:
- def __init__(self, handler):
- pass
- class MemcachedSession:
- def __init__(self, handler):
- pass
抽屉之 Tornado 实战(6)--session 工厂(工厂方法模式)
来源: http://www.bubuko.com/infodetail-2809978.html