抽屉之Tornado实战(6)--session工厂(工厂方法模式)
我之前写的session一般保存在服务器的内存里,那可以保存在缓存,或是数据库,那问题来了,不同地方,保存方式是不同的,所以需要定义不同的类,cache/redis/memcached类
session.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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类
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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
1 2 3 4 | # Session类型:cache/redis/memcached SESSION_TYPE = "cache" # Session超时时间(秒) SESSION_EXPIRES = 60 * 20 |
在Tornado里,RequestHandler类提供一个initialize方法,用于在实例handler对象之前执行的,我们在这个方法里创建session对象,并赋给handler对象self.session这普通字段
request_handler.py
1 2 3 4 5 6 7 8 9 | 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
代码详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 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 |
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步