收藏的一个tornado热加载框架# coding:utf-8
#mvc框架总入口
import sys
import os
import time
import re
import tornado.gen
import tornado.web
import traceback
import mvcroot
import mvcroot.conf
import ujson as json
if(sys.version[0:2]=="2."):
pass
else:
from importlib import reload
pymodule_cache_dict={} #用来缓存加载到内存的控制器类
class MVCMainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def httprequest_handler(self,requestpath):
requestpath=requestpath.strip()
requestpath.replace("//","/")
if(requestpath[-1:]=="/"):
requestpath=requestpath[:-1]
#==============================检查静态资源文件Begin====================================
extsz=os.path.splitext(requestpath)
extname=extsz[1].lower()
if(extname!=""): #如果请求的为静态资源
if(extname in [".txt",".css",".jpg",".gif",".png",".doc",".docx",".xls",".xlsx",""]):
if(extname in mvcroot.conf.mimetype):
self.set_header("Content-Type",mvcroot.conf.mimetype.get(extname,""))
#print(mvcroot.conf.mimetype.get(extname,""))
yield self.static_resource_handler(requestpath,extname)
return
#==============================检查静态资源文件End====================================
#==============================检测路由表中的所有url是否匹配,如果有匹配的,执行匹配的路由指向的类的page_load函数Begin==================
isfindinroutemap=False #在路由表中是否找到匹配的
routerallclassname="" #匹配的路由中指向的类的完整名称
routerclassname="" #匹配的路由中指向的类的名称
routermodulename="" #匹配的路由中指向的类所在的模块名称(不包含这个文件里面的某个class类),用来__import__加载用
isurlcontainsargs=False
for myroutetuple in mvcroot.conf.routemap:
url = requestpath #这是url源文本
p1 = myroutetuple[0] #这是我们写的正则表达式
pattern1 = re.compile(p1)#同样是编译
matcher1 = re.findall(pattern1,url)#同样是查询
if(len(matcher1)>0):
if(p1.find("(")>-1):
isurlcontainsargs=True
isfindinroutemap=True
routerallclassname=str(myroutetuple[1])[8:-2]
rfindindex=routerallclassname.rfind(".") #右边第一个.出现的位置
routermodulename=routerallclassname[0:rfindindex]
routerclassname=routerallclassname[rfindindex+1:]
print("routerclassname:{0},routermodulename:{1}".format(routerclassname,routermodulename))
page_args=matcher1[0]
if(type(page_args)!=tuple):
page_args=[page_args]
print("page_args:{0}".format(page_args))
break
if(isfindinroutemap==True): #如果在路由表匹配到符合的url,则执行路由处理函数
mypageclass=__import__(routermodulename,fromlist=True)
#print("mypageclass:{0}".format(mypageclass))
if(mvcroot.conf.debug):
reload(mypageclass)
mypage= getattr(mypageclass,routerclassname)()
mypage.request=self.request
mypage.tornadowebinstance=self
errmsg=""
try:
yield mypage.prepare()
except Exception as ex:
traceback.print_exc()
mypage.isend=True
self.write(traceback.format_exc().replace("\n","
"))
if(mypage.isend==True): #如果控制器确定要终止执行,则到这里就停止
return
try:
if(isurlcontainsargs):
yield mypage.page_load(*page_args)
else:
yield mypage.page_load()
except Exception as ex:
traceback.print_exc()
self.write(traceback.format_exc().replace("\n","
"))
return
#=============================================路由处理结束================================
#======================================检查请求的html文件Begin=================================
#========================如果路由没有检测到html页面的路由,则检查真正的静态文件 Begin======================
if(extname in [".htm",".html"]):
self.set_header("Content-Type","text/html")
yield self.static_resource_handler(requestpath,extname)
return
#===============================检查请求的html文件End=================
#=============================按照url路径寻找并加载控制器Begin===========================
#print("requestpath:"+requestpath)
patharray=requestpath.split("/")
patharraylen=len(patharray)
#print(patharray)
controllerandmethodname=""
controllername=""
methodname=""
if(patharraylen>1):
modulepre=requestpath[0:requestpath.rfind("/")].replace("/",".")
controllerandmethodname=patharray[patharraylen-1]
else:
modulepre=""
controllerandmethodname=patharray[0]
if(controllerandmethodname.find("!")>-1):
sz=controllerandmethodname.split("!")
controllername=sz[0]
methodname=sz[1]
else:
controllername=controllerandmethodname
#print("controllername:{0},methodname:{1},modulepre:{2}".format(controllername,methodname,modulepre))
if(controllername==""):
controllername="index"
#print("url中的控制器为空,将控制器名字设置为index")
# self.write("必须提供控制器名称")
# return
if(controllername=="mvcrootdoor" or controllername=="conf"):
self.write("you can't use this controller name")
return
pymoduleload="" #需要调用__import__加载的类名
if(modulepre!=""):
pymoduleload="mvcroot."+modulepre+"."+controllername
else:
pymoduleload="mvcroot."+controllername
#print("pymoduleload:"+pymoduleload)
try:
# 加载性能测试,80万次每秒的加载速度,如果是开发模式热更新的话,4000次每秒
# t1=time.time()
# for i in range(0,1000):
# mypageclass=__import__(pymoduleload,fromlist=True)
# reload(mypageclass)
# t2=time.time()
# print(t2-t1)
if(pymoduleload not in pymodule_cache_dict):
mypageclass=__import__(pymoduleload,fromlist=True)
pymodule_cache_dict[pymoduleload]=mypageclass
if(mvcroot.conf.debug==True):
mypageclass=__import__(pymoduleload,fromlist=True)
reload(mypageclass)
pymodule_cache_dict[pymoduleload]=mypageclass
#print("isdebug:{0},reload controller".format(mvcroot.conf.debug))
else:
#print("isdebug:{0},load controller from cache".format(mvcroot.conf.debug))
mypageclass=pymodule_cache_dict[pymoduleload]
pass
except Exception as ex:
self.write(traceback.format_exc().replace("\n","
"))
return
#self.redirect()
#print(mypageclass)
#print(dir(self.request))
# print("arguments:{0}".format(self.request.arguments))
# print("query_arguments:{0}".format(self.request.query_arguments))
# print("body:{0}".format(self.request.body))
# print("body_arguments:{0}".format(self.request.body_arguments))
mypage=mypageclass.page()
mypage.request=self.request
mypage.tornadowebinstance=self
errmsg=""
try:
yield mypage.prepare()
except Exception as ex:
errmsg=traceback.format_exc()
traceback.print_exc()
if(mypage.isend==True): #如果控制器确定要终止执行,则到这里就停止
return
if(methodname==""):
try:
r=yield mypage.page_load()
except Exception as ex:
errmsg=traceback.format_exc()
traceback.print_exc()
else:
try:
methodnamerun=getattr(mypage,methodname)
r=yield methodnamerun()
except Exception as ex:
errmsg=traceback.format_exc()
traceback.print_exc()
if(errmsg!=""):
print(errmsg)
self.write(errmsg.replace("\n","
"))
return
#print("执行结果:"+str(r))
rtype=type(r)
#print("r type:{0}".format(rtype.__name__))
if(rtype==mvcroot.ViewReturn):
viewname=r.Get()
print("viewname:"+viewname)
realviewfilepath=""
elif(rtype==mvcroot.TextReturn):
txt=r.Get()
self.write(txt)
elif(rtype==mvcroot.JsonReturn):
jsonresult=r.Get()
if(jsonresult!=None):
sendtext=json.dumps(jsonresult)
self.write(sendtext)
elif(rtype==str):
self.write(r)
elif(rtype.__name__ in ["int","long","float","bool"]):
self.write(str(r))
elif(rtype.__name__=="unicode"):
self.write(r.encode("utf8"))
elif(rtype==list or rtype==dict):
self.write(json.dumps(r))
elif(r==None):
#print("返回值为空值")
pass
else:
if(hasattr(r,"__dict__")):
self.write(json.dumps(r.__dict__))
mypage.request=None
mypage.tornadowebinstance=None
#r=self.render_string("page1.html")
pass
@tornado.gen.coroutine
def static_resource_handler(self,requestpath,extname):
realfilepath=mvcroot.rootpath+"/"+requestpath
#print("realfilepath:"+realfilepath)
#self.write(realfilepath)
if(os.path.exists(realfilepath)):
f=open(realfilepath,"rb")
filecontent=f.read()
f.close()
self.write(filecontent)
else:
self.write("Static File:["+realfilepath+"] Not Exists")
pass
@tornado.gen.coroutine
def routeHandler(self):
pass
@tornado.gen.coroutine
def get(self,requestpath):
yield self.httprequest_handler(requestpath)
pass
@tornado.gen.coroutine
def post(self,requestpath):
yield self.httprequest_handler(requestpath)
pass
@tornado.gen.coroutine
def put(self,requestpath):
yield self.httprequest_handler(requestpath)
pass
@tornado.gen.coroutine
def delete(self, requestpath):
yield self.httprequest_handler(requestpath)
pass