express项目的目录结构

express项目的目录结构


提纲
1、用express命令或者express -e命令生成项目后,产生的默认目录结构
2、自己添加的代码目录


用node建立一个express的后端项目,一般使用express-generator生成项目后,会自动产生一个目录结构,但是这个自动生成的目录结构还需要增加一些内容,主要是后端代码的分类目录。具体情况记录如下。

1、用express命令或者express -e命令生成项目后,产生的默认目录结构

接下来介绍一下这些目录的作用。

1.1 bin目录

该目录下存放的是一些配置文件如:项目启动的端口号等

1.2 public目录

存放的是一些公共的样式。这里可能有些人会有疑问,这里面为什么会用到样式呢?我这是用Node做后端的呀,对!理解的没错。
但是,有时候我们可能会使用到服务端渲染,所以,这里才会有样式的存在。

1.3 routes目录
顾名思义:routes下面的是所有的路由配置(也就是,通常后端口中所说的接口)。

路由文件如下:

var express = require('express');
var router = express.Router();
var usersController = require('../controller/users');
/* GET users listing. */
router.get('/getList', usersController.list);
router.get('/login', usersController.login);
router.post('/register', usersController.register);
router.get('/delete', usersController.deleteUser);
router.post('/update', usersController.updateUser);
module.exports = router;

router.get():即前端用get的方法请求接口
router.post():即前端用post的方法请求接口
请求某个接口之后会调用一个对应的函数去处理相对应的业务逻辑,拿上述代码的router.get('/getList', usersController.list)来说,当前端请求该接口之后会去调用usersController.list这个方法,看一下userController.list这个方法吧

const list = async (req, res) => {
	const { pageSize = 5, pageNum = 1 } = req.query;
	const offset = parseInt(pageSize) * (pageNum - 1);
	const limit = parseInt(pageSize);
	const users = await usersModel.findAndCountAll({ offset, limit });
	const data = {
		success: true,
		data: users
	}
	res.send(data)
}

该函数的两个参数分别是request和response分别是请求对象和响应对象。上面的代码res.send(data)即是将从数据库中查询的数据以json的形式返回给前端。关于findAndCountAll是sequelize提供的。这是一组封装好的ORM为了方便的查询数据库,读者可自行google查询用法

1.4 views目录
该目录是服务端渲染的html或jade文件的存放位置,不过需要在app.js中来指定该目录。
app.set('views', path.join(__dirname, 'views'));

1.5 app.js
该文件是项目的根文件包括一些路由的引用配置,统一的错误处理等。


2、自己添加的代码目录

代码目录结构按照MVC模式进行创建,因为public、views、app.js、package.json等文件已经有了,所以,只需要新增controller、model文件夹,结构如下:

- controller 控制层 -新增
- views 视图层 - 默认
- model 模型层(用于管理MongoDB文档对象)- 新增
- public 静态资源目录 - 默认
- app.js 入口文件 - 默认
- package.json 依赖管理文件 - 默认

上面的目录结构需要有一点说明,public是静态资源目录,这里有个疑问,后端项目为什么需要静态资源文件呢?view是视图层,后端项目为啥还要视图层呢?

入口文件
app.js 为入口文件,代码如下:

let express = require('express')
let crl = require('./controller')
let app = express()

//配置静态资源目录
app.use(express.static('./public'))
//配置模板所在目录
app.set('views','./views')
//配置ejs模板引擎
app.set('view engine','ejs')

//配置路由
app.get('/add',crl.getAdd)
app.post('/add',crl.postAdd)

app.listen(3000)

控制层
/controller/index.js 为控制层,文件代码如下:

//添加功能,get请求
function getAdd(req,res){
    //接收get请求参数
    let {name} = req.query
    res.render('index',{msg: name})
}

//添加功能,post请求
function postAdd(req,res){
    //接收post请求参数
    let {name} = req.body
    res.render('index',{msg: name})
}

module.exports = {
    getAdd,
    postAdd
}

视图层
/views/index.ejs 为视图层,文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div><%=msg %></div>
    <h1>这是视图层</h1>
</body>
</html>

模型层model

model是MVC分层中的M层,主要是用来建立对照模型,即使用代码模型与数据库中数据表的字段一一对应。

那怎么做呢?其实前面已经提到过了就是使用sequelize

// 安装sequelize
npm install sequelize
// 在项目根目录下建立model文件夹,并建立users.js文件

var Sequelize = require('sequelize');
var sequelize = new Sequelize(
	'user_info',   // 数据库名
	'limingyang',  // 用户名
	'limingyang',  // 密码
	{
		dialect: 'mysql',  // 数据库类型
		host: 'mysql56.rdsmscdhekdxy4f.rds.bj.baidubce.com',   // 数据库地址,本人用的是百度云的数据库
		port: '3306'  // 端口号
	}
)

// 定义表的模型(对应数据库中users数据表)
var Users = sequelize.define('users',
      {
	id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
	user_name: {
		type: Sequelize.STRING(50)
	},
	user_pass: {
		type: Sequelize.STRING(50)
	},
      }, 
      {
	freezeTableName: true,
	timestamps: false   // 是否自定生成并查询时间戳
      }
      );
Users.sync();
module.exports = Users;

定义表的模型时候需要注意的是如果你的表中没有createAt或者updateAt字段的时候 需要设置timestamps: false,否则在请求数据的时候会报错。

Controller中使用model中的代码:
controller是MVC分层的C层主要用来处理业务逻辑,即数据库的查询等相应的逻辑操作放在controller层中去完成。上面已经说过controller的简单使用,接下来主要阐述一些细节的东西。
我们在做一些业务逻辑处理的时候经常会操作到数据库,接下来说一下sequelize的用法,举一个简单的例子

const list = async (req, res, next) => {
	const { pageSize = 5, pageNum = 1 } = req.query;
	const offset = parseInt(pageSize) * (pageNum - 1);
	const limit = parseInt(pageSize);
	const users = await usersModel.findAndCountAll({ offset, limit });
	const data = {
		success: true,
		data: users
	}
	res.send(data)
}

该list函数是一个简单的分页查询功能。值得一说的是await usersModel.findAndCountAll({ offset, limit });
当使用usersModel.findAndCountAll({ offset, limit })去操作数据库的时候返回的是promise对象,这样就可以使用async await语法来拿到请求回来的数据并返回到前端了。

配置项目启动
在 package.json 文件中添加如下配置:

{
  "scripts": {
    "start": "node app.js"
  }
}

配置完成后执行 npm start 命令启动项目,在浏览器地址栏访问 http://localhost:3000/add?name=xxx ,即可执行添加的路由




参考资料:

1、express框架快速入门教程,https://blog.csdn.net/qq_26087315/article/details/113783288?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-1.no_search_link&spm=1001.2101.3001.4242

2、Express框架的使用教程,这篇文章中有很重要的内容,https://blog.csdn.net/qq_37506861/article/details/85008834?utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link





posted @   zhangzl419  阅读(4491)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示