关于Expess
我们可以使用http内置模块来搭建Web服务器,然而我们可以通过使用框架来搭建服务器。
原生http缺点
①原生http在进行处理时,很多操作会较为复杂;
②URL的判断,Method的判断,参数处理、逻辑代码处理等,都需要我们自己处理和封装;
③原生http会将所有内容糅合在一起,会显得非常混乱
框架好处
目前在Node中比较流行的服务器框架有express、koa 等
就express而言,我们可以基于express快速、方便的开发自己的Web服务器、且可以通过一些实用的工具和中间件来拓展自己的功能;
express的安装
expres的使用过程可以有两种选择
一、通过express提供的脚手架,直接创建一个应用的骨架
二、从零搭建自己的express应用结构
通过方式一创建,如下流程:
npm install -g express-generator
创建项目:
express express-demo
项目目录:
通过安装依赖,我们可以将程序跑起来
npm install
node bin/www
通过方式二创建,如下流程:
初始化一个新的项目:
npm init -y
express安装
npm install express
创建第一个express程序
const express = require('express');
//创建服务器
const app = express();
// /home的get请求处理
app.get("/home", (req, res) => {
res.end("Hello Home");
})
// /login的post请求处理
app.post("/login", (req, res) => {
res.end("Hello Login");
})
app.listen(8000, () => {
console.log("服务器启动成功~");
})
可以清楚的看到,可以非常方便的将请求进行分离,这样的方式非常利于我们进行维护、拓展。
请求和响应
请求的路径中如果有一些参数,可以使用如 /users/:userId;的形式
在request对象中要获取可以通过req.params.userId;
返回数据,我们可以使用json;
res.json(数据)
还有其他的方式,具体可见官方文档
https://www.expressjs.com.cn/guide/routing.html
const express = require('express');
const app = express();
app.get('/users/:userId', (req, res, next) => {
console.log(req.params.userId);
res.json({username: "Impair", level: 99});
});
app.listen(8000, () => {
console.log("静态服务器启动成功~");
})
关于中间件
Express是一个路由和中间件组成的Web框架,其应用程序本质上是一系列中间件函数的调用;
而中间件的本质就是一个回调函数,该回调函数会接收三个参数①请求对象(request对象)②响应对象(response对象)③next函数(在express中定义的用于执行下一个中间件的函数);
中间件可以执行任何代码,更改请求(request)和响应(response)对象、结束请求-相应周期(返回数据)、调用栈中的下一个中间件
如果当前的中间件没有执行完自己的功能或没有结束请求-响应周期,则必须调用next() 将控制权传递给下一个中间件功能,否则请求将会被挂起。
应用中间件
如何将一个中间件应用在我们的应用程序上
express主要提供了有两种方式:app/router.use 和 app/router.methods;
可以是app,也可以是router;
methods指的是常用的请求方式,因为methods的方式本质是use的特殊情况;
①最普通的中间件
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log("common middleware 01");
next();
})
app.use((req, res, next) => {
console.log("common middleware 02");
res.end("Hello Common Middleware~");
})
app.listen(8000, () => {
console.log("中间件服务器启动成功~");
})
在匹配上的情况下,中间件会按照注册的顺序执行
②同时,use方法可以用来匹配一个明确的路径。
app.use('/home', (req, res, next) => {
console.log("home middleware 01");
next();
});
app.use('/home', (req, res, next) => {
console.log("home middleware 02");
next();
res.end("Hello Home middleware");
});
app.use((req, res, next) => {
console.log("common middleware");
});
③path和method同时使用匹配中间件
app.get('/home', (req, res, next) => {
console.log("home get middleware");
next();
})
app.post('/login', (req, res, next) => {
console.log("login post middleware");
next();
});
app.use((req, res, next) => {
console.log("common middleware");
});
④也可以在一个method中使用多个中间件
const homeMiddleware1 = (req, res, next) => {
console.log('home middleware 01');
next();
}
const homeMiddleware2 = (req, res, next) => {
console.log('home middleware 02');
next();
}
const homeHandle = (req, res, next) => {
res.end("Hello Home~");
}
app.get('/home', homeMiddleware1, homeMiddleware2, homeHandle);
应用其他中间件
express中有内置一些帮助我们完成对express解析的中间件;
registry仓库中也有很多可以帮助开发的中间件
request解析中间件
在客户端发送post请求时,会将数据放到body中
①客户端可以通过json的方式传递②也可以通过from表单的方式传递。
用json传递给服务器body:
不进行解析时:
app.post('/login', (req, res, next) => {
req.on('data', (data) => {
console.log(data.toString());
})
req.on('end', () => {
res.end("登录成功~");
});
});
自己编写中间件来解析JSON时:
app.use((req, res, next) => {
if (req.headers['content-type'] === 'application/json') {
req.on('data', (data) => {
const userInfo = JSON.parse(data.toString());
req.body = userInfo;
})
req.on('end', () => {
next();
})
} else {
next();
}
})
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("登录成功~");
});
以上操作 也可以使用express内置的中间件或者使用body-parser来完成:
app.use(express.json());
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("登录成功~");
});
使用express子嗲的urlencoded函数作为中间件时:
传入的extended表示使用哪种解析方式:
true---使用qs第三方模块 false---使用querystring内置模块
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("登录成功~");
});
日志记录中间件
如果希望将请求日志记录下来,可以使用express官网提供的第三方库morgan
安装morgan
npm install morgan
将其作为中间件使用
const loggerWriter = fs.createWriteStream('./log/access.log', {
flags: 'a+'
})
app.use(morgan('combined', {stream: loggerWriter}));
请求与响应
客户端传递到服务器的参数方法主要有五种:
方式一:通过get请求中的URL的params;
方式二:通过get请求中的URL的query;
方式三:通过post请求的body的json格式;
方式四:通过post请求的body的x-www-form-urlencoded格式
方式五:通过post请求的form-data格式;
请求解析
方式一:params
app.use('/login/:id/:name', (req, res, next) => {
console.log(req.params);
res.json("请求成功~");
})
方式二:query
app.use('/login', (req, res, next) => {
console.log(req.query);
res.json("请求成功~");
})
响应方式
end方法
类似http的response.end方法
res.end("Hello World");
json方法
json方法中可以传入很多的类型:object、array、string、boolean、number、null等,它们会被转换成json格式返回;
res.json({name: "Impair", age: 16});
status方法
用于设置状态码:
res.status(200);