一、简介
二、创建项目(方式一:空项目手动创建)
-
新建项目文件夹
express-demo
,cd
进入文件夹后,使用命令创建package.json
文件:# 进入项目文件夹执行下面初始化命令,二选一即可,反正创建了可以后期调整的 $ cd express-demo # 方式一:需要调整初始配置 $ npm init # 方式二:直接默认初始配置不进行调整 $ npm init -y
-
安装
express
$ npm install express --save
-
创建入口文件
index.js 或 app.js
都行,package.json
中的默认入口文件叫index.js
,如果改了记得同步就行。 -
基本使用
express
const express = require('express') const app = express() app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(3000, () => { console.log("启动成功!") })
-
运行并访问 http://localhost:3000
$ node index.js
-
也可以到
package.json
的scripts
里面加个start
指令,使用指令运行,访问结果一样:-
package.json
添加指令"scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }
-
运行项目并访问 http://localhost:3000/
$ npm run start
-
三、创建项目(方式二:Express
项目生成器)
-
安装生成器
$ npm install -g express-generator
-
创建项目,会有一个初始的目录结构
$ express express-demo
-
进入项目安装依赖
$ cd express-demo $ npm i
-
运行项目并访问 http://localhost:3000/
$ npm run start
四、支持热更新
-
nodejs
本身并不直接支持热更新(Hot Reloading
),但可以通过一些工具和方法来实现热更新功能,使得代码在修改后无需重新启动服务器即可自动生效。$ npm install --save-dev nodemon
-
在项目的
package.json
中添加一个启动脚本:{ "scripts": { "dev": "nodemon app.js" } }
-
运行项目并访问 http://localhost:3000/,然后尝试修改下代码,这样就不需要每次修改后重启项目才会生效了,
只需要在开发阶段使用即可
。$ npm run dev
五、路由基础
-
路由示例
const express = require('express') const app = express() app.get('/', (req, res) => { // req: 请求对象, res:响应对象 res.send('Hello World!') })
这就是一个基本路由。在
Express
中,路由指的是客户端请求
与服务器处理函数
之间的映射关系。 -
Express
中的路由由3
部分组成,分别是请求类型
、请求地址
、处理函数
:app.METHOD(PATH, HANDLER)
例如:
app.get('/', function (req, res) { res.send('Hello World!') }) app.post('/', function (req, res) { res.send('Got a POST request') }) app.get('/user', function (req, res) { res.send('Got a GET request at /user') }) app.post('/user', function (req, res) { res.send('Got a POST request at /user') })
六、路由使用
-
最基础的用法,就是把路由挂载到
app
上const express = require('express') const app = express() app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(3000, () => { console.log("启动成功!") })
-
稍微复杂一点的就是模块化路由,为了方便对路由进行管理,不建议将路由直接挂载到
app
上,而是推荐将路由抽离为单独的模块,主要有以下几个步骤:(1)创建路由模块对应的
.js
文件(2)调用
express.Router()
创建路由对象(3)向路由对象上挂载具体的路由
(4)使用
module.exports
向外共享路由对象(5)使用
app.use()
函数注册路由模块-
示例
例如:创建一个
routes
文件夹,里面根据功能模块创建不同的.js
文件,每个文件里存放对应处理的路由。// routes/index.js var express = require('express'); var router = express.Router(); // 该模块的 默认 路由 router.get('/', function(req, res, next) { res.send('respond with a resource - /'); }); // 该模块的 /show 路由 router.get('/show', function(req, res, next) { res.send('respond with a resource - /show'); }); module.exports = router;
// routes/users.js var express = require('express'); var router = express.Router(); // 该模块的 默认 路由 router.get('/', function(req, res, next) { res.send('respond with a resource - /users'); }); // 该模块的 /show 路由 router.get('/show', function(req, res, next) { res.send('respond with a resource - /users/show'); }); module.exports = router;
// index.js const express = require('express') const app = express() // 导入模块化路由 var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); // 注册路由,可以不给路由模块添加前缀或添加更长的前缀,都是可以的 // 不添加前缀,其实默认就是 '/' app.use(indexRouter); // 模块内部路由:/ ,访问路径为 http://localhost:3000 // 模块内部路由:/show,访问路径为 http://localhost:3000/show // 添加前缀 app.use('/', indexRouter); // 模块内部路由:/ ,访问路径为 http://localhost:3000 // 模块内部路由:/show,访问路径为 http://localhost:3000/show // 添加前缀 app.use('/users', usersRouter); // 模块内部路由:/ ,访问路径为 http://localhost:3000/users // 模块内部路由:/show,访问路径为 http://localhost:3000/users/show // 添加更长的前缀 app.use('/my/users', usersRouter); // 模块内部路由:/ ,访问路径为 http://localhost:3000/my/users // 模块内部路由:/show,访问路径为 http://localhost:3000/my/users/show // 处理未匹配到的路由,返回 404 app.use((req, res) => { res.status(404).send('404 Not Found'); }); // 监听端口 app.listen(3000, () => { console.log("启动成功!") })
-
七、中间件
-
中间件(
Middleware
),指业务流程的中间处理环节。说白了就是一堆方法,接收客户端发来费请求,可以对该请求做出响应,也可以继续交给下一个中间件进行处理。主要由两部分组成:
中间件方法
、请求处理函数
。举例:中间件是需要设置注册的,没有注册就不用管。原理就是请求一个
Get 路由 /users
,在进入/users
路由之前会通过注册好的全局中间件
判断是否还要继续,如果继续也就是调用next()
,则进入注册好的app.get 中间件
继续判断,通过层层中间件判断,最后来到/users
路由中进行处理并返回数据。 -
中间件的书写顺序
中间件必须写在路由前面,写在后面就不会生效了。
-
中间件调用顺序
中间件的调用顺序不是按
先全局中间件再 app.get 中间件
这么个顺序来的,而是先注册的中间件先调用(即按代码中定义的顺序执行)
,上面只是举例。 -
对特定
url
使用中间件(局部中间件)//【app.get 中间件】只会处理 get 请求过来的 /users 路由 app.get('/users', (req, res, next) => { console.log("进入中间件!") // 向下执行 next() }) //【app.use 中间件】会处理所有请求方法(如 GET、POST、PUT 等)请求过来的 /users 路由 // app.use('/users', (req, res, next) => { // console.log("进入中间件!") // // 向下执行 // next() // }) //【路由】 app.get('/users', (req, res)=> { res.send("Hello World!") })
还可以这么写:
//【路由】与【app.get 中间件】结合 app.get('/users', (req, res, next) => { console.log("进入中间件!") // 向下执行 next() }, (req, res)=> { res.send("Hello World!") })
还可以这么写:
// 手动实现【app.get 中间件】 app.use((req, res, next) => { if (req.method === 'GET') { console.log('GET Request') // 继续处理 GET 请求 next() } else { res.status(405).send('Method Not Allowed') // 如果不是 GET 请求,返回 405 错误 } }) // 路由 app.get('/users', (req, res)=> { res.send("Hello World!") })
-
使用
app.use
设置全局生效的中间件// 接收所有的请求的中间件(全局生效) app.use((req, res, next) => { console.log('请求进入 app.use 中间件!') next() }) // 当客户端访问 /users 请求的时候走当前中间件 app.use('/users', (req, res, next) => { console.log('请求进入 app.use /users 中间件!') next() }) app.get('/users', (req, res)=> { res.send("Hello World!"); })
-
中间件执行顺序与规则
访问 http://localhost:3000/users 只会走
/users
的中间件。访问 http://localhost:3000/users/show 则会走
/users
与/users/show
两个中间件,且从上到下先注册先走。// 导入模块化路由 var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); // 给 /users 路径添加一个中间件 app.use('/users', (req, res, next) => { console.log('进入 /users 路径的中间件') // 继续执行后续的中间件或路由 next() }) // 给 /users/show 路径添加一个中间件 app.use('/users/show', (req, res, next) => { console.log('进入 /users/show 路径的中间件') // 继续执行后续的中间件或路由 next() }) // 注册路由 app.use('/', indexRouter); app.use('/users', usersRouter);
八、静态页面返回(404 页面等)
-
首先创建一个静态文件夹,用于存放网站静态资源(如
HTML
、CSS
、JS
文件)。比如可以创建一个public
文件夹,这个文件夹名没固定要求。/project-directory /public /index.html /style.css /script.js /404.html /app.js
-
然后进行配置使用
const express = require('express') const path = require('path') const app = express() // 设置静态页面,默认就是 '/' 路由 app.use(express.static(path.join(__dirname, 'public'))); // 设置一个路由,访问结果一样的 app.use('/static', express.static(path.join(__dirname, 'public'))); // 如果 public 文件夹内有其他静态文件,比如 style.css 和 script.js,也可以通过 URL 访问它们,例如: // http://localhost:3000/style.css // http://localhost:3000/script.js // 处理未匹配到的路由,返回 404 页面 app.use((req, res) => { // res.status(404).send('404 Not Found') res.status(404).sendFile(path.join(__dirname, 'public/404.html')) }) // 监听端口 app.listen(3000, () => { console.log("启动成功!") })
八、动态页面返回
- 动态页面
Express
提供了与多种模板引擎的集成支持,如EJS
、Pug(之前称为 Jade)
、Handlebars
等,自行了解吧,感觉用处不大,也可以选择其他框架的SSR
开发。
十、PM2
挂载
十一、数据库链接使用
-
数据库本地自行安装好环境。
-
MongoDB (NoSQL)
$ npm install mongoose
const mongoose = require('mongoose'); // 连接到 MongoDB 数据库 mongoose.connect('mongodb://localhost:27017/testDB', { useNewUrlParser: true, useUnifiedTopology: true }); // 定义一个 Schema const userSchema = new mongoose.Schema({ name: String, age: Number }); // 创建一个模型 const User = mongoose.model('User', userSchema); // 插入数据 const newUser = new User({ name: 'Alice', age: 30 }); newUser.save() .then(() => console.log('User saved')) .catch(err => console.error('Error saving user:', err));
-
MySQL / MariaDB
如果使用的是
MariaDB
,你也可以使用同样的库,因为MySQL2
兼容MariaDB
。$ npm install mysql2
const mysql = require('mysql2'); // 创建连接 const connection = mysql.createConnection({ host: 'localhost', user: 'root', database: 'test' }); // 查询数据 connection.query('SELECT * FROM users', (err, results, fields) => { if (err) { console.error(err); } else { console.log(results); } }); // 插入数据 connection.query( 'INSERT INTO users (name, age) VALUES (?, ?)', ['Alice', 30], (err, results) => { if (err) { console.error(err); } else { console.log('Inserted row:', results.insertId); } } ); // 关闭连接 connection.end();
-
SQLite
$ npm install sqlite3
const sqlite3 = require('sqlite3').verbose(); // 打开或创建数据库 let db = new sqlite3.Database('./test.db'); // 创建一个表 db.run("CREATE TABLE IF NOT EXISTS users (id INT, name TEXT, age INT)"); // 插入数据 let stmt = db.prepare("INSERT INTO users VALUES (?, ?, ?)"); stmt.run(1, 'Alice', 30); stmt.finalize(); // 查询数据 db.each("SELECT * FROM users", (err, row) => { console.log(row.id + ": " + row.name + " - " + row.age); }); // 关闭数据库 db.close();