前言 上次咱们搭建了一个基本的 express 后台,可是这样的项目结构的可扩展性,维护性和代码复用性都不是很好,参照以前学习 JavaWeb 时候的四层架构设计,用分层的思想来对 express 进行一点小优化,进一步提升代码的可拓展性。本文的源代码在 Github 上,建议看着代码来看这篇文章。javascript
这个就简单说一下,所谓四层架构就是 Model实体层,Dao层(数据访问层也就是从数据库中查数据),Service层(业务逻辑层,也就是处理好数据),Controller层(视图控制层,在先后端分离的状况下就是写接口响应前端请求)和前端的 view(视图层),为啥要搞分层咧,说到底就是要解耦合,提升拓展性和维护性,写代码的时候,思路清晰一点,后面改代码的时候也知道要改哪边。css
可是咱们此次只是涉及后台的,视图层咱们就不用管了,只需看前面的就好了。前端
首先看一下项目结构哈java
│ 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
文件夹。具体项目以下,咱们从最底层开始来一个一个来分析git
这个就放着各类配置文件,例如个人 db.json
里面就放了mongodb 的端口号,数据库名那些,反正就是各类配置啦github
这个就是有一些建立型的方法或者其余公共方法,像建立数据库链接池的方法我就放在这边的 db-util
里面了。mongodb
实体层,针对 mongodb 来讲,一个集合对应一个 model,而后都是这样的形式啦。数据库
const mongoose = require('mongoose'); const { mongoClient } = require('../utils/db-util'); // 建立 user Schema const user = new mongoose.Schema({ name: String, id: String, },{versionKey: false}); /*model 的参数1 导出的模块名, 参数2 建立的 Schema, 参数2 指定数据库中的集合的名字,若不加的,则抹默认取‘第一个参数s’的集合*/ let User = mongoClient.model('User', user, 'user'); module.exports = User;
建立完实体层,接下来就是 dao 层了,这边我封装了一个 BaseDao,基本的数据库操做都有了,后面咱们建立其余 dao 的时候就很舒服啦,直接继承一下 BaseDao 就行了。例以下面的这个 UserDao:express
let BaseDao = require('./BaseDao'); // 导入对应的实体 let User = require('../models/user'); class UserDao extends BaseDao{ constructor() { super(User); } //若是有啥特殊需求的话,本身再重写方法咯 } module.exports = UserDao;
这样就写好了一个基本的 dao 了,增删改查这些他都从 BaseDao 中继承了,json
service 层是业务逻辑层,这么写就看你项目的业务啦。我下面就简单些一个查询全部 user 数据的方法啦。
const UserDao = require('../dao/UserDao'); let userDao = new UserDao(); class UserService { async getUserList() { try { // 调用 dao 层查询数据 let userList = await userDao.findAll(); return userList; } catch (err) { console.log(`getUserList error--> ${error}`); return error; } } } module.exports = UserService;
controller 层,写接口用,这个写起来简单,就拿一下 service 层的数据返回就能够啦。
var express = require('express'); var router = express.Router(); const UserService = require('../services/UserService'); let userService = new UserService(); /* GET users listing. */ router.get('/', function(req, res, next) { userService.getUserList().then((data)=>{ res.json({ code:0, msg:'OK', data:data }) }); // res.send('respond with a resource'); }); 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
的代码。
var express = require('express'); var router = express.Router(); /* GET home page. */ 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 框架的分层实践若是有更好的建议或者我这样分层有啥问题的话,欢迎在在下方留言哈,你们一块儿学习一下。