【node进阶】深入浅出---MVC设计模式&RESTful风格

简介: 【node进阶】深入浅出---MVC设计模式&RESTful风格

0.gif

接口规范

RESTful架构


  • 为什么要用RESTful


在以往我们去写接口的时候,我们总是自己去命名,虽然不影响正常的使用,但是当你进入到一个大一点的开发团队里面你得遵循团队的接口规范,大多数团队用的就是RESTful规范(当然,不是所有的团队都是,但是你通过学习RESTful就可以轻松入手其他的规范,道理是相差无几的),为了能够无缝衔接的进入到团队开发,RESTful架构是值得学习的。


  • 通俗理解RESTful


RESTful就是对自己写的接口进行规范化,使用RESTful架构可以充分的发挥GET、POST、PUT、DELETE 四种请求方式的意义,简单的来说url地址中只包含名词表示资源,使用http的动词(GET | POST | PUT | DELTE)表示要进行的动作进行操作资源


  • 举例


错误的设计方式


//添加用户
router.post('/user/addUser',(req,res)=>{
  //...
})
//更新用户信息
router.put('/user/updateUser',(req,res)=>{
  //...
})
//删除用户
router.delete('/user/delUser',(req,res)=>{
  //...
})
//获取用户信息
router.get('/user/getUser',(req,res)=>{
  //...
})


正确的设计方式


//添加用户
router.post('/user',(req,res)=>{
  //...
})
//更新用户信息
router.put('/user/:id',(req,res)=>{
  //...
})
//删除用户
router.delete('/user/:id',(req,res)=>{
  //...
})
//获取用户信息
router.get('/user',(req,res)=>{
  //...
})


注意:后端要跟前端进行语义化的规定,统一战线!例如:想要获取用户信息,前端发送GET请求即可…


使用方式


REST要求,必须通过统一的接口来对资源执行各种操作:


image.png

image.png


过滤信息


一般情况下我们只是把?简单的当做是参数的传递,很容易造成url过于复杂、难以理解。可以把?用于对资源的过滤.

例如:


image.png


注意:我们在进行筛选的时候一定要与后端做好约定。


业务分层


MVC设计模式


MVC应该是编程界众所周知的,M即Model,V即View,C即Controller。分别对应我们的业务模型,用户界面和控制器。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。


上面一直用官方的话来说,大家肯定觉得比较抽象,下面我以画图的形式展现了出来(画的不好,大家应该可以看懂),MVC每层之间的逻辑关系:


1.png


controller:C层负责业务逻辑(view与model之间的桥梁)

view:V层负责展现页面

model:M层负责处理数据(连接数据库进行增删改查)


node中使用MVC思想


在这里先分享一下node中的MVC是怎么样实现的,如下图所示:


2.png


node中MVC实现代码(RESTful+MVC)


通过上图我们了解到了MVC思想在node中怎么执行的,接下来,我们通过代码进行分析:


1.代码架构


/

3.png


2.db.config.js(连接数据库



//链接数据库
const mongoose = require("mongoose")
mongoose.connect("mongodb://127.0.0.1:27017/lzq_project")
//插入集合和数据,数据库lzq_project会自动创建


3.UserService.js(创建模型,配置数据库信息)



const mongoose = require('mongoose')
const UseeType = {
    username : String,
    password : String,
    age : Number
}
const UserModel = mongoose.model('user',new mongoose.Schema(UseeType))
//模型user 将会对应 users 这个集合,
module.exports = UserModel


4.user.js(用户路由模块)



var express = require('express');
const UserController = require('../controllers/UserController');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});
//相应前端post请求-增加用户
router.post('/user',UserController.addUser)
//动态路由,获取id
router.put('/user/:id',UserController.updateUser)
//删除请求  restful
router.delete('/user/:id',UserController.delUser)
router.get('/user',UserController.getUser)
module.exports = router;


5.UserModel.js(M层,业务逻辑实现数据库增删改查)


const UserModel = require("../model/UserModel")
const UserService = {
    addUser : (username,password,age) => {
        return UserModel.create({username,password,age})
    },
    updateUser : (_id,username,password,age)=>{
        return UserModel.updateOne({_id},{
            username,password,age
          })
    },
    delUser : (_id) => {
        return UserModel.deleteOne({_id})
    },
    getUser : (page,limit) => {
        return UserModel.find({},["username","age"]).skip((page-1)*limit).limit(limit).sort({age:-1})//年龄倒序排列---  -1   正序   1
    }
}
module.exports = UserService


