笔记目录
小概
本章学习的是Express框架的使用,它是一个基于Node.js的第三方框架,可以更快 更好用的开发web应用。
1. express框架的使用
在项目文件夹目录下 npm init 初始化项目
使用 npm i express 将这个模块下载到本地
使用文档地址:http://expressjs.com/(官方文档) http://expressjs.com.cn/(中文文档)
创建一个简单的服务端
//1. 导入express模块
const express = require('express');
//2. 创建应用
const app = express();
//3. 注册路由
// 就是规定前端的URL和请求方法对应的处理逻辑.
app.get('/index', (req, res) => {
res.send('你好,Express!');
});
//这个回调函数,是用来处理http请求的
//处理哪一个?
//请求方式是get并且URL是 /index
//4. 开启监听.
app.listen(80, () => console.log('服务启动成功!'));
2. express路由注册
//1. 导入express模块
const express = require('express');
//2. 创建应用
const app = express();
//3. 注册路由
// 就是规定前端的URL和请求方法对应的处理逻辑.
// 只能接收get请求,并且url要和第1个参数匹配.
app.get('/index', (req, res) => {
res.send('你好,Express!');
});
//这个回调函数,是用来处理http请求的
//处理哪一个?
//请求方式是get并且URL是 /index
// 只接收post请求,并且url要和第1个参数匹配.
app.post('/addStudent', (req, res) => {
res.send('接收post请求');
});
//注册路由 路由匹配
//请求方式只能是delete
//url要和第1个参数匹配.
app.delete('/student', (req, res) => {
res.send('ok');
});
//4. 开启监听.
app.listen(80, () => console.log('服务启动成功!'));
express的路由匹配与原生的node.js路由匹配的区别:
express可以为符合条件的http请求精准匹配处理逻辑(app.get只接收get请求,并且url必须要和第1个参数完全匹配.;app.post只接收post请求,并且url必须要和第1个参数完全匹配)
而原生则需要大量的if else来判断req.url和req.method
express已经对url的大小写做了兼容处理;如果服务端没有与路由匹配的处理逻辑,那么它会自动的返回404响应状态码
Node.js中res.end():1.结束本次响应.向响应体中追加数据,2.参数只接收string Buffer ,3.在处理完请求之后,必须要调用1次,最多只能调用1次.
express中res.send():1.结束本次响应,
2.向响应体中追加数据
string
Buffer
array -> json(自动转成json类型)
object -> json(自动转成json类型)
3.在处理完请求之后,必须要调用1次,最多只能调用1次.
4. 自动根据返回的内容设置Content-Type, 并且还会自动的设置字符编码
原生node需要获取请求ip需要自己写函数调用,express可以直接通过req.ip得到请求ip地址
关于http的请求方式
- GET: 从服务端获取数据.
- POST: 新增数据.
- PUT/PATCH: 数据/资源的修改.
- DELETE: 删除资源/数据
…
3. express的五个对象
1.express对象
2.Application对象 (就是我们创建出来的app。)
3.Request对象 (回调函数的第1个参数 req)
4.Response对象 (回调函数的第2个参数 res)
5.Router对象 (路由)
4. express路由匹配
普通路由注册(
请求方法和URL都需要完全匹配.
)
app.get
app.post
app.put
app.delete
…
app.use();
不限定http请求方法.
URL只需要第1部分匹配就行.
如果第1个参数省略,那么第1个参数的默认值就是 /
app.all();
不限定请求方式
url必须要和第1个参数完全匹配.
5. express静态资源托管(静态资源服务器)
const express = require('express');
const path = require('path');
const app = express();
//1. 将public目录下的文件做静态资源托管.
app.use(express.static(path.join(__dirname, 'public')));
//不限制请求方式.
//第1个参数省略掉. '/'
//第2个参数是1个 req res 的回调.
//express.static的返回值 就是1个 req res的回调函数.
app.use(); //可以托管多个文件
app.listen(80, ()=>console.log('服务启动成功'));
app.use()第一个参数可以省略 默认就是/ ,express.static()的返回值就是一个req res的回调函数,static翻译过来就是静态的(adj)的意思。
6. 获取joke案例
API: /api/joke
method: get
返回:{
code: 处理状态码
count: 服务器一共有多少条笑话
joke: 随机的一条笑话内容
}
const express = require('express');
const app = express();
app.get('/api/joke', (req, res) => {
//随机的返回一条笑话的内容.
//1. 将jokes.json文件读取出来.
// 如果我们要读取一个json文件,并且这个json文件中的内容是一个标准的json字符串.
// 可以直接使用 require函数加载.
const jokes = require('./data/jokes.json');
//2. 产生1个随机的下标.
const randomIndex = Math.floor(Math.random() * jokes.length);
//3. 返回数据
// 设置http的响应状态码
res.status(200).send({
code: 200,
count: jokes.length,
joke: jokes[randomIndex]
});
})
原生node.js设置响应状态码是res.statusCode = 状态码,express是res.satus(200).send({})实现链式编程
如果要获取一个json文件,而且json文件中的内容是一个标准的json字符串,可以直接用require(‘文件地址’)得到一个js类型的数据(之前我们是用node的内置模块fs和path来拿文件)
7. express获取get请求参数
express模块获得客户端get请求时,发过来的参数(req.query)
get请求是在url地址拼接传参的:http://127.0.0.1/joke?num=10&age=10
experss中提供了一个req.query可以直接拿到后面的参数(以对象键值对的形式拿到){num:10,age:10}
const express = require('express');
const app = express();
// /index?name=jack&age=10
app.get('/index', (req, res) => {
//拿客户端请求服务端的时候,发过来的数据.
//console.log(req.query);
const {name, age} = req.query; //ES6解构赋值
console.log(req.query);
console.log(name, age);
res.send('ok');
});
app.listen(80, ()=>console.log('服务启动成功'));
express获得get请求方式的参数:req.query (得到一个对象)
8. 案例2
需求:
API: /api/joke
Method: get
参数: page: 需要第几页的笑话
size: 每一页有多少条笑话数据.
返回: {
code: 处理状态码
count: 总共有多少条笑话.
size: 每一页的笑话数量
page: 当前是第几页.
jokes: [
…笑话数据
]}
const express = require('express');
const app = express();
app.get('/api/joke', (req, res) => {
//1. 获取客户端通过URL传递过来的参数
const { page, size } = req.query;
//2. 判断参数有没有传递.
if ((!page) || (!size)) return res.status(400).send({ code: 400, msg: '参数错误' });
//3. 加载笑话库. 取到笑话库中的第page页的数据.
//3.1 加载笑话库
const jokes = require('./data/myjokes.json'); // 8880
//3.2 size代表每一页有多少条数据, page代表要去取第几页的数据.
// size = 10 page = 3
// 起始下标 结束下标. 找规律: 将现象摆出来,分析 观察
// 第1页的数据 0 9
// 第2也的数据 10 19
// 第3页的数据 20 29
// 第page页的数据 (page-1)*10 (page-1)*10+(10-1)
// (page-1)*size (page-1)*size + (size-1)
//判断传递的页码是否超出了范围.
//计算1下,笑话库的数据一共有多少页.
//笑话库一共有多少页数据.
const pageCount = Math.ceil(jokes.length / size); // 17/5 3.xxx
//判断传递的页码是否在范围之内.
if(page > pageCount) return res.status(400).send({code: 400, msg: '页码超出范围'});
//如果请求的是最后一页,
//结束的下标应该是: 数组的最后一个元素的下标.
const startIndex = (page - 1) * size;
let endIndex = startIndex + (size - 1)
if(page == pageCount){ //请求页码是最后一页
endIndex = jokes.length - 1;
}
const returnJokes = [];
for (let i = startIndex; i <= endIndex; i++) {
returnJokes.push(jokes[i]);
}
//3.3 返回数据
res.send({
code: 200,
count: jokes.length,
page,
size,
jokes: returnJokes
});
});
app.listen(80, () => console.log('服务启动成功'));
除了上述的循环push数据到空数组里面,还可以用数组的slice截取,因为已经知道了开始下标和结束下标 可以直接returnJokes =[ … jokes.slice(startIndex ,endIndex +1)].
slice(开始截取下标(包含),结束下标(不包含)),返回一个新的数组。
9. express获取post请求参数
express模块获取post请求携带的参数
- 注册中间件 app.use(express.urlencoded({extended: false}));
- req.body
/*
1. 如何接收浏览器通过post发送到服务器的数据.
req.body;
2. 如果我们要去处理浏览器通过post发送到服务器的数据.
必须要先注册1个中间件.
*/
const express = require('express');
const app = express();
//注册中间件, 只有注册了这个中间件.
//才可以通过req.body取到客户端通过post传到服务器的数据.
app.use(express.urlencoded({extended: false}));
app.post('/test', (req, res) => {
console.log(req.body);
res.send('ok');
});
app.listen(80, ()=>console.log('服务启动成功'));
10 案例3
post 请求新增一个笑话
需求: url: /api/joke/add
method post
参数: joke: 要新增的笑话.
返回{
code:
msg: ‘消息提示’
}
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
app.use(express.urlencoded({ extended: false }));
//新增笑话的接口.
app.post('/api/joke/add', (req, res) => {
//1. 获取浏览器传递到服务器的数据。
const { joke } = req.body;
//2. 判断客户端是否传递了这个参数
if (!joke) return res.status(400).send({ code: 400, msg: '参数错误' });
//3. 客户端有传递joke
// 将笑话增加到笑话库中.
//3.1 先将笑话库读取出来
const jokes = require('./data/myjokes.json');
//3.2 将笑话新增到
// 新增的笑话对象的id: 是笑话库中最后1个笑话对象的id+1
jokes.push({
id: jokes[jokes.length-1].id + 1,
content: joke
});
//3.3 写回
fs.writeFile(path.join(__dirname, 'data/myjokes.json'), JSON.stringify(jokes), 'utf-8', err=>{
if(err) return res.status(500).send({ code: 500, msg: '服务器内部发生错误' });
//写入成功
res.status(201).send({
code: 201,
msg: '创建成功'
})
});
});
app.listen(80, () => console.log('服务启动成功'));
总结
express路由注册:app.get (),app.post(),app.delete(),app.put() … 两个参数,第一个url,第二个(req,res){}回调函数
特殊的路由:app.use()
第一个参数可以省略(/)这个是可以是任何方式的请求方式都能匹配,第一个参数只需要部分匹配就可以。
用来实现静态资源托管:app.use(express.static(path.join(__dirname, ‘public’)));
app.all()
:第一个参数url必须完全匹配,请求方式可以是任意。
express的五个对象:express,application,request,response,router
express获得get请求参数:req.query ;获得post请求参数:req.body(必须先注册中间件app.use(express.urlencoded({extened:false})) )