介绍与安装 Express 是一个基于 Node.js 平台的 web 应用开发框架,提供了一系列强大而灵活的功能,用于创建单页、多页及混合应用。它是目前最流行的 Node.js 框架之一。
安装 Express 及其生成器工具可以使用以下命令:
使用命令
1 sudo npx --package express-generator express
这将会在当前目录下创建一个新的 Express 项目。
常用依赖
在项目中,我们常常会使用 nodemon
来自动重启服务器,便于开发。可以在 package.json
文件中添加以下内容:
1 2 3 4 5 6 7 8 { "scripts" : { "dev" : "nodemon ./bin/www" } , "devDependencies" : { "nodemon" : "^2.0.7" } }
发送数据 在 Express 中,发送数据到客户端有多种方式,可以发送文本、JSON、文件等。以下是一些常用的方法及其详细说明:
res.send()
:
用于发送字符串、Buffer 或对象作为响应体。
自动设置 Content-Type
,如果发送的是对象,会设置为 application/json
。
示例:1 2 3 4 5 6 7 8 9 10 11 app.get ('/' , (req, res ) => { res.send ('Hello World!' ); }); app.get ('/buffer' , (req, res ) => { res.send (Buffer .from ('Hello Buffer!' )); }); app.get ('/object' , (req, res ) => { res.send ({ message : 'Hello, Object!' }); });
res.json()
:
用于发送 JSON 响应,自动设置 Content-Type: application/json
。
相当于 res.send()
的对象版本,但更明确。
示例:1 2 3 app.get ('/api/data' , (req, res ) => { res.json ({ message : 'Hello, JSON!' }); });
res.jsonp()
:
用于发送 JSONP 响应,可以解决跨域问题。
自动设置 Content-Type: application/javascript
,并包装 JSON 响应在一个回调函数中。
示例:1 2 3 app.get ('/api/data' , (req, res ) => { res.jsonp ({ message : 'Hello, JSONP!' }); });
res.sendFile()
:
用于发送文件作为响应体。
需要提供文件的绝对路径,通常使用 __dirname
来构建路径。
可以通过选项对象设置缓存控制等。
示例:1 2 3 4 5 6 7 app.get ('/file' , (req, res ) => { res.sendFile (__dirname + '/file.txt' ); }); app.get ('/file-options' , (req, res ) => { res.sendFile (__dirname + '/file.txt' , { cacheControl : false }); });
res.download()
:
用于提示下载文件。
需要提供文件路径和可选的下载文件名。
示例:1 2 3 4 5 6 7 app.get ('/download' , (req, res ) => { res.download (__dirname + '/file.txt' ); }); app.get ('/download-name' , (req, res ) => { res.download (__dirname + '/file.txt' , 'custom_name.txt' ); });
res.redirect()
:
用于重定向请求到另一个 URL。
可以传递 URL 或者状态码和 URL。
示例:1 2 3 4 5 6 7 app.get ('/google' , (req, res ) => { res.redirect ('https://www.google.com' ); }); app.get ('/redirect-301' , (req, res ) => { res.redirect (301 , 'https://www.google.com' ); });
res.render()
:
用于渲染视图模板,并将生成的 HTML 发送给客户端。
需要配置模板引擎。
示例(假设使用 Pug 模板引擎):1 2 3 4 5 app.set ('view engine' , 'pug' ); app.get ('/template' , (req, res ) => { res.render ('index' , { title : 'Hey' , message : 'Hello there!' }); });
res.end()
:
结束响应处理流程,通常用于流数据或手动发送响应头后。
示例:1 2 3 4 app.get ('/end' , (req, res ) => { res.write ('Part of the response' ); res.end ('The end of the response' ); });
使用这些方法,您可以灵活地处理和发送不同类型的响应数据,满足各种应用需求。
路由 路由是应用程序的基本组成部分,负责定义应用程序的各个端点(URI)以及如何响应客户端请求。
路由就相当于一个小应用,所以它请求的方法和app
是一样的。
定义 需要注意的是路由是从上而下叠加的,所以静态路由一般要注意放在动态路由上面
1 2 3 4 5 6 7 8 9 var express = require ('express' );var router = express.Router ();router.get ('/' , function (req, res, next ) { res.send ('respond with a resource' ); }); module .exports = router;
使用 在主应用中使用定义的路由模块:
1 2 3 4 5 6 7 8 9 var express = require ('express' );var app = express ();var usersRouter = require ('./routes/users' );app.use ('/users' , usersRouter); app.listen (3000 , function ( ) { console .log ('Server is running on port 3000' ); });
路由方法 Express 提供多种路由方法,分别对应于 HTTP 的各种请求方法:get
、post
、put
、delete
等。例如:
1 2 3 4 5 6 7 8 9 10 11 router.post ('/' , function (req, res ) { res.send ('Got a POST request' ); }); router.put ('/user' , function (req, res ) { res.send ('Got a PUT request at /user' ); }); router.delete ('/user' , function (req, res ) { res.send ('Got a DELETE request at /user' ); });
同时express提供了route
用于更方便的在同一个路径下面,调用不同的路由方法,同时function
也可以使用箭头函数来简化=>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 router .route ("/" ) .get ((req, res ) => { res.send ('Got a GET request' ); }) .post ((req, res ) => { res.send ('Got a POST request' ); }) .put ((req, res ) => { res.send ('Got a PUT request' ); }) .delete ((req, res ) => { res.send ('Got a DELETE request' ); });
路由参数 你可以在路由中使用参数,通过 req.params
获取:
1 2 3 router.get ('/user/:id' , function (req, res ) { res.send ('user id: ' + req.params .id ); });
中间件 详细请见下面的主标题的内容
路由分组 你可以将相关的路由放在同一个路由器实例中:
1 2 3 4 5 6 7 8 9 10 11 12 var express = require ('express' );var router = express.Router ();router.get ('/about' , function (req, res ) { res.send ('About Page' ); }); router.get ('/contact' , function (req, res ) { res.send ('Contact Page' ); }); module .exports = router;
在主应用中引入:
1 2 3 4 5 6 7 8 9 var express = require ('express' );var app = express ();var mainRouter = require ('./routes/main' );app.use ('/' , mainRouter); app.listen (3000 , function ( ) { console .log ('Server is running on port 3000' ); });
错误处理 在路由中处理错误的方法:
1 2 3 4 router.use (function (err, req, res, next ) { console .error (err.stack ); res.status (500 ).send ('Something broke!' ); });
以上是关于 Express 路由的详细笔记,涵盖了定义、使用、方法、参数、中间件、分组和错误处理等方面。
中间件 中间件是 Express 应用程序中一个重要的概念,用于处理请求、响应以及应用程序之间的一系列操作。
应用级中间件:
1 2 3 4 app.use ((req, res, next ) => { console .log ('Time:' , Date .now ()); next (); });
路由级中间件:
1 2 3 4 5 6 7 8 const router = express.Router ();router.use ((req, res, next ) => { console .log ('Request URL:' , req.originalUrl ); next (); }); app.use ('/api' , router);
错误处理中间件:
1 2 3 4 app.use ((err, req, res, next ) => { console .error (err.stack ); res.status (500 ).send ('Something broke!' ); });
第三方中间件(如 body-parser
用于解析请求体):
1 2 const bodyParser = require ('body-parser' );app.use (bodyParser.json ());
中间件位于发送到服务器的请求(app.get)和返回给用户的实际响应之间
同时中间件是否执行也取决于位于代码的位置,如果有请求代码位于中间件之前的话,该中间件则不会影响该请求代码
路由中间件是一种执行前后处理操作的方法。使用 next
参数可以传递控制权:
router.param
就是一个中间件函数,在我发送请求之前就运行,如果我不使用next()
的话将不会执行发送请求的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 router.use (function (req, res, next ) { console .log ('Time:' , Date .now ()); next (); }); router.get ('/' , function (req, res, next ) { res.send ('Home Page' ); }); router.param ("id" , (req, res, next, id ) => { console .log (id); next (); }); app.get ("/" , logger, (req, res ) => { res.render ("index" , { text : "world" }); }); const userRouter = require ("./routes/users" );app.use ("/users" , userRouter); function logger (req, res, next ) { console .log (req.originalUrl ); next (); }
两种方式使用中间件的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 app.use (logger) app.get ("/" , (req, res ) => { res.render ("index" , { text : "world" }); }); function logger (req, res, next ) { console .log (req.originalUrl ); next (); } app.get ("/" , logger, (req, res ) => { res.render ("index" , { text : "world" }); }); function logger (req, res, next ) { console .log (req.originalUrl ); next (); }
解析表单/JSON数据 在 Express 应用中,解析表单和 JSON 数据是处理客户端请求的关键步骤。Express 提供了中间件来处理这些数据。
解析 URL 编码的表单数据 为了解析传统的表单数据,你可以使用 express.urlencoded
中间件。它会解析 application/x-www-form-urlencoded
编码的数据,这是标准的 HTML 表单提交的格式。
使用 express.urlencoded
直接使用req.body
的话,是无法获取的,因为express不允许访问bode的内容,所以我们需要借助中间件
注意这个{ extended: true }
不放的话,会有warning
1 2 3 4 5 6 7 8 9 10 11 12 13 var express = require ('express' );var app = express ();app.use (express.urlencoded ({ extended : true })); app.post ('/submit-form' , function (req, res ) { console .log (req.body ); res.send ('Form data received' ); }); app.listen (3000 , function ( ) { console .log ('Server is running on port 3000' ); });
参数说明
extended: true
:使用 qs
库解析 URL 编码数据,支持丰富的对象和数组结构。
extended: false
:使用 querystring
库解析 URL 编码数据,只支持简单的键值对。
解析 JSON 数据 为了解析 JSON 数据,你可以使用 express.json
中间件。它会解析 application/json
类型的数据,这在使用 API 时非常常见。
使用 express.json
1 2 3 4 5 6 7 8 9 10 11 12 13 var express = require ('express' );var app = express ();app.use (express.json ()); app.post ('/submit-json' , function (req, res ) { console .log (req.body ); res.send ('JSON data received' ); }); app.listen (3000 , function ( ) { console .log ('Server is running on port 3000' ); });
处理文件上传 如果需要处理文件上传,可以使用 multer
中间件。multer
是一个处理 multipart/form-data
的中间件,通常用于上传文件。
安装 multer
使用 multer
1 2 3 4 5 6 7 8 9 10 11 12 13 var express = require ('express' );var multer = require ('multer' );var upload = multer ({ dest : 'uploads/' });var app = express ();app.post ('/upload' , upload.single ('file' ), function (req, res ) { console .log (req.file ); res.send ('File uploaded successfully' ); }); app.listen (3000 , function ( ) { console .log ('Server is running on port 3000' ); });
参数说明
dest
:指定文件上传后的保存路径。
upload.single('file')
:处理单个文件上传,file
是表单中 <input type="file" name="file">
的 name
属性。
中间件顺序 确保解析中间件的顺序正确,应该在定义路由之前使用中间件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 app.use (express.urlencoded ({ extended : true })); app.use (express.json ()); app.use ('/upload' , upload.single ('file' )); app.post ('/submit-form' , function (req, res ) { }); app.post ('/submit-json' , function (req, res ) { }); app.post ('/upload' , function (req, res ) { });
错误处理 处理解析过程中可能出现的错误:
1 2 3 4 app.use (function (err, req, res, next ) { console .error (err.stack ); res.status (500 ).send ('Something went wrong!' ); });
以上是关于解析表单和 JSON 数据的详细笔记,包括了解析 URL 编码的表单数据、解析 JSON 数据、处理文件上传、确保中间件顺序以及错误处理等方面。
框架代码解析 目录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 myapp ├── app.js ├── package.json ├── bin │ └── www ├── public │ ├── images │ ├── javascripts │ └── stylesheets │ └── style.css ├── routes │ ├── index.js │ └── users.js ├── views │ ├── error.jade │ ├── index.jade │ └── layout.jade └── node_modules
index.js 这个render
是专门用于渲染html的,然后后面这个{ title: 'Express' }
实际上可以传任意对象,它的作用主要是把这个值传递给index.jade
1 2 3 4 5 6 7 8 9 var express = require ('express' );var router = express.Router ();router.get ('/' , function (req, res, next ) { res.render ('index' , { title : 'Express' }); }); module .exports = router;
index.jade
1 2 3 4 5 extends layout block content h1= title p Welcome to #{title}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #!/usr/bin/env node var app = require ('../app' ); var debug = require ('debug' )('ardemobackend:server' ); var http = require ('http' ); var port = normalizePort (process.env .PORT || '3000' ); app.set ('port' , port); var server = http.createServer (app); server.listen (port); server.on ('error' , onError); server.on ('listening' , onListening); function normalizePort (val ) { var port = parseInt (val, 10 ); if (isNaN (port)) { return val; } if (port >= 0 ) { return port; } return false ; } function onError (error ) { if (error.syscall !== 'listen' ) { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; switch (error.code ) { case 'EACCES' : console .error (bind + ' requires elevated privileges' ); process.exit (1 ); break ; case 'EADDRINUSE' : console .error (bind + ' is already in use' ); process.exit (1 ); break ; default : throw error; } } function onListening ( ) { var addr = server.address (); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port ; debug ('Listening on ' + bind); }
app.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 var createError = require ('http-errors' ); var express = require ('express' ); var path = require ('path' ); var cookieParser = require ('cookie-parser' ); var logger = require ('morgan' ); var indexRouter = require ('./routes/index' ); var usersRouter = require ('./routes/users' ); var app = express (); app.set ('views' , path.join (__dirname, 'views' )); app.set ('view engine' , 'jade' ); app.use (logger ('dev' )); app.use (express.json ()); app.use (express.urlencoded ({ extended : false })); app.use (cookieParser ()); app.use (express.static (path.join (__dirname, 'public' ))); app.use ('/' , indexRouter); app.use ('/users' , usersRouter); app.use (function (req, res, next ) { next (createError (404 )); }); app.use (function (err, req, res, next ) { res.locals .message = err.message ; res.locals .error = req.app .get ('env' ) === 'development' ? err : {}; res.status (err.status || 500 ); res.render ('error' ); }); module .exports = app;
使用MySQL实现后端 好的,我们可以使用 Sequelize 作为 ORM 框架来实现 MySQL 后端。以下是如何使用 Sequelize 和 Express 来实现用户的增、删、改、查操作的示例。
第一步:安装必要的 npm 包 1 npm install express sequelize mysql2
第二步:设置 Sequelize 连接 在项目根目录下创建一个 config
文件夹,然后在其中创建一个 database.js
文件,用于配置 Sequelize 连接:
1 2 3 4 5 6 7 8 const { Sequelize } = require ('sequelize' );const sequelize = new Sequelize ('mydatabase' , 'root' , 'password' , { host : 'localhost' , dialect : 'mysql' , }); module .exports = sequelize;
第三步:定义用户模型 在项目根目录下创建一个 models
文件夹,然后在其中创建一个 user.js
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const { Sequelize , DataTypes } = require ('sequelize' );const sequelize = require ('../config/database' );const User = sequelize.define ('User' , { name : { type : DataTypes .STRING , allowNull : false , }, email : { type : DataTypes .STRING , allowNull : false , unique : true , }, age : { type : DataTypes .INTEGER , allowNull : false , }, createdAt : { type : DataTypes .DATE , defaultValue : Sequelize .NOW , }, }); module .exports = User ;
第四步:同步模型和数据库 在 app.js
文件中同步模型和数据库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const express = require ('express' );const sequelize = require ('./config/database' );const usersRouter = require ('./routes/users' ); const app = express ();app.use (express.json ()); sequelize.sync () .then (() => { console .log ('Database synced' ); }) .catch ((err ) => { console .error ('Error syncing database:' , err); }); app.use ('/users' , usersRouter); module .exports = app;
第五步:创建用户路由 在 routes
文件夹中创建 users.js
路由文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 const express = require ('express' );const router = express.Router ();const User = require ('../models/user' );router.get ('/' , async (req, res) => { try { const users = await User .findAll (); res.json (users); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); router.get ('/:id' , async (req, res) => { try { const user = await User .findByPk (req.params .id ); if (!user) { return res.status (404 ).json ({ message : 'User not found' }); } res.json (user); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); router.post ('/' , async (req, res) => { try { const { name, email, age } = req.body ; const newUser = await User .create ({ name, email, age }); res.status (201 ).json (newUser); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.put ('/:id' , async (req, res) => { try { const { name, email, age } = req.body ; const user = await User .findByPk (req.params .id ); if (!user) { return res.status (404 ).json ({ message : 'User not found' }); } user.name = name || user.name ; user.email = email || user.email ; user.age = age || user.age ; await user.save (); res.json (user); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.delete ('/:id' , async (req, res) => { try { const user = await User .findByPk (req.params .id ); if (!user) { return res.status (404 ).json ({ message : 'User not found' }); } await user.destroy (); res.json ({ message : 'User deleted' }); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); module .exports = router;
第六步:在 app.js
中使用用户路由 1 2 3 4 5 6 const usersRouter = require ('./routes/users' ); app.use ('/users' , usersRouter);
CRUD 操作文档 1. 创建 (Create) 在 Sequelize 中,创建一个新的记录是通过实例化模型并调用 create()
方法来完成的。
作用 :创建一个新的记录并将其保存到数据库中。
例子 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const User = require ('../models/user' );const newUser = { name : 'Jane Smith' , age : 25 , email : 'jane.smith@example.com' }; User .create (newUser) .then (savedUser => { console .log ('User saved:' , savedUser); }) .catch (err => { console .error ('Error saving user:' , err); });
2. 读取 (Read) 读取操作涉及查询数据库以检索记录。
作用 :从数据库中检索一个或多个记录。
例子 :
1 2 3 4 5 6 7 User .findAll () .then (users => { console .log ('Users found:' , users); }) .catch (err => { console .error ('Error finding users:' , err); });
1 2 3 4 5 6 7 User .findOne ({ where : { name : 'Jane Smith' } }) .then (user => { console .log ('User found:' , user); }) .catch (err => { console .error ('Error finding user:' , err); });
3. 更新 (Update) 更新操作用于修改已存在的记录。
作用 :在数据库中更新一个记录的字段。
例子 :
1 2 3 4 5 6 7 User .update ({ age : 26 }, { where : { name : 'Jane Smith' } }) .then (() => { console .log ('User updated' ); }) .catch (err => { console .error ('Error updating user:' , err); });
使用 findByPk()
和 save()
更新一个记录(需要知道记录的 ID):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 User .findByPk (userId) .then (user => { if (user) { user.age = 26 ; return user.save (); } else { console .log ('User not found' ); } }) .then (updatedUser => { console .log ('User updated:' , updatedUser); }) .catch (err => { console .error ('Error updating user:' , err); });
4. 删除 (Delete) 删除操作用于从数据库中移除记录。
作用 :删除一个或多个数据库中的记录。
例子 :
1 2 3 4 5 6 7 User .destroy ({ where : { name : 'Jane Smith' } }) .then (() => { console .log ('User deleted' ); }) .catch (err => { console .error ('Error deleting user:' , err); });
1 2 3 4 5 6 7 User .destroy ({ where : {} }) .then (() => { console .log ('All users deleted' ); }) .catch (err => { console .error ('Error deleting users:' , err); });
使用MongoDB实现后端 当然,这里是一个完整的示例,展示如何在MongoDB中使用Mongoose和Express实现用户的增、删、改、查操作。
第一步:在 app.js
中连接数据库并添加相关路由 修改 app.js
文件,添加用户路由,下面的代码为提取过的只关于连接的部分:
在这里设置MongoDB连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var mongoose = require ('mongoose' );var usersRouter = require ('./routes/users' ); var app = express ();mongoose.connect ('mongodb://localhost:27017/mydatabase' , { useNewUrlParser : true , useUnifiedTopology : true , }); const db = mongoose.connection ;db.on ('error' , console .error .bind (console , 'connection error:' )); db.once ('open' , () => { console .log ('Connected to MongoDB' ); }); module .exports = app;
当然也可以使用环境变量的方式储存配置
首先下载dotenv
然后新建.env
文件
1 DATABASE_URL=mongodb://localhost:27017/expressDemo
最后是更改app.js
中的链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var mongoose = require ('mongoose' );require ('dotenv' ).config ();var indexRouter = require ('./routes/index' );var usersRouter = require ('./routes/users' ); var app = express ();mongoose.connect (process.env .DATABASE_URL , { useNewUrlParser : true , useUnifiedTopology : true , }); const db = mongoose.connection ;db.on ('error' , console .error .bind (console , 'connection error:' )); db.once ('open' , () => { console .log ('Connected to MongoDB' ); }); module .exports = app;
第二步:定义用户模式(Schema) 在 models
文件夹中创建 User.js
模型文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const mongoose = require ('mongoose' );const UserSchema = new mongoose.Schema ({ name : { type : String , required : true , }, email : { type : String , required : true , unique : true , }, age : { type : Number , required : true , }, date : { type : Date , default : Date .now , }, }); module .exports = mongoose.model ('User' , UserSchema );
需要注意的部分是module.exports = mongoose.model('User', UserSchema);
并不是mongodb的collectionname
,正确的collectionname
逻辑如下:模型名称是 User
,所以Mongoose会自动使用集合名称 users
。这意味着 users.js
路由文件中的所有操作都对应于MongoDB数据库中的 users
集合。
第三步:创建用户路由 在 routes
文件夹中创建 users.js
路由文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 const express = require ('express' );const router = express.Router ();const User = require ('../models/User' );router.get ('/' , async (req, res) => { try { const users = await User .find (); res.json (users); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); router.get ('/:id' , getUser, (req, res ) => { res.json (res.user ); }); router.post ('/' , async (req, res) => { const user = new User ({ name : req.body .name , email : req.body .email , age : req.body .age , }); try { const newUser = await user.save (); res.status (201 ).json (newUser); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.put ('/:id' , getUser, async (req, res) => { if (req.body .name != null ) { res.user .name = req.body .name ; } if (req.body .email != null ) { res.user .email = req.body .email ; } if (req.body .age != null ) { res.user .age = req.body .age ; } try { const updatedUser = await res.user .save (); res.json (updatedUser); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.delete ('/:id' , getUser, async (req, res) => { try { await res.user .remove (); res.json ({ message : 'User deleted' }); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); async function getUser (req, res, next ) { let user; try { user = await User .findById (req.params .id ); if (user == null ) { return res.status (404 ).json ({ message : 'Cannot find user' }); } } catch (err) { return res.status (500 ).json ({ message : err.message }); } res.user = user; next (); } module .exports = router;
CRUD 操作文档 1. 创建 (Create) 在 Mongoose 中,创建一个新的文档是通过实例化模型并调用 save()
方法来完成的。
作用 :创建一个新的文档并将其保存到数据库中。
例子 :
1 2 3 4 5 6 7 8 9 10 11 12 const User = mongoose.model ('User' , userSchema);const newUser = new User ({ name : 'Jane Smith' , age : 25 , email : 'jane.smith@example.com' }); newUser.save ((err, savedUser ) => { if (err) return handleError (err); console .log ('User saved:' , savedUser); });
2. 读取 (Read) 读取操作涉及查询数据库以检索文档。
作用 :从数据库中检索一个或多个文档。
例子 :
查询所有文档:
1 2 3 4 User .find ({}, (err, users ) => { if (err) return handleError (err); console .log ('Users found:' , users); });
查询特定文档:
1 2 3 4 User .findOne ({ name : 'Jane Smith' }, (err, user ) => { if (err) return handleError (err); console .log ('User found:' , user); });
3. 更新 (Update) 更新操作用于修改已存在的文档。
作用 :在数据库中更新一个文档的字段。
例子 :
4. 删除 (Delete) 删除操作用于从数据库中移除文档。
作用 :删除一个或多个数据库中的文档。
例子 :
删除一个文档:
1 2 3 4 User .findOneAndDelete ({ name : 'Jane Smith' }, (err, user ) => { if (err) return handleError (err); console .log ('User deleted:' , user); });
删除所有文档:
1 2 3 4 User .deleteMany ({}, (err ) => { if (err) return handleError (err); console .log ('All users deleted' ); });
完成 已经实现了一个完整的用户管理API,支持增、删、改、查操作。例如:
GET /users
- 获取所有用户
GET /users/:id
- 获取特定ID的用户
POST /users
- 创建新用户
PUT /users/:id
- 更新特定ID的用户
DELETE /users/:id
- 删除特定ID的用户
基础代码: app.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 var createError = require ('http-errors' );var express = require ('express' );var path = require ('path' );var cookieParser = require ('cookie-parser' );var logger = require ('morgan' );const mysql = require ('mysql2' );require ('dotenv' ).config ();var indexRouter = require ('./routes/index' );var usersRouter = require ('./routes/users' ); var app = express ();const db = mysql.createPool ({ host : 'localhost' , port : 3306 , user : 'root' , password : '12345678' , database : 'go' }); db.getConnection ((err, connection ) => { if (err) { console .error ('Error connecting to MySQL:' , err); } else { console .log ('Connected to MySQL' ); connection.release (); } }); app.set ('views' , path.join (__dirname, 'views' )); app.set ('view engine' , 'jade' ); app.use (logger ('dev' )); app.use (express.json ()); app.use (express.urlencoded ({ extended : false })); app.use (cookieParser ()); app.use (express.static (path.join (__dirname, 'public' ))); app.use ('/' , indexRouter); app.use ('/users' , usersRouter); app.use (function (req, res, next ) { next (createError (404 )); }); app.use (function (err, req, res, next ) { res.locals .message = err.message ; res.locals .error = req.app .get ('env' ) === 'development' ? err : {}; res.status (err.status || 500 ); res.render ('error' ); }); module .exports = app;
models/index.js 1 2 3 4 5 6 7 8 9 const { Sequelize } = require ('sequelize' );const sequelize = new Sequelize ('go' , 'root' , '12345678' , { host : 'localhost' , port : 3306 , dialect : 'mysql' , }); module .exports = sequelize;
models/User.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const { Sequelize , DataTypes } = require ('sequelize' );const sequelize = require ('./index' );const User = sequelize.define ('User' , { user_id : { type : DataTypes .INTEGER , autoIncrement : true , primaryKey : true }, user_name : { type : DataTypes .STRING , allowNull : false }, user_psw : { type : DataTypes .STRING , allowNull : false }, user_email : { type : DataTypes .STRING , allowNull : false } }, { tableName : 'user' , timestamps : false }); module .exports = User ;
routes/index.js 1 2 3 4 5 6 7 8 9 10 var express = require ('express' );var router = express.Router ();router.get ('/' , function (req, res, next ) { res.render ('index' , { title : 'Express' }); }); module .exports = router;
routes/users.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 const express = require ('express' );const router = express.Router ();const User = require ('../models/User' );router.get ('/' , async (req, res) => { try { const users = await User .findAll (); res.json (users); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); router.get ('/:id' , getUser, (req, res ) => { res.json (res.user ); }); router.post ('/' , async (req, res) => { const user = new User ({ user_name : req.body .user_name , user_psw : req.body .user_psw , user_email : req.body .user_email , }); try { const newUser = await user.save (); res.status (201 ).json (newUser); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.put ('/:id' , getUser, async (req, res) => { if (req.body .user_name != null ) { res.user .user_name = req.body .user_name ; } if (req.body .user_psw != null ) { res.user .user_psw = req.body .user_psw ; } if (req.body .user_email != null ) { res.user .user_email = req.body .user_email ; } try { const updatedUser = await res.user .save (); res.json (updatedUser); } catch (err) { res.status (400 ).json ({ message : err.message }); } }); router.delete ('/:id' , getUser, async (req, res) => { try { await res.user .destroy (); res.json ({ message : 'User deleted' }); } catch (err) { res.status (500 ).json ({ message : err.message }); } }); async function getUser (req, res, next ) { let user; try { user = await User .findByPk (req.params .id ); if (user == null ) { return res.status (404 ).json ({ message : 'Cannot find user' }); } } catch (err) { return res.status (500 ).json ({ message : err.message }); } res.user = user; next (); } module .exports = router;