原理

1、面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ 、__delitem__、__setitem__方法

2、Tornado框架中,默认执行Handler的get/post等方法之前默认会执行 initialize方法,所以可以通过自定义的方式使得所有请求在处理前执行操作...

3、session其实就是定义在服务器端用于保存用户回话的容器,其必须依赖cookie才能实现。

4、工厂模式,此非必须

示例

# -*- coding:utf-8 -*-

# SESSION_ENGINE = "session_code.RedisSession"
SESSION_ENGINE = "session_code.CacheSession"
SESSION_ID = "__session_id__"
EXPIRES = 300 REDIS_HOST = '192.168.11.96'
REDIS_PORT = 6379

settings.py

# -*- coding:utf-8 -*-
# 1. "scrapy.middlware.C1"
# import importlib
# path = "scrapy.middlware.C1"
# md,cls = path.rsplit('.',maxsplit=1)
# m = importlib.import_module(md)
# getattr(m,cls)
# 2. 面向对象 # class Foo(object):
#
# def __getitem__(self, item):
# return "123"
#
# def __setitem__(self, key, value):
# pass
#
# def __delitem__(self, key):
# pass
# obj = Foo()
# v = obj['k1']
# print(v)
# obj['k1'] = 666
# del obj['k1'] # request.session['k1'] = 666 # 3.
import time
import hashlib
from . import settings def gen_random_str(): md5 = hashlib.md5()
md5.update(str(time.time()).encode('utf-8'))
return md5.hexdigest() class CacheSession(object): container = {} def __init__(self,handler):
self.handler = handler
self.session_id = settings.SESSION_ID
self.expires = settings.EXPIRES
self.initial() def initial(self):
client_random_str = self.handler.get_cookie(self.session_id)
if client_random_str and client_random_str in self.container:
self.random_str = client_random_str
else:
self.random_str = gen_random_str()
self.container[self.random_str] = {}
expires = time.time()+ self.expires
self.handler.set_cookie(self.session_id,self.random_str,expires=expires) def __getitem__(self, item):
return self.container[self.random_str].get(item) def __setitem__(self, key, value): self.container[self.random_str][key] = value def __delitem__(self, key):
if key in self.container[self.random_str]:
del self.container[self.random_str][key] class RedisSession(object):
def __init__(self,handler):
self.handler = handler
self.session_id = settings.SESSION_ID
self.expires = settings.EXPIRES
self.initial()
@property
def conn(self):
import redis
conn = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT)
return conn def initial(self):
client_random_str = self.handler.get_cookie(self.session_id) if client_random_str and self.conn.exists(client_random_str):
self.random_str = client_random_str
else:
self.random_str = gen_random_str() expires = time.time()+ self.expires
self.handler.set_cookie(self.session_id,self.random_str,expires=expires)
self.conn.expire(self.random_str,self.expires) def __getitem__(self, item):
import json
data_str = self.conn.hget(self.random_str,item)
if data_str:
return json.loads(data_str)
else:
return None def __setitem__(self, key, value):
import json
self.conn.hset(self.random_str,key,json.dumps(value)) def __delitem__(self, key):
self.conn.hdel(self.random_str,key) class SessionFactory(object):
@staticmethod
def get_session():
from . import settings
import importlib
engine = settings.SESSION_ENGINE
module_path,cls_name = engine.rsplit('.',maxsplit=1)
md = importlib.import_module(module_path)
cls = getattr(md,cls_name)
return cls

mysession.py

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from .mysession import SessionFactory class SessionHandler(object):
def initialize(self, *args, **kwargs):
cls = SessionFactory.get_session()
self.session = cls(self) # CacheSession对象,RedisSession对象 class LoginHandler(SessionHandler,RequestHandler):
# def initialize(self,*args,**kwargs):
# cls = SessionFactory.get_session()
# self.session = cls(self) # CacheSession对象,RedisSession对象
# print(self.session.container) def get(self):
self.render("login.html") def post(self, *args, **kwargs):
user = self.get_argument("user")
pwd = self.get_argument("pwd")
if user == "alex" and pwd == "":
self.session["user"] = user
self.redirect("/index")
else:
self.render("login.html") class IndexHandler(SessionHandler,RequestHandler):
# def initialize(self,*args,**kwargs):
# cls = SessionFactory.get_session()
# self.session = cls(self) # CacheSession对象,RedisSession对象
# # print(self.session.container) def get(self,*args,**kwargs):
user = self.session["user"]
print(user)
if user:
self.write("welcome index")
else:
self.redirect("/login") sett = {
"template_path": "views",
}
application = tornado.web.Application([
(r"/login", LoginHandler),
(r"/index", IndexHandler),
],**sett) # application.reverse_url("n1") if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

