• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Nodejs回顾node使用Express模块写接口_05

武飞扬头像
儒雅的烤地瓜
帮助2

目录

一. 后端接口是什么

二. 使用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  ------服务器

  1.  
    //引入express包
  2.  
    const express=require('express');
  3.  
    //引入用户路由器
  4.  
    const userRouter=require('./router/user.js');
  5.  
    //引入body-parser中间件
  6.  
    const bodyParser=require('body-parser');
  7.  
    // console.log(userRouter);
  8.  
    //创建web服务器
  9.  
    const app=express();
  10.  
    //设置端口
  11.  
    app.listen(8080);
  12.  
    //托管静态资源到public目录
  13.  
    app.use( express.static('./public') );
  14.  
    //使用body-parser中间件将post请求数据解析为对象
  15.  
    app.use( bodyParser.urlencoded({
  16.  
    extended:false
  17.  
    }) );
  18.  
    //路由器/路由在最后出现(中间件就是要拦截路由的,所以一定要放在路由器挂载之前,才能起到拦截的作用)
  19.  
    //在web服务器挂载路由器,添加前缀/user
  20.  
    //路由URL访问 /user/reg
  21.  
    app.use( '/user',userRouter );
学新通

*pool.js  ------连接池

  1.  
    //引入mysql模块
  2.  
    const mysql=require('mysql');
  3.  
    //创建连接池对象
  4.  
    const pool=mysql.createPool({
  5.  
    host:'127.0.0.1',
  6.  
    port:'3306',
  7.  
    user:'root',
  8.  
    password:'',
  9.  
    database:'xz',
  10.  
    connectionLimit:'20'
  11.  
    });
  12.  
    //导出连接池对象
  13.  
    module.exports=pool;

路由器目录router下的路由器:

