原理

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. C++矩阵库 Eigen 简介

    最近需要用 C++ 做一些数值计算,之前一直采用Matlab 混合编程的方式处理矩阵运算,非常麻烦,直到发现了 Eigen 库,简直相见恨晚,好用哭了. Eigen 是一个基于C++模板的线性代数库, ...

  2. PCB设计工程师面试题

    网上的一套PCB设计工程师面试题,测下你能不能拿90分?  [复制链接]           一.填空 1.PCB上的互连线按类型可分为()和() . 2.引起串扰的两个因素是()和(). 3.EMI ...

  3. 记一次异机rman还原后的操作

    当时从主库通过rman备份到目前测试库还原之后,由于备份是在备库备份的,所以数据库还原后状态为readonly,standby_file_management参数为auto.首先需要通过alter d ...

  4. C++重载运算符练习--对people类重载“= =”运算符和“=”运算符

    题目描述 对people类重载“= =”运算符和“=”运算符,“==”运算符判断两个people类对象的id属性是否相等:“=”运算符实现people类对象的赋值操作. 代码如下 #include&l ...

  5. 20155229 《信息安全系统设计基础》 week10 课上测试ch06

    1( 单选题 | 1 分) 下面代码中,对数组x填充后,采用直接映射高速缓存,所有对x和y引用的命中率为() A . 1 B . 1/4 C . 1/2 D . 3/4 正确答案: D 解析:填充消除 ...

  6. 20155338《网络对抗技术》 Exp1 PC平台逆向破解

    20155338<网络对抗技术> Exp1 PC平台逆向破解 实践目标 1.实践的对象是一个名为pwn1的linux可执行文件. 2.该程序正常执行流程是:main调用foo函数,foo函 ...

  7. 《Java 程序设计》课堂实践项目-简易计算器

    <Java 程序设计>课堂实践项目简易计算器 课后学习总结 目录 改变 简易计算器实验要求 课堂实践成果 课后思考 改变 修改了博客整体布局,过去就贴个代码贴个图很草率,这次布局和内容都有 ...

  8. $watch和$observe的使用

    $observe 是Attribute对象的一个方法,用来监听DOM中属性值的变化.比如 attr1="{{name}}" Attribute定义在directive中的link函 ...

  9. Docker系列之CentOS7安装Docker(一)

    0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 一.瞎扯淡(只讲有用的) 感兴趣的同学可以上网搜索一下docker具体的介绍.我这边主要介绍偏实战的内容,不喜勿喷,有问题也请指出 ...

  10. 设计模式之module模式及其改进

    写在前面 编写易于维护的代码,其中最重要的方面就是能够找到代码中重复出现的主题并优化他们,这也是设计模式最有价值的地方 <head first设计模式>里有一篇文章,是说使用模式的心智, ...