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('服务器已经启动...');
})
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 的请求方式来表示:
-
-
【新增】:【POST】http://abc.com/comment/1
-
【查询】:【GET】http://abc.com/comment/1
-
【删除】:【delete】http://abc.com/comment/1
-
【修改】:【PUT】http://abc.com/comment/1
-

浙公网安备 33010602011771号