express 项目分层实践详解
前言
上次我们搭建了一个基本的express后台,但是这样的项目结构的可扩展性,维护性和代码复用性都不是很好,参照之前学习JavaWeb时候的四层架构设计,用分层的思想来对express进行一点小优化,进一步提高代码的可拓展性。本文的源代码在Github上,建议看着代码来看这篇文章。
1四(五)层结构概念
这个就简单说一下,所谓四层架构就是Model实体层,Dao层(数据访问层也就是从数据库中查数据),Service层(业务逻辑层,也就是处理好数据),Controller层(视图控制层,在前后端分离的情况下就是写接口响应前端请求)和前端的view(视图层),为啥要搞分层咧,说到底就是要解耦合,提高拓展性和维护性,写代码的时候,思路清晰一点,后面改代码的时候也知道要改哪边。
但是我们这次只是涉及后台的,视图层我们就不用管了,只需看前面的就行了。
2分层
首先看一下项目结构哈
│app.js │package.json │README.md │ ├─.idea ││express-project.iml ││misc.xml ││modules.xml ││vcs.xml ││watcherTasks.xml ││workspace.xml ││ │└─inspectionProfiles ├─bin │www │ ├─config │db.json │ ├─dao │BaseDao.js │UserDao.js │ ├─models │user.js │ ├─public │├─images │├─javascripts │└─stylesheets │style.css │ ├─routes │index.js │users.js │ ├─services │UserService.js │ ├─utils │db-util.js │ └─views error.jade index.jade layout.jade
按照分层思想,我们新建几个文件夹哈,首先是Model层的models文件夹,dao层的dao文件夹,service层的services文件夹,controller层的话就用原来的routes文件夹就可以了,为了方便,我加了一个全局配置的config文件夹和工具函数utils文件夹。具体项目如下,我们从最底层开始来一个一个来分析
2.1config
这个就放着各种配置文件,例如我的db.json里面就放了mongodb的端口号,数据库名那些,反正就是各种配置啦
2.2utils
这个就是有一些创建型的方法或者其他公共方法,像创建数据库连接池的方法我就放在这边的db-util里面了。
2.3models
实体层,针对mongodb来说,一个集合对应一个model,然后都是这样的形式啦。
constmongoose=require('mongoose');
const{mongoClient}=require('../utils/db-util');
//创建userSchema
constuser=newmongoose.Schema({
name:String,
id:String,
},{versionKey:false});
/*model的参数1导出的模块名,
参数2创建的Schema,
参数2指定数据库中的集合的名字,若不加的,则抹默认取‘第一个参数s'的集合*/
letUser=mongoClient.model('User',user,'user');
module.exports=User;
2.4dao
创建完实体层,接下来就是dao层了,这边我封装了一个BaseDao,基本的数据库操作都有了,后面我们创建其他dao的时候就很舒服啦,直接继承一下BaseDao就好了。例如下面的这个UserDao:
letBaseDao=require('./BaseDao');
//导入对应的实体
letUser=require('../models/user');
classUserDaoextendsBaseDao{
constructor(){
super(User);
}
//如果有啥特殊需求的话,自己再重写方法咯
}
module.exports=UserDao;
这样就写好了一个基本的dao了,增删改查这些他都从BaseDao中继承了,
2.5services
service层是业务逻辑层,这么写就看你项目的业务啦。我下面就简单些一个查询所有user数据的方法啦。
constUserDao=require('../dao/UserDao');
letuserDao=newUserDao();
classUserService{
asyncgetUserList(){
try{
//调用dao层查询数据
letuserList=awaituserDao.findAll();
returnuserList;
}catch(err){
console.log(`getUserListerror-->${error}`);
returnerror;
}
}
}
module.exports=UserService;
2.6routes
controller层,写接口用,这个写起来简单,就拿一下service层的数据返回就可以啦。
varexpress=require('express');
varrouter=express.Router();
constUserService=require('../services/UserService');
letuserService=newUserService();
/*GETuserslisting.*/
router.get('/',function(req,res,next){
userService.getUserList().then((data)=>{
res.json({
code:0,
msg:'OK',
data:data
})
});
//res.send('respondwitharesource');
});
router.get('/login',(req,res,next)=>{
res.json({
code:0,
msg:'OK',
data:{result:true}
})
});
module.exports=router;
然后这边的话,我有一个想法,就是想着每次多一个路由实例(controller)的时候,就要往app.js里面导入并引入,觉得这样controller多了的时候,app.js里面代码会很多,所以就想着把模块导入的代码移到routes文件夹里面的index.js里面来,app.js就引入个index就好啦。所以就有了下面index.js的代码。
varexpress=require('express');
varrouter=express.Router();
/*GEThomepage.*/
router.get('/',function(req,res,next){
res.render('index',{title:'Express'});
});
//user路由模块
//当我在user文件里面写一个'/login'的时候,前端访问就要访问'/user/login'
router.use('/user',require('./users'));
module.exports=router;
至此,全文就结束啦,对于express框架的分层实践如果有更好的建议或者我这样分层有啥问题的话,欢迎在在下方留言哈,大家一起学习一下。也希望大家多多支持毛票票。