• 抽屉之Tornado实战(6)--session工厂(工厂方法模式)


      我之前写的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
    
  • 相关阅读:
    《BI那点儿事》数据流转换——聚合
    《BI那点儿事》数据仓库建模:星型模式、雪片模式
    《BI那点儿事》Cube的存储
    《BI项目笔记》创建多维数据集Cube(2)
    《BI项目笔记》增量ETL数据抽取的策略及方法
    类对象切割对虚函数调用的影响
    类对象切割对虚函数调用的影响
    显示调用析构函数潜在隐患分析
    显示调用析构函数潜在隐患分析
    PeekMessage和GetMessage函数的主要区别
  • 原文地址:https://www.cnblogs.com/xinsiwei18/p/5879486.html
Copyright © 2020-2023  润新知