express 项目分层实践详解


Posted in Javascript onDecember 10, 2018

前言

上次我们搭建了一个基本的 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.1 config

这个就放着各种配置文件,例如我的 db.json 里面就放了mongodb 的端口号,数据库名那些,反正就是各种配置啦

2.2 utils

这个就是有一些创建型的方法或者其他公共方法,像创建数据库连接池的方法我就放在这边的 db-util 里面了。

2.3 models

实体层,针对 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;

2.4 dao

创建完实体层,接下来就是 dao 层了,这边我封装了一个 BaseDao,基本的数据库操作都有了,后面我们创建其他 dao 的时候就很舒服啦,直接继承一下 BaseDao 就好了。例如下面的这个 UserDao:

let BaseDao = require('./BaseDao');
// 导入对应的实体
let User = require('../models/user');

class UserDao extends BaseDao{
 constructor() {
 super(User);
 }
 //如果有啥特殊需求的话,自己再重写方法咯
}

module.exports = UserDao;

这样就写好了一个基本的 dao 了,增删改查这些他都从 BaseDao 中继承了,

2.5 services

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;

2.6 routes

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 框架的分层实践如果有更好的建议或者我这样分层有啥问题的话,欢迎在在下方留言哈,大家一起学习一下。也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在一个form用一个SUBMIT(或button)分别提交到两个处理表单页面的代码
Feb 15 Javascript
js最简单的拖拽效果实现代码
Sep 24 Javascript
基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
Sep 02 Javascript
放弃用你的InnerHTML来输出HTML吧 jQuery Tmpl不详细讲解
Apr 20 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
50 个 jQuery 插件可将你的网站带到另外一个高度
Apr 26 Javascript
Angularjs 与 bower安装和使用详解
May 11 Javascript
vue 打包后的文件部署到express服务器上的方法
Aug 09 Javascript
基于VUE移动音乐WEBAPP跨域请求失败的解决方法
Jan 16 Javascript
浅谈JS对象添加getter与setter的5种方法
Jun 09 Javascript
vue数据初始化initState的实例详解
Apr 11 Javascript
解决Vue动态加载本地图片问题
Oct 09 Javascript
JS选取DOM元素常见操作方法实例分析
Dec 10 #Javascript
微信小程序分享海报生成的实现方法
Dec 10 #Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
Dec 10 #jQuery
详解Angular Forms中自定义ngModel绑定值的方式
Dec 10 #Javascript
jQuery+css last-child实现选择最后一个子元素操作示例
Dec 10 #jQuery
微信小程序与后台PHP交互的方法实例分析
Dec 10 #Javascript
引入外部js脚本加载慢与页面白屏问题的解决
Dec 10 #Javascript
You might like
ASP知识讲座四
2006/10/09 PHP
用PHP实现弹出消息提示框的两种方法
2013/12/17 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
2016/03/21 PHP
php实现留言板功能(会话控制)
2017/05/23 PHP
php解决约瑟夫环算法实例分析
2019/09/30 PHP
利用js获取服务器时间的两个简单方法
2010/01/08 Javascript
jQuery创建插件的代码分析
2011/04/14 Javascript
网页中返回顶部代码(多种方法)另附注释说明
2013/04/24 Javascript
js修改input的type属性问题探讨
2013/10/12 Javascript
JS根据key值获取URL中的参数值及把URL的参数转换成json对象
2015/08/26 Javascript
JavaScript文本框脚本编写的注意事项
2016/01/25 Javascript
BootStrap的Datepicker控件使用心得分享
2016/05/25 Javascript
jQuery移动端图片上传组件
2016/06/12 Javascript
微信小程序 ecshop地址三级联动实现实例代码
2017/02/28 Javascript
微信小程序scroll-view实现横向滚动和上拉加载示例
2017/03/06 Javascript
Angular2仿照微信UI实现9张图片上传和预览的示例代码
2017/10/19 Javascript
ES6解构赋值的功能与用途实例分析
2017/10/31 Javascript
zTree树形菜单交互选项卡效果的实现方法
2017/12/25 Javascript
vue this.reload 方法 配置
2018/09/12 Javascript
javascript json字符串到json对象转义问题
2019/01/22 Javascript
Vuejs通过拖动改变元素宽度实现自适应
2020/09/02 Javascript
在vue中实现某一些路由页面隐藏导航栏的功能操作
2020/09/21 Javascript
分享8个JavaScript库可更好地处理本地存储
2020/10/12 Javascript
python集合用法实例分析
2015/05/30 Python
通过实例简单了解Python sys.argv[]使用方法
2020/08/04 Python
python中实现栈的三种方法
2020/12/19 Python
香港艺人陈冠希创办的潮流品牌:JUICESTORE
2021/03/04 全球购物
SQL Server数据库笔试题和答案
2016/02/04 面试题
销售总监岗位职责
2014/01/04 职场文书
春节联欢晚会主持词
2014/03/24 职场文书
2015年保洁工作总结范文
2015/04/28 职场文书
祝酒词范文
2015/08/12 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
草系十大最强宝可梦,纸片人上榜,榜首大家最熟悉
2022/03/18 日漫
Python语法学习之进程的创建与常用方法详解
2022/04/08 Python
Vue深入理解插槽slot的使用
2022/08/05 Vue.js