前言 上次咱們搭建了一個基本的 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 框架的分層實踐若是有更好的建議或者我這樣分層有啥問題的話,歡迎在在下方留言哈,你們一塊兒學習一下。