*user.js  ------用户路由器

  1.  
    //引入exress包
  2.  
    const express=require('express');
  3.  
    //引入连接池模块
  4.  
    const pool=require('../pool.js');
  5.  
    //console.log(pool);
  6.  
    //创建路由器对象
  7.  
    const r=express.Router();
  8.  
    //添加路由
  9.  
    //1.用户注册 post /reg 接口地址:http://127.0.0.1:8080/user/reg
  10.  
    r.post('/reg',(req,res)=>{
  11.  
    //1.1获取post请求的数据
  12.  
    let obj=req.body;
  13.  
    console.log(obj);
  14.  
    //1.2验证数据是否为空
  15.  
    if(!obj.uname){
  16.  
    res.send({code:401,msg:'uname required'});
  17.  
    //阻止往后执行
  18.  
    return;
  19.  
    }
  20.  
    if(!obj.upwd){
  21.  
    res.send({code:402,msg:'upwd required'});
  22.  
    return;
  23.  
    }
  24.  
    if(!obj.email){
  25.  
    res.send({code:403,msg:'email required'});
  26.  
    return;
  27.  
    }
  28.  
    if(!obj.phone){
  29.  
    res.send({code:404,msg:'phone required'});
  30.  
    return;
  31.  
    }
  32.  
    //1.3执行SQL命令
  33.  
    pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{
  34.  
    if(err) throw err;
  35.  
    console.log(result);
  36.  
    //注册成功
  37.  
    res.send({code:200,msg:'reg suc'});
  38.  
    });
  39.  
    });
  40.  
    //2.用户登录 post /login 接口地址:http://127.0.0.1:8080/user/login
  41.  
    r.post('/login',(req,res)=>{
  42.  
    //2.1获取post请求的数据
  43.  
    let obj=req.body;
  44.  
    console.log(obj);
  45.  
    //2.2验证数据是否为空
  46.  
    if(!obj.uname){
  47.  
    res.send({code:401,msg:'uname required'});
  48.  
    return;
  49.  
    }
  50.  
    if(!obj.upwd){
  51.  
    res.send({code:402,msg:'upwd required'});
  52.  
    return;
  53.  
    }
  54.  
    //2.3执行SQL命令
  55.  
    //到数据中查询是否有用户名和密码同时匹配的数据
  56.  
    pool.query('SELECT * FROM xz_user WHERE uname=? AND upwd=?',[obj.uname,obj.upwd],(err,result)=>{
  57.  
    if(err) throw err;
  58.  
    //返回的结果是空数组,长度为0,说明登录失败
  59.  
    console.log(result);
  60.  
    if(result.length===0){
  61.  
    res.send({code:301,msg:'login err'});
  62.  
    }else{//查询到了匹配的用户,登录是成功
  63.  
    res.send({code:200,msg:'login suc'});
  64.  
    }
  65.  
    });
  66.  
    });
  67.  
    //3.修改用户 get /update 接口地址:http://127.0.0.1:8080/user/update
  68.  
    r.get('/update',(req,res)=>{
  69.  
    //3.1获取查询字符串传递的数据
  70.  
    let obj=req.query;
  71.  
    console.log(obj);
  72.  
    //3.2使用for-in遍历对象,验证各项是否为空
  73.  
    //声明变量用于保存状态码
  74.  
    let i=400;
  75.  
    for(let k in obj){
  76.  
    //每循环一个属性,i加1
  77.  
    i ;
  78.  
    //k代表每个属性名 obj[k]代表对应的属性值
  79.  
    //console.log(k,obj[k]);
  80.  
    //如果属性值为空,则提示该项属性不能为空
  81.  
    if(!obj[k]){
  82.  
    res.send({code:i,msg:k ' required'});
  83.  
    return;
  84.  
    }
  85.  
    }
  86.  
    //3.3执行SQL命令
  87.  
    //修改数据,将整个对象修改
  88.  
    pool.query('UPDATE xz_user SET ? WHERE uid=?',[obj,obj.uid],(err,result)=>{
  89.  
    if(err) throw err;
  90.  
    //返回的是对象,如果对象下的affectedRows为0说明修改失败,否则修改成功
  91.  
    console.log(result);
  92.  
    if(result.affectedRows===0){
  93.  
    res.send({code:301,msg:'update err'});
  94.  
    }else{
  95.  
    res.send({code:200,msg:'update suc'});
  96.  
    }
  97.  
    });
  98.  
    });
  99.  
    //4.删除用户 get /delete 接口地址:http://127.0.0.1:8080/user/delete
  100.  
    r.get('/delete',(req,res)=>{
  101.  
    //4.1获取查询字符串传递的数据
  102.  
    let obj=req.query;
  103.  
    console.log(obj);
  104.  
    //4.2验证数据是否为空
  105.  
    if(!obj.uid){
  106.  
    res.send({code:401,msg:'uid required'});
  107.  
    return;
  108.  
    }
  109.  
    //4.3执行SQL命令
  110.  
    pool.query('DELETE FROM xz_user WHERE uid=?',[obj.uid],(err,result)=>{
  111.  
    if(err) throw err;
  112.  
    //返回对象,通过affectedRows判断是否删除成功
  113.  
    console.log(result);
  114.  
    if(result.affectedRows===0){
  115.  
    res.send({code:301,msg:'delete err'});
  116.  
    }else{
  117.  
    res.send({code:200,msg:'delete suc'});
  118.  
    }
  119.  
    });
  120.  
    });
  121.  
    //查询所有用户
  122.  
    // /user/userlist 接口地址:http://127.0.0.1:8080/user/userlist
  123.  
    r.get("/userlist",(req,res)=>{
  124.  
    // 准备sql语句
  125.  
    var sql="select * from xz_user";
  126.  
    //连接池查询数据库
  127.  
    pool.query(sql,(err,result)=>{
  128.  
    if(err) throw err;
  129.  
    //把查询结果当做响应传给前台
  130.  
    res.send(result);
  131.  
    });
  132.  
    });
  133.  
     
  134.  
    // 查询对应uid的用户
  135.  
    // /user/userlist_uid 接口地址:http://127.0.0.1:8080/user/userlist_uid
  136.  
    r.get("/userlist_uid",(req,res)=>{
  137.  
    let obj=req.query;
  138.  
    // console.log(obj)
  139.  
    // 准备sql语句
  140.  
    var sql="select * from xz_user where uid=?";
  141.  
    //连接池查询数据库
  142.  
    pool.query(sql,[obj.uid],(err,result)=>{
  143.  
    if(err) throw err;
  144.  
    //把查询结果当做响应传给前台
  145.  
    res.send(result);
  146.  
    });
  147.  
    });
  148.  
    //导出路由器
  149.  
    module.exports=r;
学新通

静态资源目录public下的静态资源文件:

*user_reg.html

  1.  
    <h2>用户注册</h2>
  2.  
    <form method="post" action="/user/reg">
  3.  
    用户<input type="text" name="uname"><br>
  4.  
    密码<input type="text" name="upwd"><br>
  5.  
    邮箱<input type="text" name="email"><br>
  6.  
    电话<input type="text" name="phone"><br>
  7.  
    <input type="submit">
  8.  
    </form>

*user_login.html

  1.  
    <h2>用户登录</h2>
  2.  
    <form method="post" action="/user/login">
  3.  
    用户<input type="text" name="uname"><br>
  4.  
    密码<input type="text" name="upwd"><br>
  5.  
    <input type="submit">
  6.  
    </form>

*user_update.html

  1.  
    <h2>修改用户</h2>
  2.  
    <form method="get" action="/user/update">
  3.  
    编号<input type="text" name="uid"><br>
  4.  
    邮箱<input type="text" name="email"><br>
  5.  
    电话<input type="text" name="phone"><br>
  6.  
    姓名<input type="text" name="user_name"><br>
  7.  
    性别<input type="text" name="gender"><br>
  8.  
    <input type="submit">
  9.  
    </form>

