Node.js框架--Express

Express 的特点:

  • 易上手

  • 高性能

  • 扩展性强:可以自由的拆分和安装模块

安装 Express

// 示例:使用 express 快速搭建一个服务器

const express = require('express');
const app = express();

app.get('/', (req, res)=>{
    res.send('<h1>Hello Express</h1>')
}).listen(3000,()=>{
    console.log('服务器已经启动...');
})

Express 本质是一个非常简洁的框架,这个框架本身只是由中间件路由组成。

中间件

本身正常的过程是发送请求到服务器,服务器端对请求进行处理,然后给客户端响应。中间件就是在接收到前端的请求后,做出的一系列的工作。

 

// 下面是一个中间件的示例

function 中间件的名字(req, res, next){
  // req 代表 http 请求
  // res 代表 http 响应
  // next 调用下一个中间件
}

app.use(中间件的名字); //注册中间件

中间件的使用(注册:use)的顺序是很重要的。后面我们在使用中间件的时候,一定要注意中间件的前后顺序关系。

 

一般来讲,我们不会涉及到自己书写中间件,一般都是使用第三方的中间件。

下面以 body-parser 中间件为例

安装 body-parser

npm i body-parser

  具体方法

// 示例:使用 express 快速搭建一个服务器

const express = require('express');
const app = express();
const bodyParser = require('body-parser'); // 引入第三方中间件

// 注册中间件
// 这边注册 bodyParser 的时候,设置一下解析规则
// 原生的 node,如果要获取 post 请求的数据,需要监听事件
// data,end,bodyParser 就可以让我们很轻松的获取到 post 请求的数据
app.use(bodyParser.urlencoded({extended : false}));
app.use(bodyParser.json()); // 把数据解析成 json 对象

let str = `
    <form method="POST" action="">
        <div>
            name : <input type="text" name="username">
        </div>
        <div>
            age : <input type="text" name="userage">
        </div>
        <button>提交</button>
    </form>
`

app.use('/', (req, res)=>{
    if(req.body.username && req.body.userage){
        console.log('拿到了客户端post 请求的数据');
        console.log(`数据为:${req.body.username},${req.body.userage}`);
        res.send(`name 为${req.body.username},age 为${req.body.userage}`);
    } else {
        res.send(str);
    }
}).listen(3000,()=>{
    console.log('服务器已经启动...');
})

  

路由

所谓路由,就是对客户端的请求进行合适的导航。

从 express 4.0 开始,路由已经成为了一个单独的中间件,并且这个中间件是 express 内置。

// index.js
// 示例:使用 express 快速搭建一个服务器

const express = require('express');
const app = express();
const router = require('./router');
// 所以我们需要设置路由将用户不同的 url 导航到不同的页面

app.use('/', router);

app.listen(3000,()=>{
    console.log('服务器已经启动...');
})

// router.js
// 这个就是我的路由文件
// 专门用来管理应用程序的路由

const express = require('express');
const router = express.Router();

// 之后所有的路由配置都挂在这个 router 上面
router.get('/',(req,res)=>{
    res.send('这是首页');
})

router.get('/contact',(req,res)=>{
    res.send('这是联系我们');
})

router.get('/detail',(req,res)=>{
    res.send('这是商品详情');
})

module.exports = router;

  

静态资源的托管

什么是静态资源?

所谓静态资源,就是指 html,css,图片,图标,字体,这些都是静态资源。

在 express 中内置了一个中间件,专门用来管理静态资源。

app.use(express.static(静态资源的目录));

  

__dirname:当前所在的目录
__filename:当前文件所在位置

例如:

console.log(__dirname); // /Users/Jie/Desktop/demo
console.log(__filename); // /Users/Jie/Desktop/demo/index.js

  接下来,我们来设置该项目的静态资源目录,代码如下:

// 示例:使用 express 快速搭建一个服务器

const express = require('express');
const app = express();
const router = require('./router');
// 所以我们需要设置路由将用户不同的 url 导航到不同的页面

app.use(express.static(__dirname + '/public'))

app.use('/', router);

app.listen(3000,()=>{
    console.log('服务器已经启动...');
})

备注:此时在我们的项目根目录下面新建一个 public 目录,新建一个index.html,那么express 会自动访问到 index.html

 

express 脚手架

大家一听到脚手架,第一反应就是工地上的脚手架,就是那个东西。脚手架和工地上的脚手架其实是一个意思,就是把项目的架子搭建起来。

首先第一步,需要安装脚手架工具:

npm i express-generator -g

安装完成后,我们就可以使用命令:

express <项目名> 

但是搭建起来的项目,没有依赖项,所以需要 npm i 安装依赖。

安装完成之后,npm start 就可以启动了。

搭建好项目之后,接下来我们来看一下整个项目的目录结构。

 

  • app.js:入口文件

  • bin:二进制目录

  • node_modules:依赖包

  • package.json:依赖包的记录文件

  • public:静态目录

  • routes:路由

  • views:页面模板

接下来,我们要来做一个具体的项目:学生管理系统 

首先,我们的项目已经用 express 脚手架搭建起来了,我们也学过 mongodb

接下来我们就要把两者结合起来,研究一下 express 搭建的项目中如何访问mongodb

 

mongoose

mongoose 是一个 node.js 操作 mongodb 的驱动程序

所谓驱动程序,就是提供了一套接口。比如,我们新买了一个鼠标,鼠标和我的电脑系统实际上是各自独立,现在,我想用我的操作系统去操作鼠标,那就需要有一套接口程序,我的操作系统,只需要去调用这一套接口,就可以操作鼠标,那么,这一套接口就是驱动程序。

