Nodejs+express后端学习笔记(1)
1 Node.js安装
1、下载安装包:进入官网(https://nodejs.org/en),下载左侧的稳定版。
2、选择安装位置,不用勾选自动安装必要工具。
其他都默认Next。
配置环境,具体参考本文章:
https://blog.csdn.net/WHF__/article/details/129362462
2 Node.js使用
nodejs用来开发Web服务器(后端)。本文使用Visual Studio Code进行编写和调试。
2.1 REPL环境使用
命令行状态下输入:node
,就可以进入。
可以进行简单的函数编写和计算。
1、输入函数:
> function add(a,b){
return a+b;
}
> add(1,2)
会输出3。
2、输入调试:
console.log("hello")
2.2 基本知识、程序运行方法
1、JS文件的执行方式:js单线程执行,有异步任务,同步任务。
2、模块、包与commonjs规范:
- 内置(Nodejs自带)
- 第三方模块(安装在node-modules文件夹中)
-
- npm
-
- npm install 模块名 --save
-
- npm uninstall 模块名
- 自定义(项目里独立的js文件,根据commonjs规范定义)
3、运行js代码:node ****.js
。
2.3 第一个js文件
1、console
新建一个文件夹,在文件夹内新建helloworld.js
文件,文件内容如下:
//helloworld.js
console.log("hello, world!");
运行代码,在终端控制台输入:node helloworld.js
,程序将会反馈出hello, world!
。
2、function函数定义和调用
代码如下:
console.log("hello, world!");
function add(a,b){
return a+b;
}
console.log(add(1,2));
控制台输入输出:
PS G:\Visual Studio\Nodejs_Project\nodejs_test> node .\helloworld.js
hello, world!
3
2.4 外部js文件导入
如果要使helloworld.js
文件能够引用其他js文件,需要使用require
函数。
1、在同级文件夹下新建utils.js
文件,文件内容如下:
function add(a,b){
return a+b;
}
function about(){
return "服务器";
}
const name = "utils"
module.exports = {
add,
about,
msg:"你好",
name,
}
文件内能够定义变量、函数,并通过module.exports引出,以便其他文件调用。
2、文件引入:
在helloworld.js
文件中,使用require函数引入utils.js
文件,然后调用文件内的参数,具体代码如下:
const util = require('./utils.js');
console.log("hello, world!");
console.log(util);
console.log(util.add(1,2));
console.log(util.about());
console.log(util.msg);
console.log(util.name);
3、代码运行:
PS G:\Visual Studio\Nodejs_Project\nodejs_test> node .\helloworld.js
hello, world!
{
add: [Function: add],
about: [Function: about],
msg: ‘你好’,
name: ‘utils’
}
3
服务器
你好
utils
2.5 export导出方法
1、导出对象
module.exports = {
add,
about,
msg,
...
}
2、导出值/属性
module.exports.add = add;
module.exports.about = about;
module.exports.msg = msg;
...
3、导出
export.add = add;
export about = about;
...
2.6 fs库使用、同步异步
1、fs库使用:如果要使用fs,管理文件系统。
直接const fs = require('fs')
。
有同步和异步的读取方法,两者都会按照顺序执行程序,但同步方法必须阻塞程序,等到数据读取出来,再继续执行。而异步方法则不会阻塞住程序,而是另外开一个回调函数(类似于中断处理函数),先执行下方代码,等到数据读取出来,再调用回调函数。因此,同步和异步的数据的呈现顺序会出现差异。代码如下:
const fs = require('fs'); // 文件系统模块
console.log("-------------------------------")
// 异步读取,函数运行和读取到值的时间不同,读取到值之后,再调用function
console.log("a1");
fs.readFile("./text1.txt", "utf-8", function(error, res) {
if(error){
console.log(error);
return;
}
console.log(res);
});
console.log("b1");
console.log("c1");
// 同步读取文件,读取到文件之间把值给data
console.log("-------------------------------")
console.log("a2");
const data = fs.readFileSync("./text2.txt", "utf-8");
console.log(data);
console.log("b2");
console.log("c2");
代码运行如下,可以发现异步读取的函数输出结果不是按照顺序来的,但这种方法对于网络请求来说非常重要,能够避免因为网络速度较慢造成程序长时间阻塞。
-------------------------------
a1
b1
c1
-------------------------------
a2
text2
b2
c2
text1
2、异步方法也可以使用这种方式:相当于设置一个回调函数,等文件读取完成后调用回调函数。
function readFileCompletedHandle(error, res) {
if(error){
console.log(error);
return;
}
console.log(res);
}
fs.readFile("./text1.txt", "utf-8", readFileCompletedHandle);
2.7 更多官方库
链接:
https://nodejs.p2hp.com/api/v19/documentation/
3 express框架
3.1 初始化工程
使用命令npm init
来创建新工程。里面的设置全部默认,设置完成后会出现一个package.json
文件。
//package.json
{
"name": "nodejs_test",
"version": "1.0.0",
"description": "",
"main": "helloworld.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
3.2 npm
进入npm官网,查找需要的第三方函数库,比如gulp、express、mqtt等。
链接:
https://npm.p2hp.com/
3.3 引入express
在项目文件夹下,输入命令:
npm add express
然后项目中就会安装各种依赖包。
3.4 http构建服务器
新建http_demo.js
文件,代码如下:
// http_demo.js
var http = require('http')
// 通过http模块,创建web应用
var app = http.createServer((req,res) => {
res.writeHead(200,{"ContentType":"text/plain"});
res.end("hello world");
});
// 通过监听端口启动
app.listen(3000,'localhost');
console.log("http://localhost:3000");
运行程序,启动服务器,终端输入:
node http_demo.js
可以看到程序输出:
http://localhost:3000
进入该网址,就可以看到:
如果想要停止服务器运行,使用Ctrl+C
组合键关闭。
3.5 express构建服务器
express对http库进行了封装。
新建app.js
文件,代码如下:
// 导入express
const express = require("express");
const app = express()
app.get('/',(req,res)=>{
res.send('Hello World Express!');
})
app.listen(3000,()=>{
console.log("Express app at: http://localhost:3000");
})
运行程序:
node app.js
得到输出:
Express app at: http://localhost:3000
进入网页:
4 express路由
4.1 get、post、put、delete四种请求
app.js
代码如下:
// 导入express
const express = require("express");
const app = express()
// get请求
app.get('/',(req,res)=>{
res.send('Get Express!');
})
// post请求
app.post('/',(req,res)=>{
res.send('Post Express!');
})
// put请求
app.put('/',(req,res)=>{
res.send('Put Express!');
})
// delete请求
app.delete('/',(req,res)=>{
res.send('delete Express!');
})
app.listen(3000,()=>{
console.log("Express app at: http://localhost:3000");
})
输入node app.js
运行服务器。
浏览器能够看到Get Express!
。
4.2 下载Postman验证
参考链接: https://blog.csdn.net/qq_37591637/article/details/88655294
输入网址:http://localhost:3000
,左侧选择get、post、put、delete请求。点击Send,在底部就可以查看服务器返回的数据。
2、发送JSON格式数据:
//app.js
// get请求
app.get('/',(req,res)=>{
res.send({"name":"小美","age":"18","message":"刚满十八岁~"}); // json格式数据
})
保存后重启服务器,刷新网页,可以看到:
postman也可以获得数据:
重启服务器比较麻烦,因此以下可以采用热部署。
4.3 热部署 nodemon
1、安装nodemon:
命令行输入:
npm install nodemon -d -g
-d
的意思是作为依赖,可以自动添加到package.json
中。
-g
的意思是全局安装。
2、在package.json
的script
中修改:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js"
},
3、使用npm start
命令来启动服务器。
修改并保存app.js内的数据:
// get请求
app.get('/',(req,res)=>{
// res.send('Get Express!');
res.send({"name":"小兰","age":"16","message":"刚满十六岁~"}); // json格式数据
})
刷新浏览器,不用重启服务器,就可以看到返回数据的变化。
注意:如果出现nodemon : 无法将“nodemon”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再 试一次。
问题的另外一个解决方法:
https://blog.csdn.net/yan_danfeng/article/details/109306687
4.4 路由模块化
将多个请求放置到其他文件。
新建router-demo.js
,将部分app.js
的代码移植到文件内,需要创建router对象,并在最后使用module.exports
导出。
var express = require("express");
// 创建router对象
var router = express.Router();
// get请求
router.get('/',(req,res)=>{
res.send({"name":"小兰","age":"16","message":"刚满十六岁~"}); // json格式数据
})
// post请求
router.post('/',(req,res)=>{
res.send('Post Express!');
})
// put请求
router.put('/',(req,res)=>{
res.send('Put Express!');
})
// delete请求
router.delete('/',(req,res)=>{
res.send('delete Express!');
})
module.exports = router;
app.js
修改为:
// 导入 express
const express = require("express");
const router = require("./router-demo");
const app = express();
// 绑定路由
app.use(router);
app.listen(3000,()=>{
console.log("Express app at: http://localhost:3000");
})
重启服务器,可以看到服务依旧可以使用。
5 express中间件
5.1 中间件的请求参数
1、 req.query:查询字符串传递参数。查询字符串时URL中?
后面的参数。
2、 req.params:包含路由定义的动态路由参数。动态路由参数是通过在路由路径中使用冒号:
定义的。
3、 req.body:包含通过请求主体传递的参数,通常用于POST、PUT和DELETE请求中发送数据。需要使用中间件(body-parser)来解析请求主体。
4、 req.headers:包含请求中的头部信息。
5.1.1 修改状态Status
如果要get先返回状态(201),可以使用:
router.get('/',(req,res)=>{
res.stauts(201).send({"name":"小兰","age":"16","message":"刚满十六岁~"}); // json格式数据
})
postman再次send以下,可以发现状态变化,从200变成201。
5.1.2 修改头部Headers
.set()
可以组装头部,.end()
表示一次响应的结束。
// get请求
router.get('/',(req,res)=>{
res.set({"aHeader":"bHeader"});
res.status(201).send({"name":"小兰","age":"16","message":"刚满十六岁~"}); // json格式数据
res.end();
})
可以发现Headers内数据变化。
5.1.3 修改路由路径
如果从http://localhost:3000/user
发送Get请求。
则可以修改app.js
中绑定路由的参数,前面加上路径。
app.use('/user',router);
postman结果如下:依旧可以正常工作。
5.1.4 服务器读取字符串传递参数 query方法
获取params内的键值对数据,也就是?
后面的数据。
1、修改router-demo.js
内get请求的函数:
var express = require("express");
// 创建router对象
var router = express.Router();
// get请求
router.get('/',(req,res)=>{
// 请求对象
console.log("req请求",req);
// 响应对象
res.set({"aHeader":"bHeader"});
res.status(201).send({"name":"小红","age":"16","message":"刚满十六岁~"}); // json格式数据
res.end();
})
// post请求
router.post('/',(req,res)=>{
res.send('Post Express!');
})
// put请求
router.put('/',(req,res)=>{
res.send('Put Express!');
})
// delete请求
router.delete('/',(req,res)=>{
res.send('delete Express!');
})
module.exports = router;
使用浏览器/postman发送一次请求,在VS Code的终端能够看到服务器的console.log调试信息,可以发现非常的长。
req请求 <ref *2> IncomingMessage {
_readableState: ReadableState {
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: [],
awaitDrainWriters: null,
[Symbol(kState)]: 1185840
},
...
[Symbol(kHeadersCount)]: 28,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0
}
2、如果浏览器或postman发送了键值对:
gender: female
网址则变成:
http://localhost:3000/user?gender=female
服务器读取方法如下:req.query.*****
,*****是params中的Key值,输出的是value。
// get请求
router.get('/',(req,res)=>{
// 请求对象
console.log("req请求: ",req.query.gender);
// 响应对象
res.set({"gender":req.query.gender});
res.status(201).send({"name":"小红","age":"16","message":"刚满十六岁~"}); // json格式数据
res.end();
})
服务器控制台可以看到:
postman可以看到服务器返回了键值对gender:female
给自己。
5.1.5 服务器读取动态路由参数 params方法
对于路由路径/user/:id
,当发送请求到/user/123
时,req,params.id
将返回“123”。也就是获取id
。
router-demo.js
文件修改如下,修改router.get('/:id', ...)
,并添加读取req.params.id
:
// get请求
router.get('/:id',(req,res)=>{
// 请求对象
console.log("req请求: ",req.query.gender);
console.log("id: " + req.params.id);
// 响应对象
res.set({"gender":req.query.gender});
res.status(201).send({"name":"小红","age":"16","message":"刚满十六岁~"}); // json格式数据
res.end();
})
因此在刚才的网址和字符串传递参数之间添加动态路由参数:
http://localhost:3000/user/123?gender=female
发送之后,服务器调试信息如下:
req请求: female
id: 123
5.1.6 服务器读取POST请求的body
注意与5.3.4.2、5.3.4.3区分。
1、安装body-parser,命令行输入:
npm install body-parser
2、引入包、添加中间件、使用req.body读取数据。
//router-demo.js
var express = require("express");
const bodyParser = require("body-parser");
// 创建router对象
var router = express.Router();
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: false }));
// ...
// post请求
router.post('/', (req,res)=>{
console.log("post");
console.log(req.body);
res.send(req.body);
})
// ...
module.exports = router;
3、postman发送数据:
选择body
、选择x-www-form-urlencoded
格式、添加键值对{“nation”:“china”},发送POST请求。
4、可以看到服务器调试端输出:
post
[Object: null prototype] { nation: ‘china’ }
postman接收到:
5.2 express中间件的调用流程
1、客户端发送请求给服务器。
2、express服务器中对数据经过多次处理。
3、express服务器响应客户端请求。
express中间件的本质是function处理函数:
app.get('/', function(req, res, next){
// 处理请求对象 req
// 处理响应对象 res
// ...
next();
})
注意:中间件函数的形参列表中,必须包含next参数。而路由处理函数中只包含req和res。
5.2.1 定义全局中间件函数
修改app.js
,在绑定路由之前加入中间件:
// 路由方法:
// 导入 express服务器
const express = require("express");
const router = require("./router-demo");
const server = express();
// 定义中间件函数
const fw = function(req, res, next){
console.log("执行所有请求的前置函数")
next();
};
server.use(fw);// 实例化使用中间件函数,发出任何请求时执行
// 绑定路由
server.use('/user',router);
server.listen(3000,()=>{
console.log("Express server at: http://localhost:3000");
})
浏览器刷新一下,就可以在服务器调试端口看见中间件反馈的信息。
Express server at: http://localhost:3000
执行所有请求的前置函数
req请求: female
id: 123
多个中间件之间,共享同一份req和res,因此可以在上游的中间件中,统一为req和res对象添加自定义的属性或方法,供下游的中间件使用。
如下定义的就是全局中间件:
// 定义中间件函数1
const fw1 = function(req, res, next){
console.log("前置函数1")
next();
};
server.use(fw1); // 实例化使用中间件函数,发出任何请求时执行
// 定义中间件函数2
const fw2 = function(req, res, next){
console.log("前置函数2")
next();
};
server.use(fw2); // 实例化使用中间件函数,发出任何请求时执行
5.2.2 定义局部中间件函数
编写中间件函数,然后将函数放在GET请求函数中间,可以放置多个。
router.get('/', [
middleWareFunction1,
middleWareFunction2,
...,
], (req, res)=>{
res.send("express get");
})
5.2.1中app.js
的代码不变,修改router-demo.js
的代码:
// router-demo.js
var express = require("express");
// 创建router对象
var router = express.Router();
// 定义局部中间件函数
const mwf1 = function(req, res, next){
console.log("中间件函数1");
next();
};
const mwf2 = function(req, res, next){
console.log("中间件函数2");
next();
};
// get请求
router.get('/:id', [mwf1, mwf2], (req,res)=>{
// 请求对象
console.log("req请求: ",req.query.gender);
console.log("id: " + req.params.id);
// 响应对象
res.set({"gender":req.query.gender});
res.status(201).send({"name":"小红","age":"16","message":"刚满十六岁~"}); // json格式数据
res.end();
})
// post请求
router.post('/',(req,res)=>{
res.send('Post Express!');
})
// put请求
router.put('/',(req,res)=>{
res.send('Put Express!');
})
// delete请求
router.delete('/',(req,res)=>{
res.send('delete Express!');
})
module.exports = router;
postman发送GET请求后,服务器显示如下:
前置函数1
前置函数2
中间件函数1
中间件函数2
req请求: female
id: 123
postman发送POST请求后,服务器显示如下:
前置函数1
前置函数2
可以发现mwf作为局部中间件,在get请求中被调用,但在post请求中没有被调用。而在app.js
文件中的两个全局中间件依然被调用。
注意:
1、在路由之前注册中间件。
2、客户端发送过来的请求,可以连续调用多个中间件进行处理。
3、执行完中间件的业务代码之后,一定要调用next()
函数。
4、中间件调用next()之后,一定不要再写额外的代码。
5、连续调用多个中间件时,多个中间件之间,共享req和res对象。
5.3 中间件级别
5.3.1 应用级别的中间件
通过app.use()或app.get()或app.post(),绑定到app实例上的中间件
5.3.2 路由级别的中间件
绑定到express.Router()实例上的中间件。和应用级别的中间件没有区别,只不过一个是绑定到app实例上,一个是绑定到router实例上。
5.3.3 错误级别的中间件
当项目发生异常,从而防止项目异常崩溃。错误级别的中间件函数有四个形参,分别为(err, req, res, next)。
1、修改router-demo.js
的delete请求:
// router-demo.js
router.delete('/',(req,res)=>{
res.status(5000);
throw new Error("服务器发送错误");
})
throw new Error()
为手动抛出一个错误信息。
2、添加错误中间件,由于要全局有效,因此放在app.js
内,还要放在绑定路由的后面。
// app.js
// 导入 express服务器
const express = require("express");
const router = require("./router-demo");
const server = express();
// 定义中间件函数1
const fw1 = function(req, res, next){
console.log("前置函数1")
next();
};
server.use(fw1); // 实例化使用中间件函数,发出任何请求时执行
// 定义中间件函数2
const fw2 = function(req, res, next){
console.log("前置函数2")
next();
};
server.use(fw2); // 实例化使用中间件函数,发出任何请求时执行
// 绑定路由
server.use('/user',router);
// 错误中间件
const errorfw = (error, req, res, next) => {
if(error){
console.log('异常:',error.message);
res.status(500).send('服务器发生错误:' + error.message);
}else{
next();
}
}
server.use(errorfw);
server.listen(3000,()=>{
console.log("Express server at: http://localhost:3000");
})
运行顺序是:中间件请求函数1、中间件请求函数2、router内的请求函数、错误中间件请求函数。
3、Postman发送DELETE请求。
服务器后台显示如下:
前置函数1
前置函数2
异常: 服务器发送错误
postman显示如下:
5.3.4 express内置的中间件
5.3.4.1 express.static()
express.static 快速托管静态资源,比如html文件、图片、css样式。
新建resource
文件夹,在app.js
文件中添加server.use(express.static('resource'));
。
代码如下:
// ...
// 绑定路由
server.use('/user',router);
// 错误中间件
const errorfw = function(error, req, res, next){
if(error){
console.log('异常:',error.message);
res.status(500).send('服务器发生错误:' + error.message);
}else{
next();
}
}
server.use(errorfw);
server.use(express.static('resource'));
server.listen(3000,()=>{
console.log("Express server at: http://localhost:3000/1.jpg");
})
resource文件夹下资源如下:
使用该中间件以管理文件夹内的图片、html、css,资源可通过浏览器访问,地址为:
http://localhost:3000/1.jpg
http://localhost:3000/1.html
http://localhost:3000/1.css
5.3.4.2 express.json()
注意与5.1.6、5.3.4.3区分。
express.json 解析JSON格式的body请求体数据。
1、修改app.js
文件,在路由之前添加express.json()
,代码如下:
// app.js
// ...
server.use(express.json());
server.use('/user',router); // 绑定路由
// ...
2、在router-demo.js
文件内,修改post请求,代码如下:
//router-demo.js
var express = require("express");
// 创建router对象
var router = express.Router();
// ...
// post请求
router.post('/', (req,res)=>{
console.log("post");
console.log(req.body);
//res.send('Post Express!');
res.send(req.body);
})
// ...
module.exports = router;
3、postman发送数据:选择POST、Body、raw、JSON,文本输入:
{
"name":"小明"
}
点击Send发送请求。
4、postman接收到的信息如上图下侧,服务器调试端口如下:
post
{ name: ‘小明’ }
5.3.4.3 express.urlencoded()
注意与5.1.6、5.3.4.3对比。
express.urlencoded 解析URL-encoded格式的params请求体数据,也就是网址?
后面的数据。
1、修改app.js
文件,在路由之前添加express.urlencoded({extended:false})
,代码如下:
// app.js
server.use(express.json());
server.use(express.urlencoded({extended:false}));
// 绑定路由
server.use('/user',router);
2、在router-demo.js
文件内,修改post请求,代码如下:
//router-demo.js
var express = require("express");
// 创建router对象
var router = express.Router();
// ...
// post请求
router.post('/', (req,res)=>{
console.log("post");
console.log(req.body);
const {username, password} = req.body;
console.log("username: " + username);
console.log("password: " + password);
res.send(req.body);
})
// ...
module.exports = router;
3、postman选择POST请求、Body、x-www-form-urlencoded,添加键值对{“username”:“john”,“password”:“123456789”},发送请求。
4、服务器调试端口:
post
[Object: null prototype] { username: ‘john’, password: ‘1234568789’ }
username: john
password: 1234568789
postman显示:
5.3.5 第三方的中间件
略
6 express连接Mysql数据库
6.1 Mysql数据库配置
1、安装Mysql和Mysql Workbench,其他管理工具也可以,当然只用命令行也行。
2、新建连接:
主界面点击加号添加新的连接。这里可以创建默认Schema。输入密码,测试连接。
3、新建表 Table,添加元素与其对应的数据类型。
4、插入数据:
insert into gps_fence.user_login values(2,"root","woshiroot","123456789@qq.com","18200000000","0123456789",true);
然后点击闪电执行代码,下方显示出具体数据。
6.2 后端js连接测试
6.2.1 引入mysql库
终端输入:
npm install -s mysql
6.2.2 连接数据库
新建文件mysql-demo.js
,测试数据库连接。
代码如下:
const mysql = require("mysql");
const connection = mysql.createConnection({
host:'localhost',
user:'root',
password:'woshiroot',
database:'gps_fence'
});
const table = 'user_login';
// 连接数据库
connection.connect((err) =>{
if(err){
console.log('Error connecting to MYSQL database: ' + err.stack);
return;
}else{
console.log('Connect to MYSQL database as id' + connection.threadId);
}
})
6.2.3 查询数据
js代码如下:
// 发送查询请求
const sqlStr = `select * from ${table}`;
connection.query(sqlStr, (err, results)=>{
if(err){
return console.log(err.message);
}else{
console.log(results);
}
})
调试输出:
[
RowDataPacket {
user_id: 1,
username: 'root',
password: 'woshiroot',
email: '14*********5@qq.com',
phonenumber: '18206170000',
worknumber: '0123456789',
valid: 1
},
RowDataPacket {
user_id: 2,
username: 'root',
password: 'woshiroot',
email: '123456789@qq.com',
phonenumber: '18200000000',
worknumber: '0123456789',
valid: 1
}
]
6.2.4 插入数据
js代码如下:
//插入数据请求
const user_data = {
username:'joe',
password:'iamjoe20240107',
email:'20240107@gmail.com',
phonenumber:'1119491001',
worknumber:'007',
};
const sqlStr1 = `insert into ${table} (username,password,email,phonenumber,worknumber) values (?,?,?,?,?)`;
// console.log(sqlStr1);
connection.query(sqlStr1, [
user_data.username,
user_data.password,
user_data.email,
user_data.phonenumber,
user_data.worknumber
], (err, results)=>{
if(err){
return console.log(err.message);
}else{
console.log(results);
}
})
查看Mysql Workbench,发现数据已经添加到数据库。
插入方法2:
//插入数据请求
const user_data = {
username:'tom',
password:'tomcat19990101',
email:'19990101@gmail.com',
phonenumber:'1119491011',
worknumber:'008',
};
const sqlStr1 = `insert into ${table} (username,password,email,phonenumber,worknumber) values `;
// console.log(sqlStr1);
const user_data_amended = `(${Object.values(user_data).map(value => `"${value}"`).join(',')})`;
console.log(user_data_amended);
connection.query(sqlStr1 + user_data_amended, (err, results)=>{
if(err){
return console.log(err.message);
}else{
console.log(results);
}
})
mysql数据库显示如下:
6.2.5 修改数据
6.2.6 删除数据
6.3 前端后端连接
前端发送GET请求,后端访问数据库,查询数据并发送给前端。
1、安装库:express、body-parser、cors、mysql
npm install -s express body-parser cors mysql
2、新建文件db.js
,代码如下:
// db.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mysql = require('mysql');
const app = express();
app.use(bodyParser.json());
app.use(cors());
// 结合Mysql数据库
const connection = mysql.createConnection({
host:'localhost',
user:'root',
password:'root',
database:'test'
})
const table = 'user_login';
// 连接数据库
connection.connect((err) =>{
if(err){
console.log('Error connecting to MYSQL database: ' + err.stack);
return;
}else{
console.log('Connect to MYSQL database as id' + connection.threadId);
}
})
// 查询数据请求
const sqlStr = `select * from ${table}`;
connection.query(sqlStr,(err, results, fields)=>{
if(err){
return console.log(err.message);
}else{
console.log(results);
app.post('/api',(req, res)=> {
res.send("none");
})
app.get('/api',(req, res)=> {
if(req.query.key === "1234"){
res.send(results);
}else{
res.send("wrong key");
}
})
app.listen(3000,()=>{
console.log("Express server at: http://localhost:3000");
})
}
})
3、Postman相当于前端,给服务器发送Get请求:
4、服务器给Postman返回的信息如下,正是Mysql内的数据。
[
{
"user_id": 1,
"username": "root",
"password": "woshiroot",
"email": "123456789@qq.com",
"phonenumber": "18200000000",
"worknumber": "0123456789",
"valid": 1
},
...
]
6.4 工程接口API
工程中最好使用sequelize进行数据库池的管理。
6.4.1 安装 sequelize
npm install sequelize
Sequelize常用基本方法,方便对数据库进行增删改查的操作:
- create(values, options):创建一个新的数据实例。
- bulkCreate(records, options):批量创建多个数据实例。
- findAll(options):查询满足条件的所有数据实例。
- findOne(options):查询满足条件的第一个数据实例。
- findByld(identifier, options):根据逐渐或者ID查询数据实例。
- update(values, options):更新满足条件的数据实例的值。
- destroy(options):删除满足条件的数据实例。
- count(options):统计满足条件的数据实例的数量。
- increment(fields, options):自增满足条件的数据实例的指定字段值。
- decrement(fields, options):自减满足条件的数据实例的指定字段值。
6.4.2 创建数据库配置文件
新建config
文件夹,新建dbconfig.js
,代码如下:
//dbconfig.js
const Sequelize = require('sequelize');
// 创建一个新的Sequelize实例
const DB = new Sequelize("test","root","root",{ //分别为数据库名、用户名、密码
host:'localhost',
port: 3306,
dialect:'mysql',
pool:{
max:100,
min:0,
idle:10000, // 10秒没有使用,释放该连接
},
logging:console.log, //Sequelize日志输出方法
})
// 测试数据库连接
DB.authenticate().then(()=>{
console.log("数据库连接成功");
}).catch((err)=>{
console.log("数据库连接失败: ",err)
});
module.exports = DB;
6.4.3 创建模型
由于数据库的表内不同的字段有不同的数据类型,比如INTEGER、VARCHAR、TINYINT等等,需要nodejs对相应的数据进行类型匹配。field内字符串需要与mysql内完全相同。
可以新建多个模型文件,管理数据库内不同的表(Table)。
创建Models
文件夹,创建user-login_model.js
,代码如下:
// user-login_model.js
const DB = require("../config/dbconfig.js");
const Sequelize = require('sequelize');
// user_login是数据库的表名 define('表名',{字段})
// 模型与数据库表名的映射
const user_login_model = DB.define("user_login",{
id:{
primaryKey: true,
type: Sequelize.INTEGER,
field:"user_id",
autoIncrement:true
},
username:{
type:Sequelize.STRING(45),
allowNull:true,
field:"username"
},
password:{
type:Sequelize.STRING(45),
allowNull:true,
field:"password"
},
email:{
type:Sequelize.STRING(45),
allowNull:true,
field:"email"
},
phonenumber:{
type:Sequelize.STRING(45),
allowNull:true,
field:"phonenumber"
},
worknumber:{
type:Sequelize.STRING(45),
allowNull:true,
field:"worknumber"
},
valid:{
type:Sequelize.BOOLEAN,
allowNull:false,
defaultValue:false,
field:"valid"
}
},{
freezeTableName: true, // 防止sequelize自动在表名后加s
timestamps: false // 禁用createAt和updateAt
});
module.exports = user_login_model;
6.4.4 添加路由
可以新建多个路由文件,每个路由文件内对相同表单进行不同路由的数据处理。
新建routes
文件夹,新建user_login.js
文件,代码如下:
// user_login.js
// 导入express
const express = require('express');
const router = express.Router();
const user_login_model = require("../Models/user_login_model.js");
// 获取所有学生信息:http://localhost:3000/user_login/search
router.get('/search', async (req, res, next) => {
try {
const result = await user_login_model.findAll({ raw: true });
res.json({
code: 1001,
msg: result,
});
} catch (err) {
next(err);
}
});
// 添加user信息:http://localhost:3000/user_login/add
router.post('/add', async (req, res, next) => {
try {
const { username, password, email, phonenumber, worknumber, vaild } = req.body;
await user_login_model.create({ username, password, email, phonenumber, worknumber, vaild });
await res.json({
code: 1001,
msg: '数据插入成功',
});
} catch (err) {
next(err);
}
});
// 删除学生信息:http://localhost:3000/user_login/delete
router.post('/delete', async (req, res, next) => {
try {
const { id } = req.body;
await user_login_model.destroy({ where: { id } });
await res.json({
code: 1001,
msg: '删除成功',
});
} catch (err) {
next(err);
}
});
// 更新某条信息:http://localhost:3000/user_login/update
router.put('/update', async (req, res, next) => {
try {
const { id, valid } = req.body;
const user = await user_login_model.findOne({ where: { id } });
if (!user) {
return res.json({
code: 1002,
msg: '查询失败',
});
}
await user.update({ valid });
await res.json({
code: 1001,
msg: 'valid更新成功',
});
} catch (err) {
next(err);
}
});
// 错误处理中间件
router.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
code: 1002,
msg: '服务器发生错误',
});
});
module.exports = router;
6.4.5 添加引用
在app.js
文件内,导入路由文件,如果有多个路由,需要可以使用path方法进行添加。
// app.js
// 导入 express服务器
const express = require("express");
// 导入router
const path = require('path');
const app = express();
const cors = require('cors');
//路由加载之前使用内置中间件
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use(cors());
app.use(express.static('resource'));
// 导入路由
const user_loginRouter = require(path.join(__dirname, 'routes', 'user_login.js'));
app.use('/user_login',user_loginRouter);
const device_infoRouter = require(path.join(__dirname, 'routes', 'device_info.js'));
app.use('/device_info',device_infoRouter);
app.listen(3000,()=>{
console.log("Express server at: http://localhost:3000");
})
6.4.6 代码测试
1、运行程序,命令行输入:
npm start
2、Postman发送请求:
6.4.6.1 Get请求,查询数据:
请求地址:localhost:3000/user_login/search
返回数据如下:
6.4.6.2 Post请求,添加信息:
请求地址:http://localhost:3000/user_login/add
选择body,选择x-www-form-urlencoded,在下方添加需要输入数据表的键值对。
点击发送,Postman收到回复:
{
“code”: 1001,
“msg”: “数据插入成功”
}
查看数据表user_login:
6.4.6.3 Post请求,删除信息:
请求地址:http://localhost:3000/user_login/delete
选择body,选择x-www-form-urlencoded,只要输入id。
返回数据:
{
“code”: 1001,
“msg”: “删除成功”
}
数据表情况:可以看到user_id为5的数据已经被删除。
6.4.6.4 Put请求,修改数据:
请求地址:http://localhost:3000/user_login/update
请求数据:这里使用原始数据JSON格式发送(用法都一样的)。
返回数据:
{
“code”: 1001,
“msg”: “valid更新成功”
}
数据表情况:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!