*user_delete.html

  1.  
    <h2>删除用户</h2>
  2.  
    <form method="get" action="/user/delete">
  3.  
    编号<input type="text" name="uid">
  4.  
    <input type="submit">
  5.  
    </form>

*userlist.html

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="utf-8">
  5.  
    <title></title>
  6.  
    </head>
  7.  
    <body>
  8.  
    <form action="/user/userlist">
  9.  
    <input type="submit">
  10.  
    </form>
  11.  
    </body>
  12.  
    </html>

*userlist_uid.html

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="utf-8">
  5.  
    <title></title>
  6.  
    </head>
  7.  
    <body>
  8.  
    <form action="/user/userlist_uid">
  9.  
    <input type="text" name="uid">
  10.  
    <input type="submit">
  11.  
    </form>
  12.  
    </body>
  13.  
    </html>

🏝️ 扩展:
 

💬 中间件在哪里引入合适?

由于中间件要写在路由文件里,有多少个路由就要写多少个中间件,路由又写在路由器里,路由器最终要挂载到服务器里(app.js),成为服务器的一部分,所以,可以这样认为,以后所有的中间件都要在服务器里引入

💬 连接池在哪里引入合适?

连接池不是中间件,所以不用引用到服务器里,它是一个单独的自定义模块,将来哪一个路由器需要连接数据库,就引用到具体的路由器即可实现一个连接池文件多个复用


❣️ 一个前端请求的执行过程:以用户注册路由为例

在这里我们使用form表单的请求方式,通过浏览器向服务器发出请求

 *user_reg.html

  1.  
    <h2>用户注册</h2>
  2.  
    <form method="post" action="/user/reg">
  3.  
    用户<input type="text" name="uname"><br>
  4.  
    密码<input type="text" name="upwd"><br>
  5.  
    邮箱<input type="text" name="email"><br>
  6.  
    电话<input type="text" name="phone"><br>
  7.  
    <input type="submit">
  8.  
    </form>

*用户注册路由

用户注册的接口地址:http://127.0.0.1:8080/user/reg

释:路由URL访问     /user/reg

▪️ 路由前缀: /user    ▪️ 路由地址:/reg

  1.  
    //引入express包
  2.  
    const express=require('express');
  3.  
    //引入连接池模块
  4.  
    const pool=require('../pool.js');
  5.  
    //console.log(pool);
  6.  
    //创建路由器对象
  7.  
    const r=express.Router();
  8.  
    //添加路由
  9.  
    //1.用户注册 post /reg
  10.  
    r.post('/reg',(req,res)=>{
  11.  
    //1.1获取post请求的数据
  12.  
    let obj=req.body;
  13.  
    console.log(obj);
  14.  
    //1.2验证数据是否为空
  15.  
    if(!obj.uname){
  16.  
    res.send({code:401,msg:'uname required'});
  17.  
    //阻止往后执行
  18.  
    return;
  19.  
    }
  20.  
    if(!obj.upwd){
  21.  
    res.send({code:402,msg:'upwd required'});
  22.  
    return;
  23.  
    }
  24.  
    if(!obj.email){
  25.  
    res.send({code:403,msg:'email required'});
  26.  
    return;
  27.  
    }
  28.  
    if(!obj.phone){
  29.  
    res.send({code:404,msg:'phone required'});
  30.  
    return;
  31.  
    }
  32.  
    //1.3执行SQL命令
  33.  
    pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{
  34.  
    if(err) throw err;
  35.  
    console.log(result);
  36.  
    //注册成功
  37.  
    res.send({code:200,msg:'reg suc'});
  38.  
    });
  39.  
    });
学新通

😇  易犯错误:多个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表单提交传递的数据,如下图红框的内容为后端获取的数据

  1.  
    r.post('/reg',(req,res)=>{
  2.  
    //获取post请求的数据
  3.  
    let obj=req.body;
  4.  
    console.log(obj); // 下图红框数据👇
  5.  
    👇

学新通

👉 接下来,nodejs通过连接池对象操作数据库,执行sql命令,向浏览器页面返回注册成功的数据

  1.  
    pool.query('INSERT INTO xz_user SET ?',[obj],(err,result)=>{
  2.  
    if(err) throw err;
  3.  
    console.log(result);// 结果为下图蓝框数据
  4.  
    //注册成功
  5.  
    res.send({code:200,msg:'reg suc'}); // 响应返回给浏览器页面的展示数据
  6.  
    });
  7.  
    });

学新通

学新通

注意:安装mysql数据库后,在操作数据库前,先启动数据库服务
 

nodejs操作数据库,需要启动数据库服务,所以,在通过浏览器请求静态资源文件user_reg.html后,向服务器提交form表单请求前,我们通过XAMPP客户端启动mysql数据库
 

学新通

 学新通

如果这篇【文章】有帮助到你,希望可以给【青春木鱼】点个👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【前端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️青春木鱼❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhiacigf
系列文章
更多 icon
同类精品
更多 icon
继续加载