6.UserController.js(C层,把M层的数据给V层)


const UserService = require("../services/UserService");
const UserController = {
    addUser: async (req,res)=>{
        console.log(req.body);
        //插入数据库
        // 1.创建模型,一一对应数据库的集合(users)
        const {username,password,age} = req.body
        await UserService.addUser(username,password,age)
        res.send({
            ok:1
          })
    },
    //更新用户信息的回调函数
    updateUser: async (req,res)=>{
        console.log(req.body,req.params.id);
        const {username,password,age} = req.body
        await UserService.updateUser(req.params.id,username,password,age)
        res.send({ok:'ok'})
    },
    delUser : async (req,res)=>{
        await UserService.delUser(req.params.id)
        res.send({ok:'1'})
    },
    getUser : async (req,res)=>{ 
        console.log(req.query);
        const {page,limit} = req.query
        const data = await UserService.getUser(page,limit)
        res.send(data)
      }
}
module.exports = UserController


7.index.ejs(V层,前端显示的页面)


<body>
  <h1>mongoDB增删改查的演示</h1>
  <div>
    <div>用户名:<input id="username" /></div>
    <div>密码:<input type="password" id="password" /></div>
    <div>年龄:<input type="age" id="age" /></div>
    <div><button id="register">注册</button></div>
  </div>
  <hr>
  <div>
    <button id="update">更新</button>
    <button id="del">删除</button>
  </div>
  <hr>
  <table border="1">
    <thead>
      <tr>
        <td>id</td>
        <td>用户名</td>
        <td>年龄</td>
        <td>操作</td>
      </tr>
    </thead>
    <tbody>
    </tbody>
  </table>
  <script>
    let name = document.querySelector('#username')
    let psd = document.querySelector('#password')
    let age = document.querySelector('#age')
    register.onclick = () => {
      console.log(name.value, psd.value, age.value);
      fetch("/api/user", {
        method: 'post',
        body: JSON.stringify({
          username: name.value,
          password: psd.value,
          age: age.value
        }),
        headers: {
          "Content-Type": "application/json"
        }
      }).then(res => res.json())
        .then(res => {
          console.log(res);
        })
    }
    update.onclick = () => {
      fetch("/api/user/634f5d8ed2922eaf4a9972b1", {
        method: 'put',
        body: JSON.stringify({
          username: "修改的名字",
          password: "修改的密码",
          age: 20
        }),
        headers: {
          "Content-Type": "application/json"
        }
      }).then(res => res.json())
        .then(res => {
          console.log(res);
        })
    }
    del.onclick = () => {
      fetch("/api/user/634f5d8ed2922eaf4a9972b1",{
        method:'DELETE'
      }).then(res => res.json())
        .then(res => {
          console.log(res);
        })
    }
    fetch("/api/user?page=1&limit=5").then(res => {
      return res.json()
    }).then(res => {
      console.log(res);
      let tbody = document.querySelector('tbody')
      tbody.innerHTML = res.map(item => {
        return `<tr>
              <td>${item._id}</td>
              <td>${item.username}</td>
              <td>${item.age}</td>
              <td><button data-id="${item._id}" id="btn">更新</button> <button data-id="${item._id}" id="del">删除</button></td>
             </tr>`
      }).join('')
      tbody.onclick = (event) => {
        console.log(event.target);
        if (event.target.id === "btn") {
          fetch(`/api/user/${event.target.dataset.id}`, {
            method: 'post',
            body: JSON.stringify({
              username: "以后绝不压竞猜&阿修",
              age: 22
            }),
            headers: {
              "Content-Type": "application/json"
            }
          }).then(res => res.json())
            .then(res => {
              fetch("/api/user?page=1&limit=5").then(res => res.json())
                .then(res => {
                  tbody.innerHTML = res.map(item => {
                    return `<tr>
              <td>${item._id}</td>
              <td>${item.username}</td>
              <td>${item.age}</td>
              <td><button data-id="${item._id}" id="btn">更新</button> <button data-id="${item._id}" id="del">删除</button></td>
             </tr>`
                  }).join('')
                })
            })
        }
        if (event.target.id === 'del') {
          console.log(event.target.id);
          fetch(`/api/user/${event.target.dataset.id}`).then(res => res.json()).then(res => {
            fetch("/api/user?page=1&limit=5").then(res => res.json())
              .then(res => {
                tbody.innerHTML = res.map(item => {
                  return `<tr>
              <td>${item._id}</td>
              <td>${item.username}</td>
              <td>${item.age}</td>
              <td><button data-id="${item._id}" id="btn">更新</button> <button data-id="${item._id}" id="del">删除</button></td>
             </tr>`
                }).join('')
              })
          })
        }
      }
    })
  </script>
