tornado项目之基于领域驱动模型架构设计的京东用户管理后台
本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。
一、预备知识:
1.接口:
python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基于python的抽象类和抽象方法实现接口功能。
示例代码:
 接口示例代码
 接口示例代码2.依赖注入:
依赖注入的作用是将一系列无关的类通过注入参数的方式实现关联,例如将类A的对象作为参数注入给类B,那么当调用类B的时候,类A会首先被实例化。
示例代码:
 依赖注入示例
 依赖注入示例注:原理:首先需要明确一切事物皆对象类也是对象,类是有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类:接口类,用于约束数据库访问类的方法
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | classIUseRepository:    """    用户信息仓库接口    """    deffetch_one_by_user_pwd(self, username, password):        """        根据用户名密码获取模型对象        :param username: 主键ID        :param password: 主键ID        :return:        """    deffetch_one_by_email_pwd(self, email, password):        """        根据邮箱密码获取模型对象        :param email: 主键ID        :param password: 主键ID        :return:        """    defupdate_last_login_by_nid(self,nid,current_date):        """        根据ID更新最新登陆时间        :param nid:        :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类
 User类 UserType类
 UserType类 VipType类
 VipType类注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。
接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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。(详细见下文数据库处理类的方法)
我们先来看一下对应的数据库处理类中的一个方法:
| 1 | 示例代码: | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | deffetch_one_by_user_pwd(self, username, password):       ret =None       cursor =self.db_conn.connect()       sql ="""select nid,username,email,last_login,vip,user_type from UserInfo where username=%s and password=%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。
3.接下来我们看一下服务层service:
service也是一个承上启下的作用,它调用Moldel文件对应的数据库业务协调方法,并被对应的UI层调用(本例中是UIadmin)。
目录结构:

同样的,我们只介绍User文件夹:它包含4个py文件:
- ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
- Request:封装请求Moldel文件对应数据库协调类的参数
- Response:封装需要返回UI层的参数
- Sevice:核心服务处理文件
下面对上述目录做详细代码:
ModelView:
| 1 2 3 4 5 6 7 8 9 10 11 | 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:
| 1 2 3 4 5 6 | classUserRequest:    def__init__(self, username, email, password):        self.username =username        self.email =email        self.password =password | 
Response:
| 1 2 3 4 5 6 | classUserResponse:    def__init__(self, status=True, message='', model_view=None):        self.status =status    # 是否登陆成功的状态        self.message =message  #错误信息        self.modelView =model_view  #登陆成功后的用户数据  | 
UserService:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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层的用户信息        exceptException as e:            response.status =False            response.message =str(e) | 
总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。
4.UI层
UI层主要负责业务处理完成后与前端的交互,它是服务层Service的调用者:
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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层文件。如果本文对您有参考价值
tornado源码系列
tornado项目之基于领域驱动模型架构设计的京东用户管理后台
posted @ 2016-09-07 09:15 战神王恒 阅读(506) | 评论 (7) 编辑
tornado高效开发必备之源码详解
posted @ 2016-09-01 09:10 战神王恒 阅读(945) | 评论 (22) 编辑
tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片
posted @ 2016-08-29 09:17 战神王恒 阅读(1072) | 评论 (18) 编辑
Web框架之Tornado
posted @ 2016-08-25 18:41 战神王恒 阅读(91) | 评论 (0) 编辑
本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。
一、预备知识:
1.接口:
python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基于python的抽象类和抽象方法实现接口功能。
示例代码:
 接口示例代码
 接口示例代码2.依赖注入:
依赖注入的作用是将一系列无关的类通过注入参数的方式实现关联,例如将类A的对象作为参数注入给类B,那么当调用类B的时候,类A会首先被实例化。
示例代码:
 依赖注入示例
 依赖注入示例注:原理:首先需要明确一切事物皆对象类也是对象,类是有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类:接口类,用于约束数据库访问类的方法
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | classIUseRepository:    """    用户信息仓库接口    """    deffetch_one_by_user_pwd(self, username, password):        """        根据用户名密码获取模型对象        :param username: 主键ID        :param password: 主键ID        :return:        """    deffetch_one_by_email_pwd(self, email, password):        """        根据邮箱密码获取模型对象        :param email: 主键ID        :param password: 主键ID        :return:        """    defupdate_last_login_by_nid(self,nid,current_date):        """        根据ID更新最新登陆时间        :param nid:        :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类
 User类 UserType类
 UserType类 VipType类
 VipType类注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。
接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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。(详细见下文数据库处理类的方法)
我们先来看一下对应的数据库处理类中的一个方法:
| 1 | 示例代码: | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | deffetch_one_by_user_pwd(self, username, password):       ret =None       cursor =self.db_conn.connect()       sql ="""select nid,username,email,last_login,vip,user_type from UserInfo where username=%s and password=%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。
3.接下来我们看一下服务层service:
service也是一个承上启下的作用,它调用Moldel文件对应的数据库业务协调方法,并被对应的UI层调用(本例中是UIadmin)。
目录结构:

同样的,我们只介绍User文件夹:它包含4个py文件:
- ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
- Request:封装请求Moldel文件对应数据库协调类的参数
- Response:封装需要返回UI层的参数
- Sevice:核心服务处理文件
下面对上述目录做详细代码:
ModelView:
| 1 2 3 4 5 6 7 8 9 10 11 | 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:
| 1 2 3 4 5 6 | classUserRequest:    def__init__(self, username, email, password):        self.username =username        self.email =email        self.password =password | 
Response:
| 1 2 3 4 5 6 | classUserResponse:    def__init__(self, status=True, message='', model_view=None):        self.status =status    # 是否登陆成功的状态        self.message =message  #错误信息        self.modelView =model_view  #登陆成功后的用户数据  | 
UserService:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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层的用户信息        exceptException as e:            response.status =False            response.message =str(e) | 
总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。
4.UI层
UI层主要负责业务处理完成后与前端的交互,它是服务层Service的调用者:
示例代码:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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层文件。如果本文对您有参考价值
 
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号