原理

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. java学习笔记-JavaWeb篇二

    JavaWEB篇二 45 HttpSession概述46 HttpSession的生命周期 47 HttpSession常用方法示例48 HttpSessionURL重写 49 HttpSession ...

  2. CanOpen协议【CanFestival】移植方法 支持VC、QT、STM32

    前段时间学习了CanOpen协议,到网上下载的CanFestival3-10源码,移植到VC.QT.STM32等平台,由于网上的资源较少,走了不少弯路,移植好使用过程中才逐渐暴露出各种问题,比如OD字 ...

  3. 【H5】ie8如何兼容html5标签(hack)

    ie8是识别不了html5语义化标签的,解决方法: 在头部文件的<head></head>里面下如下代码    (这段代码的意思是如果ie版本低于ie8,就创建所有HTML5新 ...

  4. Node学习笔记之模块实现

    一.模块分类 由Node提供的模块,称为核心模块:部分核心模块在Node源代码的编译过程中,编译进了二进制执行文件.在node进程启动时,该部分就直接加载进内存,文件定位和编译执行的步骤可以省略掉,并 ...

  5. Unity 4.7 导出工程在XCode9/10上报错 validateRenderPassDescriptor:644: failed assertion `XXXX'

    Unity 4.7 导出工程在XCode9/10上报错 validateRenderPassDescriptor:644: failed assertion `Texture at colorAtta ...

  6. FPGA-Xilinx原语调用之ODDR

    记录背景:最近由于想实现GMIItoRGMII的功能,因此需要调用ODDR原语. ODDR:Dedicated Dual Data Rate (DDR) Output Register 通过ODDR把 ...

  7. ES6的Module系统

    http://es6.ruanyifeng.com/#docs/module Module 的语法 概述 严格模式 export 命令 import 命令 模块的整体加载 export default ...

  8. 【转载】ATL问题集

    原文:http://blog.csdn.net/fengrx/article/details/4171629 这些问题是以前在csdn当版主是一些朋友整理的,今天找到了,贴到这里来! #1 如何使用控 ...

  9. CF833B The Bakery 线段树,DP

    CF833B The Bakery LG传送门 线段树优化DP. 其实这是很久以前就应该做了的一道题,由于颓废一直咕在那里,其实还是挺不错的一道题. 先考虑\(O(n^2k)\)做法:设\(f[i][ ...

  10. eclipse - 新建jsp页面默认模板设置

    有时候我们自己如果没有现成的JSP模板时,系统一般会自动生成如下页面: 这个页面显然并不是我们所需要的,所以我们需要修改默认模板 进入 修改 <%@ page language="ja ...