nodejs 和 mongodb 也是两个独立的东西。要想 nodejs 去操作mongodb,我们就需要安装相应的驱动程序才行。

 

首先第一步,安装 mongoose

npm i mongoose

接下来,我们来看一下 mongoose 的使用步骤:

  • 建立数据模型

  • 在数据模型的基础上调用各种方法来操作 mongodb 数据库

 

接下来,我们 来一步一步的做,首先第一步,创建一个 db.js ,该文件负责连接数据库,代码如下:

// 该文件负责书写连接数据库的相关配置

const mongoose = require('mongoose');
// 连接数据库的字符串,说明要连接 f71 数据库
const dbURI = 'mongodb://localhost/f71'; 

mongoose.connect(dbURI,{useNewUrlParser : true, useUnifiedTopology : true});

mongoose.connection.on('connected',()=>{
    console.log('数据库已经连接...');
})

  接下来,我们就需要创建数据模型,在项目根目录代码创建一个 stuModel 的文件,这个文件就是学生模型,代码如下:

// 该文件就是数据模型文件
require('./db.js')
const mongoose = require('mongoose');

// 1. 创建 Schema,Schema 就是我们数据模型的骨架
// 在创建 Schema,就需要和集合(表)进行对应
const stuSchema = new mongoose.Schema({
    name : String,
    age : Number,
    gender : String,
    score : Number
});

// 2. 根据上面创建的 Schema 来生成数据模型
// (1) model 的名字 (2)定义的 Schema (3)和数据库的哪个集合关联
mongoose.model('stuModel',stuSchema,'stu');

// 3. 将这个模型导出去,后面所有的操作(增删改查)都是基于这个模型
module.exports = mongoose.model('stuModel');

  

接下来,既然我们的模型已经创建好了,接下来我们就要开始使用这个模型来看一下是否能操作 mongodb 数据库

具体代码如下:

const stuModel = require('./stuModel');

stuModel.find((err, data)=>{
    console.log(data);
})

  

三层架构

什么是三层架构?

最早是来自于微软的后端分层的思想。以前的 web 开发是重服务器端,轻客户端。

补充:高类聚,低耦合

所谓高类聚,就是封装一个模块,这个模块应该尽量关心自己的功能。

所谓耦合,就是模块与模块之间的关系,低耦合,就是模块与模块之间的关系要尽量的低。

 

一般来讲,封装一个模块,如果该模块高类聚,那么它必然也是低耦合。

三层架构的解释如下:

三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。 [1]

三层架构区分层次的目的是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。

 

接下来,我们来看一下在我们的项目中,如何实现三层架构。

首先在项目根目录下,创建 dao 和 service 目录,dao 就是持久层,service 就是业务层,routes 就作为我们的表现层。

dao 既然作为持久层,所以,我们所有的数据库相关的操作,都应该放进dao目录里面。

在 dao 层里面新建 model 目录,所有的 model 放进这个目录里面。db.js 也放进这个 dao 目录。

stuDao.js 负责和数据库打交道,具体代码如下:

const stuModel = require('./model/stuModel');

module.exports.getStuDao = async function(){
    return await stuModel.find();
}

  dao 层操作数据库拿到的数据传递给业务层,代码如下:

// 这一层就是我们的业务层

const {getStuDao} = require('../dao/stuDao');

module.exports.getStuService = async function(){
    return await getStuDao()
}

  业务层的代码又会传递给表现层,代码如下:

var express = require('express');
var router = express.Router();
// 引入业务层的方法
const {getStuService} = require('../service/stuService');

/* GET home page. */
router.get('/stu', async function(req, res, next) {
  res.send(await getStuService());
});

module.exports = router;

  

Restful

在解释 restful 之前,我们先来看一下 rest。

rest 的英语全称为 Representational State Transfer,翻译成中文是“表现层状态转移”。

其实这句话完整的说法是 resource representational state transfer,资源在表现层的状态转移。

  • 资源:指的就是网络资源,或者说网络数据。网络上的一切东西都可以称之为资源,例如一首歌,一部电影,一张图片,一个图标。网络上有这么多资源,我们使用 URI 来标记。所谓上网,其实就是资源之间的互动。

  • representational state:表现层,指的是资源的一种表现形式。一段数据,我可与使用 json 来表示,也可以使用 xml 来表示。上面提到的 URI 只代表存在这个资源,但是这个资源的表现形式由表现层来定义。当我们请求一个数据的时候,响应头里面有一个字段 content-type:html/text png/image jpeg/image

  • transfer:资源存续的状态转移。前面在学习 http 协议的时候,有 GET 请求、POST 请求,这些请求方式其实就是对一个资源进行操作

Restful 其实核心就是一点,应该使用不同的 HTTP 请求方式来标记资源状态的改变。

HTTP 请求方式,实际上是有很多的:

  • GET

  • POST

  • DELETE

  • PUT

  • PATCH

  • ....

使用 restful 设计 URL 前后的对比。

删除一个评论:http://abc.com/?method=comment.del&id=xxx

或者

http://abc.com/comment/del/xxx

这样设计 API 违背了 URI 的本质,URI 本质仅仅是标记互联网上面的一个资源,不应该参杂任何的对该资源做出处理的行为

通过 Restful 的 URI 设计风格,可以还原 URI 的本质,让 URI 仅仅是表示一个资源而已。

任何对该资源做的操作,都应该通过 HTTP 的请求方式来表示:

http://abc.com/comment/1

 

posted @ 2020-12-30 23:11  瓜豆のO泡  阅读(209)  评论(0)    收藏  举报