当前位置:网站首页>tornado项目之路由装饰器
tornado项目之路由装饰器
2022-07-04 07:05:00 【youhebuke225】
- 当我们进行启动项目的时候,首先需要的就是注册路由,所以我们可以定义一个方法,这个方法叫
get_handlers
,来获取整个项目的路由 - 但是如何表示一个类是一个路由呢?这个时候,我们就用到了装饰器
open_handler
,经过这个装饰器装饰的类,那么他就是一个路由,所以open_handler
至少有两个参数path
路径index
用于路由排序
装饰器
我们在目录tornado项目core\decorators\open_handler
下写一个装饰器,类作为装饰器 点击
class HandlerDecorate:
"""路由装饰器 1. 实质上路由装饰器只是给装饰的类添加了__url_path__的属性 2. 我们初始化的时候就通过__url_path__这个属性来判断当前的类是路由的处理器 3. __url_path_index__用来给路由进行排序 """
def __init__(self, path, index=None) -> None:
self.__url_path__ = path
self.__url_path_index__ = index
def __call__(self, cls):
cls.__url_path__ = self.__url_path__
cls.__url_path_index__ = self.__url_path_index__
return cls
我们在__init__.py
中暴露这个装饰器
from core.decorators.open_handler.index import HandlerDecorate
open_handler = HandlerDecorate
只要经过@open_hander
修饰的类,就会含有__url_paht__
属性,如
@open_handler(path="/api/(.*)", index=1)
class openApiHandlerService(RequestHandler):
def get(self, *args, **kwargs):
self.write("hello world")
self.finish()
那么,openApiHandlerService就会含有__url_paht__
属性为/api/(.*)
路由的收集
定义get_handlers
方法,来获取被装饰器修饰的类
遍历项目文件
我们需要定义一个遍历项目文件的函数,当前函数用于查找项目中被
open_handler
修饰的类
我们在core\utils\module_utils.py
下,新建一个函数,用于遍历得到某文件下的所有的module
import importlib
import pkgutil
import os
def get_all_modules(path, file_name):
""" 获取路径下的所有file_name的module """
# 获取目录的配置(目录必须是一个包,才会有__path__属性)
_app = importlib.import_module(path)
def get_all_moudules_name(package_path, prefix=""):
# 用于深度遍历文件夹
for loader, name, is_package in pkgutil.iter_modules([package_path]):
if is_package:
# 如果还是一个包,那么再次遍历,且遍历的时候加上前缀
for _name in get_all_moudules_name(os.path.join(package_path, name), prefix=f"{
name}."):
yield prefix + _name
else:
yield prefix + name
return [
importlib.import_module(f"{
path}.{
module_name}")
for module_name in get_all_moudules_name(_app.__path__[0])
if module_name.split(".")[-1][:len(file_name)] == file_name
]
为了规范,我们所有的路由定义的类都凡在开都为handlers
的文件中
获取项目下所有的路由
我们在core\decorators\open_handler
下新建一个OpenHandler
的类,并定义一个get_handlers
的方法用来获取所有的路由
class OpenHandler:
"""路由容器 1. 初始化的时候获取路由的容器类和工具类 2. 返回tornado路由列表 """
def __init__(self, source_libs) -> None:
self.source_libs = source_libs # 传递目录名,用于获取目录下所有使用装饰器的类
self.handler_libs = [] # 存储路由的容器
def get_handlers(self):
self._handler_libs_ = []
_modules = [] # 目录下所有的moudule容器
for _path in self.source_libs:
_modules += get_all_modules(_path, "handler")
for _module in _modules:
self.handler_libs += [
dict(
path=_member.__url_path__,
handler=f"{
_member.__module__}.{
_member.__name__}",
index = _member.__url_path_index__
)
for _name,_member in inspect.getmembers(_module, inspect.isclass)
if hasattr(_member, "__url_path__")
]
# 排序
self.handler_libs.sort(key=lambda x: x['index'])
# 生成tornado的路由对象
_result = []
for _handler_lib in self.handler_libs:
# 遍历生成tornado的路由对象
_path = _handler_lib.get("path")
_result.append(
url(_path, import_object(_handler_lib.get("handler"))))
# 所有的路由列表
return _result
注册路由
一般我们在启动项目的时候需要注册路由
获取handler下的所有路由
为了项目规范我们把所有的路由都注册在了命名为
handler
的文件夹下,在启动环境的时候,我们一般调用Environment
类下的方法,我们在Environment
下,写一个获取handler下的路由的方法
class Environment:
...
def get_all_handlers(self):
open_handler = OpenHandler(["core"])
return open_handler.get_handlers()
他所表示的是获取core
文件夹下的所有的路由,然后我们进行路由的注册
class Application(Application):
def __init__(self):
# 初始化数据库、redis等,项目启动的时候,不要引入模型类
# 注册路由
handlers = environment.get_all_handlers()
# 添加动态路由
super().__init__(handlers, **config.settings)
测试
- 启动项目,我们输入
http://localhost:8888/api/
,就会发现我们可以访问到注册的路由了
边栏推荐
- How does the recv of TCP socket receive messages of specified length?
- [Valentine's day] - you can change your love and write down your lover's name
- Campus network problems
- Tar source code analysis 4
- Shopping malls, storerooms, flat display, user-defined maps can also be played like this!
- What is the use of cloud redis? How to use cloud redis?
- MySQL 45 lecture learning notes (XIII) delete half of the table data, and the table file size remains the same
- 2022年,或許是未來10年經濟最好的一年,2022年你畢業了嗎?畢業後是怎麼計劃的?
- Master-slave replication principle of MySQL database
- Vulhub vulnerability recurrence 77_ zabbix
猜你喜欢
NLP-文献阅读总结
Splicing plain text into JSON strings - easy language method
Set JTAG fuc invalid to normal IO port
云Redis 有什么用? 云redis怎么用?
Mobile adaptation: vw/vh
What is the use of cloud redis? How to use cloud redis?
Cervical vertebra, beriberi
Research on an endogenous data security interaction protocol oriented to dual platform and dual chain architecture
Campus network problems
Data double write consistency between redis and MySQL
随机推荐
Research on an endogenous data security interaction protocol oriented to dual platform and dual chain architecture
Code rant: from hard coding to configurable, rule engine, low code DSL complexity clock
How can the old version of commonly used SQL be migrated to the new version?
CMS source code of multi wechat management system developed based on thinkphp6, with one click curd and other functions
js 常用时间处理函数
Selection (021) - what is the output of the following code?
Tar source code analysis 8
2022年,或许是未来10年经济最好的一年,2022年你毕业了吗?毕业后是怎么计划的?
BasicVSR++: Improving Video Super-Resolutionwith Enhanced Propagation and Alignment
selenium IDE插件下载安装使用教程
Shopping malls, storerooms, flat display, user-defined maps can also be played like this!
What is the use of cloud redis? How to use cloud redis?
How does the recv of TCP socket receive messages of specified length?
About how idea sets up shortcut key sets
The final week, I split
【网络数据传输】基于FPGA的百兆网/兆网千UDP数据包收发系统开发,PC到FPGA
tars源码分析之1
Mysql 45讲学习笔记(六)全局锁
The crackdown on Huawei prompted made in China to join forces to fight back, and another enterprise announced to invest 100 billion in R & D
Tar source code analysis Part 2