【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台
2017-08-14 00:00
751 查看
本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。
示例代码:
接口示例代码
示例代码:
依赖注入示例
注:原理:首先需要明确一切事物皆对象类也是对象,类是有Type创建的,当类实例化的时候,会调用type类的call方法,call方法会调用new方法,new方法调用init方法。
备注:
Infrastructure:一些公共组件,例如md5加密,分页模块,session等。
Model:关于数据库的逻辑处理模块
Repository:数据访问层,包含数据库的增删改查
Service:服务层,调用Model,包含带有规则的请求和返回
Statics:静态文件目录
UI层:业务处理
Views:模板文件
Application:tornado程序的起始文件
Config:配置文件
Mapper:依赖注入文件,负责整个框架不同类的依赖注入
本文主要以用户管理为例进行介绍,因此我们来关注一下User.py文件:
代码结构:
下面对上述代码结构做一一介绍:
classIUseRepository:
"""
用户信息仓库接口
"""
deffetch_one_by_user_pwd(self,username,password):
"""
根据用户名密码获取模型对象
:paramusername:主键ID
:parampassword:主键ID
:return:
"""
deffetch_one_by_email_pwd(self,email,password):
"""
根据邮箱密码获取模型对象
:paramemail:主键ID
:parampassword:主键ID
:return:
"""
defupdate_last_login_by_nid(self,nid,current_date):
"""
根据ID更新最新登陆时间
:paramnid:
:return:
"""
从上述代码可以看出,数据库访问类如果继承IUseRepository类,就必须实现其中的抽象方法。
接下来的三个类,VipType、UserType、User是与用户信息相关的类,是数据库需要保存的数据,我们希望存入数据库的数据格式为:nid、username、email、last_login、user_type_id、vip_type_id,其中User类用于保存上述数据。因为user_type_id、vip_type_id存的是数字,即user_type_id、vip_type_id是外键,不能直接在前端进行展示,因此,我们创建了VipType、UserType类,用于根据id,获取对应的VIP级别和用户类型。
示例代码:
User类
UserType类
VipType类
注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。
接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:
示例代码:
classUserService:
def__init__(self,user_repository):
self.userRepository=user_repository
defcheck_login(self,username=None,email=None,password=None):
ifusername:
user_model=self.userRepository.fetch_one_by_user_pwd(username,password)
else:
user_model=self.userRepository.fetch_one_by_email_pwd(email,password)
ifuser_model:
current_date=datetime.datetime.now()
self.userRepository.update_last_login_by_nid(user_model.nid,current_date)
returnuser_model
这里,我们重点介绍一下上述代码:
初始化参数user_repository:通过依赖注入对应的数据库访问类的对象;
check_login:访问数据库的关键逻辑处理方法,根据用户是用户名+密码方式还是邮箱加密码的方式登录,然后调用对应的数据库处理方法,如果登陆成功,更新时间和最后登录时间,最后将User类的实例返回给调用它的服务层service。(详细见下文数据库处理类的方法)
我们先来看一下对应的数据库处理类中的一个方法:
示例代码:
deffetch_one_by_user_pwd(self,username,password):
ret=None
cursor=self.db_conn.connect()
sql="""selectnid,username,email,last_login,vip,user_typefromUserInfowhereusername=%sandpassword=%s"""
cursor.execute(sql,(username,password))
db_result=cursor.fetchone()
self.db_conn.close()
ifdb_result:
ret=User(nid=db_result['nid'],
username=db_result['username'],
email=db_result['email'],
last_login=db_result['last_login'],
user_type=UserType(nid=db_result['user_type']),
vip_type=VipType(nid=db_result['vip'])
)
returnret
这里我们使用pymysql进行数据库操作,以用户名+密码登陆为例,如果数据库有对应的用户名和密码,将查询结果放在User类中进行初始化,至此,ret中封装了用户的全部基本信息,将ret返回给上面的check_login方法,即对应上文中的返回值user_model,user_model返回给调用它的服务层service。
总结:Molde最终将封装了用户基本信息的User类的实例返回给服务层service。
目录结构:
同样的,我们只介绍User文件夹:它包含4个py文件:
ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
Request:封装请求Moldel文件对应数据库协调类的参数
Response:封装需要返回UI层的参数
Sevice:核心服务处理文件
下面对上述目录做详细代码:
ModelView:
classUserModelView:
def__init__(self,nid,username,email,last_login,user_type_id,user_type_caption,vip_type_id,vip_type_caption):
self.nid=nid
self.username=username
self.email=email
self.last_login=last_login
self.user_type=user_type_id
self.user_type_caption=user_type_caption
self.vip_type=vip_type_id
self.vip_type_caption=vip_type_caption
注:对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
Request:
classUserRequest:
def__init__(self,username,email,password):
self.username=username
self.email=email
self.password=password
Response:
classUserResponse:
def__init__(self,status=True,message='',model_view=None):
self.status=status#是否登陆成功的状态
self.message=message#错误信息
self.modelView=model_view#登陆成功后的用户数据
classUserService:
def__init__(self,model_user_service):#通过依赖注入Moldel对应的数据库业务协调方法,此例中对应上文中的user_service
self.modelUserService=model_user_service
defcheck_login(self,user_request):#核心服务层业务处理方法
response=UserResponse()#实例化返回类
try:
model=self.modelUserService.check_login(user_request.username,user_request.email,user_request.password)#接收上文中的用户基本信息,是User类的实例
ifnotmodel:
raiseException('用户名或密码错误')
else:#如果登陆成功,通过UserModelView类格式化返回前端的数据
model_view=UserModelView(nid=model['nid'],
username=model['usename'],
email=model['email'],
last_login=model['last_login'],
user_type_id=model['user_type'].nid,
user_type_caption=model['user_type'].caption,
vip_type_id=model['vip_type'].nid,
vip_type_caption=model['vip_type'].caption,)
response.modelView=model_view#定义返回UI层的用户信息
exceptExceptionase:
response.status=False
response.message=str(e)
总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。
示例代码:
classLogin(AdminRequestHandler):
defget(self,*args,**kwargs):
is_login=self.session["is_login"]
current_user=""
ifis_login:
current_user=self.session["user_info"].username
self.render('Account/Login.html',current_user=current_user)
defpost(self,*args,**kwargs):
user_request=[]
#获取用户输入的用户名邮箱密码
user_request.append(self.get_argument('name',None))
user_request.append(self.get_argument('email',None))
user_request.append(self.get_argument('pwd',None))
checkcode=self.get_argument("checkcode",None)
Mapper.mapper(*user_request)
obj=UserService.check_login()
self.session["is_login"]=True
self.session["user_info"]=obj.modelView
self.write("已登陆")
总结以上就是基于领域驱动模型的用户管理后台,包含数据库操作文件,数据库业务处理文件,服务端文件,UI层文件。如果本文对您有参考价值,欢迎帮博主点下文章下方的推荐,谢谢!
一、预备知识:
1.接口:
python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基于python的抽象类和抽象方法实现接口功能。示例代码:
fromabcimportABCMetafromabcimportabstractmethod#导入抽象方法 classFather(metaclass=ABCMeta):#创建抽象类 @abstractmethoddeff1(self):pass@abstractmethoddeff2(self):pass classF1(Father):deff1(self):pass deff2(self):pass deff3(self):passobj=F1()
接口示例代码
2.依赖注入:
依赖注入的作用是将一系列无关的类通过注入参数的方式实现关联,例如将类A的对象作为参数注入给类B,那么当调用类B的时候,类A会首先被实例化。示例代码:
classMapper:__mapper_ralation={}@staticmethoddefregist(cls,value):Mapper.__mapper_ralation[cls]=value@staticmethoddefexist(cls):ifclsinMapper.__mapper_ralation:returnTrueelse:returnFalse@staticmethoddefvalue(cls):returnMapper.__mapper_ralation[cls]classMytype(type):def__call__(cls,*args,**kwargs):obj=cls.__new__(cls,*args,**kwargs)arg_list=list(args)ifMapper.exist(cls):value=Mapper.value(cls)arg_list.append(value)obj.__init__(*arg_list)returnobjclassFoo(metaclass=Mytype):def__init__(self,name):self.name=namedeff1(self):print(self.name)classBar(metaclass=Mytype):def__init__(self,name):self.name=namedeff1(self):print(self.name)Mapper.regist(Foo,"666")Mapper.regist(Bar,"999")f=Foo()print(f.name)b=Bar()print(b.name)
依赖注入示例
注:原理:首先需要明确一切事物皆对象类也是对象,类是有Type创建的,当类实例化的时候,会调用type类的call方法,call方法会调用new方法,new方法调用init方法。
二、企业级应用设计
1.总体框架目录结构:
备注:
Infrastructure:一些公共组件,例如md5加密,分页模块,session等。
Model:关于数据库的逻辑处理模块
Repository:数据访问层,包含数据库的增删改查
Service:服务层,调用Model,包含带有规则的请求和返回
Statics:静态文件目录
UI层:业务处理
Views:模板文件
Application:tornado程序的起始文件
Config:配置文件
Mapper:依赖注入文件,负责整个框架不同类的依赖注入
2.首先我们从Moldel开始查看:
文件目录:本文主要以用户管理为例进行介绍,因此我们来关注一下User.py文件:
代码结构:
下面对上述代码结构做一一介绍:
IUseRepository类:接口类,用于约束数据库访问类的方法 示例代码:
从上述代码可以看出,数据库访问类如果继承IUseRepository类,就必须实现其中的抽象方法。
接下来的三个类,VipType、UserType、User是与用户信息相关的类,是数据库需要保存的数据,我们希望存入数据库的数据格式为:nid、username、email、last_login、user_type_id、vip_type_id,其中User类用于保存上述数据。因为user_type_id、vip_type_id存的是数字,即user_type_id、vip_type_id是外键,不能直接在前端进行展示,因此,我们创建了VipType、UserType类,用于根据id,获取对应的VIP级别和用户类型。
示例代码:
classUser:"""领域模型""" def__init__(self,nid,username,email,last_login,user_type,vip_type):self.nid=nidself.username=usernameself.email=emailself.last_login=last_loginself.user_type=user_typeself.vip_type=vip_type
User类
classUserType:USER_TYPE=({'nid':1,'caption':'用户'},{'nid':2,'caption':'商户'},{'nid':3,'caption':'管理员'},)def__init__(self,nid):self.nid=niddefget_caption(self):caption=NoneforiteminUserType.USER_TYPE:ifitem['nid']==self.nid:caption=item['caption']break returncaptioncaption=property(get_caption)
UserType类
classVipType:VIP_TYPE=({'nid':1,'caption':'铜牌'},{'nid':2,'caption':'银牌'},{'nid':3,'caption':'金牌'},{'nid':4,'caption':'铂金'},)def__init__(self,nid):self.nid=niddefget_caption(self):caption=NoneforiteminVipType.VIP_TYPE:ifitem['nid']==self.nid:caption=item['caption']break returncaptioncaption=property(get_caption)
VipType类
注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。
接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:
示例代码:
这里,我们重点介绍一下上述代码:
初始化参数user_repository:通过依赖注入对应的数据库访问类的对象;
check_login:访问数据库的关键逻辑处理方法,根据用户是用户名+密码方式还是邮箱加密码的方式登录,然后调用对应的数据库处理方法,如果登陆成功,更新时间和最后登录时间,最后将User类的实例返回给调用它的服务层service。(详细见下文数据库处理类的方法)
我们先来看一下对应的数据库处理类中的一个方法:
这里我们使用pymysql进行数据库操作,以用户名+密码登陆为例,如果数据库有对应的用户名和密码,将查询结果放在User类中进行初始化,至此,ret中封装了用户的全部基本信息,将ret返回给上面的check_login方法,即对应上文中的返回值user_model,user_model返回给调用它的服务层service。
总结:Molde最终将封装了用户基本信息的User类的实例返回给服务层service。
3.接下来我们看一下服务层service:
service也是一个承上启下的作用,它调用Moldel文件对应的数据库业务协调方法,并被对应的UI层调用(本例中是UIadmin)。目录结构:
同样的,我们只介绍User文件夹:它包含4个py文件:
ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
Request:封装请求Moldel文件对应数据库协调类的参数
Response:封装需要返回UI层的参数
Sevice:核心服务处理文件
下面对上述目录做详细代码:
ModelView:
注:对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
Request:
Response:
UserService:
总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。
4.UI层
UI层主要负责业务处理完成后与前端的交互,它是服务层Service的调用者:示例代码:
总结以上就是基于领域驱动模型的用户管理后台,包含数据库操作文件,数据库业务处理文件,服务端文件,UI层文件。如果本文对您有参考价值,欢迎帮博主点下文章下方的推荐,谢谢!
相关文章推荐
- 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
- [.NET领域驱动设计实战系列]专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能
- [.NET领域驱动设计实战系列]专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能
- [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店
- [导入]从架构设计到系统实施——基于.NET 3.0的全新企业应用系列课程(7):设计基于MMC 3.0的管理工具.zip(8.70 MB)
- 领域驱动设计实战—基于DDDLite的权限管理OpenAuth.net
- [导入]从架构设计到系统实施——基于.NET 3.0的全新企业应用系列课程(8):为Vista用户设计Gadget.zip(8.67 MB)
- 使用Apworks开发基于CQRS架构的应用程序(二):创建领域模型项目
- 后台设计的基石:用户权限管理(RBAC)及工作流(workflow)模型
- [导入]从架构设计到系统实施——基于.NET 3.0的全新企业应用系列课程(7):设计基于MMC 3.0的管理工具.zip(8.70 MB)
- [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店
- [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店
- [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店
- 基于整合了struts 和hibernate 的j2ee 架构的用户权限管理系统的设计与实现
- JSF项目中实现基于RBAC模型的权限管理设计
- 敏捷开发产品管理系列之八:基于业务设计技术架构(兼谈12306性能问题)
- 敏捷开发产品管理系列之八:基于业务设计技术架构(兼谈12306性能问题)
- 项目架构开发:业务逻辑层之领域驱动失血模型