【Nodejs】回顾node中如何使用Express模块写接口_05
目录
一. 后端接口是什么
二. 使用Express模块写后端接口
⬛ 模拟练习 👇
⬛ 代码整合 👇
❣️ 一个前端请求的执行过程:以用户注册路由为例
【前文回顾】👉 深入理解Express框架之如何使用各类中间件_04
一. 后端接口是什么
在网上查资料时,有看到比较高大上专业的说法,在nodejs中,接口是使用nodejs实现的包含方法、属性、索引器和事件作为成员对协定进行定义的引用类型,nodejs可以通过express模块来写接口。
那什么是后端接口:个人认为,通俗的讲就是后端给前端提供的数据,和数据库的交互。
🌴 注:接口是给前端程序的
我们需要明确一个概念,就是所谓后端接口,是后端提供给前端的可以和数据库交互的数据。是给前端程序的而非前端开发人员
在nodejs下,每个路由对应一个接口。路由即接口,如一个登陆路由就是一个登陆接口。不同的后端语言,接口的实现形式不一样,nodejs下的接口,就是以路由的形式实现,也就是说,在nodejs下,接口的形式就是一个路由。
二. 使用Express模块写后端接口
我们在工作中,时常碰到这种场景,有时候前端需要调用接口,测试功能,但是相关的接口还没有开发好,或者没有相应的数据,这时候怎么办呢?在这里,我们就来模拟一下,在实际开发中,使用nodejs+express写自己的接口
示例:项目目录结构图(用户模块为例)
public ......................................托管静态资源目录,放所有的静态文件
router.......................................存放所有的路由器的目录
user.js................................用户路由器
app.js........................................web服务器文件,项目的启动文件
pool.js......................................连接池文件,被路由器所使用
本地项目存储位置如下:👇
项目文件夹xz的内容:👇
⬛ 模拟练习 👇
练习:创建文件app.js,创建web服务器,托管静态资源到public目录,包含用户注册的文件user_reg.html,点击提交,向服务器端发请求(post /reg)。使用用户路由器。
练习:在router/user.js中创建路由器对象,添加用户注册的路由(post /reg),导出路由器对象;在web服务器app.js中引入用户路由器并挂载,添加前缀/user
提示:require('./router/user.js')
练习:在app.js 下,使用body-parser中间件将post请求的数据解析为对象,在路由中获取
练习:用户登录
练习:修改用户
练习:删除用户
练习:检索用户
⬛ 代码整合 👇
*app.js ------服务器
//引入express包const express=require('express');//引入用户路由器const userRouter=require('./router/user.js');//引入body-parser中间件const bodyParser=require('body-parser');// console.log(userRouter);//创建web服务器const app=express();//设置端口app.listen(8080);//托管静态资源到public目录app.use( express.static('./public') );//使用body-parser中间件将post请求数据解析为对象app.use( bodyParser.urlencoded({ extended:false}) );//路由器/路由在最后出现(中间件就是要拦截路由的,所以一定要放在路由器挂载之前,才能起到拦截的作用)//在web服务器挂载路由器,添加前缀/user//路由URL访问 /user/reg app.use( '/user',userRouter );
*pool.js ------连接池
//引入mysql模块const mysql=require('mysql');//创建连接池对象const pool=mysql.createPool({ host:'127.0.0.1', port:'3306', user:'root', password:'', database:'xz', connectionLimit:'20'});//导出连接池对象module.exports=pool;
路由器目录router下的路由器:
*user.js ------用户路由器
//引入exress包const express=require('express');//引入连接池模块const pool=require('../pool.js');//console.log(pool);//创建路由器对象const r=express.Router();//添加路由//1.用户注册 post /reg 接口地址:http://127.0.0.1:8080/user/regr.post('/reg',(req,res)=>{ //1.1获取post请求的数据 let obj=req.body; console.log(obj); //1.2验证数据是否为空 if(!obj.uname){ res.send({code:401,msg:'uname required'});//阻止往后执行return; } if(!obj.upwd){ res.send({code:402,msg:'upwd required'});return; } if(!obj.email){ res.send({code:403,msg:'email required'});return; } if(!obj.phone){ res.send({code:404,msg:'phone required'});return; } //1.3执行SQL命令 pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{ if(err) throw err;console.log(result);//注册成功res.send({code:200,msg:'reg suc'}); });});//2.用户登录 post /login 接口地址:http://127.0.0.1:8080/user/loginr.post('/login',(req,res)=>{ //2.1获取post请求的数据 let obj=req.body; console.log(obj); //2.2验证数据是否为空 if(!obj.uname){ res.send({code:401,msg:'uname required'});return; } if(!obj.upwd){ res.send({code:402,msg:'upwd required'});return; } //2.3执行SQL命令 //到数据中查询是否有用户名和密码同时匹配的数据 pool.query('SELECT * FROM xz_user WHERE uname=? AND upwd=?',[obj.uname,obj.upwd],(err,result)=>{ if(err) throw err; //返回的结果是空数组,长度为0,说明登录失败console.log(result);if(result.length===0){ res.send({code:301,msg:'login err'});}else{//查询到了匹配的用户,登录是成功 res.send({code:200,msg:'login suc'}); } });});//3.修改用户 get /update 接口地址:http://127.0.0.1:8080/user/updater.get('/update',(req,res)=>{ //3.1获取查询字符串传递的数据 let obj=req.query; console.log(obj); //3.2使用for-in遍历对象,验证各项是否为空 //声明变量用于保存状态码 let i=400; for(let k in obj){//每循环一个属性,i加1i++;//k代表每个属性名 obj[k]代表对应的属性值 //console.log(k,obj[k]); //如果属性值为空,则提示该项属性不能为空if(!obj[k]){ res.send({code:i,msg:k+' required'}); return;} } //3.3执行SQL命令 //修改数据,将整个对象修改 pool.query('UPDATE xz_user SET ? WHERE uid=?',[obj,obj.uid],(err,result)=>{ if(err) throw err;//返回的是对象,如果对象下的affectedRows为0说明修改失败,否则修改成功console.log(result);if(result.affectedRows===0){ res.send({code:301,msg:'update err'});}else{ res.send({code:200,msg:'update suc'});} });});//4.删除用户 get /delete 接口地址:http://127.0.0.1:8080/user/deleter.get('/delete',(req,res)=>{ //4.1获取查询字符串传递的数据 let obj=req.query; console.log(obj); //4.2验证数据是否为空 if(!obj.uid){ res.send({code:401,msg:'uid required'});return; } //4.3执行SQL命令 pool.query('DELETE FROM xz_user WHERE uid=?',[obj.uid],(err,result)=>{ if(err) throw err;//返回对象,通过affectedRows判断是否删除成功console.log(result);if(result.affectedRows===0){ res.send({code:301,msg:'delete err'});}else{ res.send({code:200,msg:'delete suc'});} });});//查询所有用户// /user/userlist 接口地址:http://127.0.0.1:8080/user/userlistr.get("/userlist",(req,res)=>{// 准备sql语句var sql="select * from xz_user";//连接池查询数据库pool.query(sql,(err,result)=>{if(err) throw err;//把查询结果当做响应传给前台res.send(result);});});// 查询对应uid的用户// /user/userlist_uid 接口地址:http://127.0.0.1:8080/user/userlist_uidr.get("/userlist_uid",(req,res)=>{ let obj=req.query; // console.log(obj)// 准备sql语句var sql="select * from xz_user where uid=?";//连接池查询数据库pool.query(sql,[obj.uid],(err,result)=>{if(err) throw err;//把查询结果当做响应传给前台res.send(result);});});//导出路由器module.exports=r;
静态资源目录public下的静态资源文件:
*user_reg.html
用户注册
用户
密码
邮箱
电话
*user_login.html
用户登录
用户
密码
*user_update.html
修改用户
编号
邮箱
电话
姓名
性别
*user_delete.html
删除用户
编号
*userlist.html
*userlist_uid.html
🏝️ 扩展:
💬 中间件在哪里引入合适?
由于中间件要写在路由文件里,有多少个路由就要写多少个中间件,路由又写在路由器里,路由器最终要挂载到服务器里(app.js),成为服务器的一部分,所以,可以这样认为,以后所有的中间件都要在服务器里引入
💬 连接池在哪里引入合适?
连接池不是中间件,所以不用引用到服务器里,它是一个单独的自定义模块,将来哪一个路由器需要连接数据库,就引用到具体的路由器即可实现一个连接池文件多个复用
❣️ 一个前端请求的执行过程:以用户注册路由为例
在这里我们使用form表单的请求方式,通过浏览器向服务器发出请求
*user_reg.html
用户注册
用户
密码
邮箱
电话
*用户注册路由
用户注册的接口地址:http://127.0.0.1:8080/user/reg
释:路由URL访问 /user/reg
▪️ 路由前缀: /user ▪️ 路由地址:/reg
//引入express包const express=require('express');//引入连接池模块const pool=require('../pool.js');//console.log(pool);//创建路由器对象const r=express.Router();//添加路由//1.用户注册 post /regr.post('/reg',(req,res)=>{ //1.1获取post请求的数据 let obj=req.body; console.log(obj); //1.2验证数据是否为空 if(!obj.uname){ res.send({code:401,msg:'uname required'});//阻止往后执行return; } if(!obj.upwd){ res.send({code:402,msg:'upwd required'});return; } if(!obj.email){ res.send({code:403,msg:'email required'});return; } if(!obj.phone){ res.send({code:404,msg:'phone required'});return; } //1.3执行SQL命令 pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{ if(err) throw err;console.log(result);//注册成功res.send({code:200,msg:'reg suc'}); });});
😇 易犯错误:多个send问题❗ 👉 了解更新send用法详情
Error: Can't set headers after they are sent.
路由中出现多次响应,多个send被调用
1. 首先,启动服务器app.js。
👉 进入项目文件夹xz的路径栏里,输入cmd,回车
👉 nodejs下,启动服务器:node app.js,回车即可启动服务器
😇 小技巧:在命令行输入node以及空格后,输入要运行的文件的开头部分,按tab键可自动补全文件名,这样可以节省输入的时间
2. 使用浏览器请求静态资源文件user_reg.html
👉 静态资源文件请求格式:http://127.0.0.1:8080/user_reg.html
浏览器地址栏输入,以上地址,运行结果:
3. 输入用户注册的表单信息,通过浏览器向服务器提交form表单请求
❗ 注意:form表单的action属性值中url:"/user/reg",要和后端接口url保持一致:r.post('/reg',req,res)=>{ ... }
4. 服务器(后端)获取前端的请求数据
👉 nodejs通过创建对应的注册路由,在路由中获取上图form表单提交传递的数据,如下图红框的内容为后端获取的数据
r.post('/reg',(req,res)=>{ //获取post请求的数据 let obj=req.body; console.log(obj); // 下图红框数据👇 👇
👉 接下来,nodejs通过连接池对象操作数据库,执行sql命令,向浏览器页面返回注册成功的数据
pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{ if(err) throw err;console.log(result);// 结果为下图蓝框数据//注册成功res.send({code:200,msg:'reg suc'}); // 响应返回给浏览器页面的展示数据 });});
❗ 注意:安装mysql数据库后,在操作数据库前,先启动数据库服务
nodejs操作数据库,需要启动数据库服务,所以,在通过浏览器请求静态资源文件user_reg.html后,向服务器提交form表单请求前,我们通过XAMPP客户端启动mysql数据库
如果这篇【文章】有帮助到你,希望可以给【青春木鱼】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【前端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️【青春木鱼】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!