tornado_app.py

1、
def gen_random_str(): # 这个是为了生成随机字符串for session_id
md5 = hashlib.md5()
md5.update(str(time.time()).encode("utf-8"))
return md5.hexdigest() 2、
create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() 以上均可

补充:random_str

自制session的更多相关文章

  1. Tornado之笔记集合

    目录 一.基本使用 二.路由系统 三.视图函数 四.模版语言 五.cookie 六.CSRF 七.文件上传 八.异步非阻塞 九.RESTFUL 十.自定义组件 一.基本使用 1.最简使用 import ...

  2. 「七天自制PHP框架」第三天:PHP实现的设计模式

    往期回顾:「七天自制PHP框架」第二天:模型与数据库,点击此处 原文地址:http://www.cnblogs.com/sweng/p/6624845.html,欢迎关注:编程老头 为什么要使用设计模 ...

  3. netcore的Session使用小记

    之前说过,core需要什么功能就添加并使用什么中间件 照例,在Startup.cs的ConfigureServices方法中添加services.AddSession();再在Configure方法中 ...

  4. 自制MVC框架原理介绍

    当初用jsp开发程序时,因为很多东西写在一起混淆的,项目做大或者变更的时候就会很吃力,联动性太大,有时修改视图的东西都可能会影响业务逻辑,分层不明确. 后来听说了Struts MVC,做过几个示例,层 ...

  5. session实现购物车

    为实现简单的购物功能(购物车添加.账户查看.购物车商品删除.实时的购物商品数量及价格的计算显示.购物车商品数量可手动输入等),用session实现了一简单的以php语言为基础.连接MySQL数据库的购 ...

  6. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  7. 懒加载session 无法打开 no session or session was closed 解决办法(完美解决)

           首先说明一下,hibernate的延迟加载特性(lazy).所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作.因为hibernate当中支持实体对象,外键会与实体对象关联起来.如 ...

  8. 探索ASP.NET MVC5系列之~~~6.Session篇(进程外Session)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  9. Nhibernate的Session管理

    参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...

随机推荐

  1. PAT乙级1036

    1036 跟奥巴马一起编程 (15 分)   美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014 年底,为庆祝“计算机科学教育周”正式启动, ...

  2. RadioButtonFor值为false.默认选中的问题

    (自己看了下.图片有点宽.显示的不全.可以右键新标签查看) 作为一个新手.今天又开始了mvc的学习之旅.然而学习过程中又遇到了一个奇妙的问题.... 一切按部就班到了这里.注册界面. 一眼看上去就不对 ...

  3. HashTable、HashSet和Dictionary的区别(转载)

    1.HashTable哈希表(HashTable)表示键/值对的集合.在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类 ...

  4. ubuntu下安装eclipse IDE for C/C++ developers

     序 linux的GUI和windos比起来实在逊色,虽然它的终端模式(命令行模式)非常强大.linux发行版ubuntu的GUI相对其他版本要华丽一些,所以最近由redhat转向ubuntu进行li ...

  5. day 85 Vue学习之vue-cli脚手架下载安装及配置

      1. 先下载node.js,下载地址:https://nodejs.org/en/download/ 找个目录保存,解压下载的文件,然后配置环境变量,将下面的路径配置到环境变量中. 由于 Node ...

  6. Go语言相对于C++的优点

    Go语言是Google公司在2009年开源的一门高级编程语言,它为解决大型系统开发过程中的实际问题而设计,支持并发.规范统一.简单优雅,被很多Go语言传道者誉为“互联网时代的C语言”.而C++语言诞生 ...

  7. go学习笔记-环境安装

    环境安装 环境安装 主要包含三个部分 运行环境及开发sdk 系统环境和路径配置 IDE配置 以mac环境为例,其他环境类似 运行环境及开发sdk 使用 brew 安装 brew install go ...

  8. CBrother异或加密与C++异或加密函数

    CBrother脚本异或加密与C++异或加密函数 异或对于数据加密来说是最简单的方式,在一般的安全性要求不是非常高的地方,异或加密是最好的选择. C++异或加密代码 int g_PWD = 0xffe ...

  9. vue动态修改title

    1.项目中,cmd下 ,运行:cnpm install vue-wechat-title --save 2.在 main.js 中,设置: import VueWechatTitle from 'vu ...

  10. WPF 学习笔记-在WPF下创建托盘图标

    原文:WPF 学习笔记-在WPF下创建托盘图标 首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Co ...