</body>


最终效果


4.gif


MVC的优缺点


从上面的代码中可以观察得出来一个事情,我们的代码结构很清晰,分离一层一层去写,方便维护,但是同时发现项目明显的便复杂了,所以总结了MVC的优缺点


MVC的优点


  1. 耦合性低,方便维护,可以利于分工协作
  2. 代码的复用性比较强


MVC的缺点:


项目变得的确优点复杂,对书写代码的小伙伴们要求得比较多


小结


大家跟我的node专栏学习走到这里就可以发现一个有趣的事情:


node+express+RESTful+MVC嘎嘎好用,其实到这里你的node可以进行适当的开发了,后面的文章加一个身份验证以及写一个全栈项目,node就要完结了,所以下一篇就是我们的身份验证,同时还要更新【node番外】mongoDB和mysql两个数据库哦,以及node连接数据库。

少年,继续加油吧!😀😀


相关文章
|
4月前
|
设计模式 前端开发 Java
Java设计模式【二十六】:MVC模式
Java设计模式【二十六】:MVC模式
35 0
|
4月前
|
设计模式 存储
二十三种设计模式全面解析-原型模式进阶之原型管理器:集中管理对象原型的设计模式之道
二十三种设计模式全面解析-原型模式进阶之原型管理器:集中管理对象原型的设计模式之道
|
2月前
|
Web App开发 JavaScript NoSQL
深入浅出:构建基于Node.js的RESTful API
在当今快速发展的互联网时代,RESTful API已成为前后端分离架构中不可或缺的一部分。本文旨在为初学者和中级开发人员提供一个清晰、简洁的指南,详细介绍如何使用Node.js构建一个高效、可维护的RESTful API。通过结合实际案例,本文将从API设计理念出发,深入讲解如何利用Express框架及MongoDB数据库实现API的增删改查功能,同时探讨如何通过JWT进行安全认证,确保数据传输的安全性。此外,文章还将简要介绍如何使用Swagger生成API文档,使得API的测试和维护更加便捷。无论你是希望提升现有项目的API设计,还是想从零开始构建一个新项目,本文都将为你提供一条清晰的道路
|
3天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
1月前
|
Web App开发 JavaScript 前端开发
使用Node.js和Express构建RESTful API
使用Node.js和Express构建RESTful API
19 0
|
2月前
|
设计模式 存储 前端开发
Java Web开发中MVC设计模式的实现与解析
Java Web开发中MVC设计模式的实现与解析
|
2月前
|
JSON 前端开发 Java
【JavaEE进阶】 关于Spring mvc 响应
【JavaEE进阶】 关于Spring mvc 响应
|
2月前
|
前端开发 Java 应用服务中间件
【JavaEE进阶】 初识Spring Web MVC
【JavaEE进阶】 初识Spring Web MVC
|
2月前
|
NoSQL JavaScript 前端开发
深入浅出:使用Node.js和MongoDB构建RESTful API
在当今的软件开发领域,构建高效、可扩展的Web服务已成为开发者的重要任务之一。本文将引导读者通过现代JavaScript环境——Node.js,搭配流行的NoSQL数据库MongoDB,一步步构建一个RESTful API。不同于常规的摘要,我们将采用故事化的方式,通过一个虚构的应用“BookFinder”的开发旅程,带领读者理解API设计、数据库交互及安全性考量等关键知识点。无论你是前端工程师希望深化后端知识,还是后端新手寻求实践机会,本文都将提供你所需的指南和启示。
|
3月前
|
设计模式 存储 前端开发
【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)
【1月更文挑战第13天】【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)