初始化 Node 项目流程
1、先创建一个目录,然后定位到创建的目录中
2、调用 npm init -y 来初始化 package.json,它是 NodeJS 约定的用来存放项目的信息和配置等信息的文件。
3、安装 express
mkdir XXX
cd XXX
npm init -y
npm i -S experss
使用 node 框架 express
express官网:https://www.expressjs.com.cn/
一、起步看顶部的 初始化 Node 项目流程
二、hello world
let express = require("express")
// 1.创建 app
var app = express()
app.get("/",(req,res) => res.send("hello express"))
app.listen(2222,() => console.log("express-helloExpress is running at port 2222") )
三、基本路由
路由是指确定应用程序如何响应客户端对特定端点的请求,该特定端点是URI(或路径)和特定的HTTP请求方法(GET,POST等)。
每个路由可以具有一个或多个处理程序函数,这些函数在匹配该路由时执行。由定义采用以下结构:
app.METHOD(PATH,HANDLER)
app是Express 实例
METHOD是小写的HTTP请求方法(get post等等)
PATH是服务器上的路径
HANDLER是当路由匹配时执行的功能
3.1、路由:是指根据url分配到对应的处理程序
当你以 get 方法请求 / 的时候,执行对应的处理函数
app.get("/",function(req,res){
res.send(" a get request")
})
当你以 post 方法请求 / 的时候,执行对应的处理函数
app.post("/",function(req,res){
res.send("a post request")
})
当你以 put 方法请求 /user 的时候,执行对应的处理函数
app.put("/user",(req,res) => {
res.send("put: user!!!!");
})
当你以 delete 方法请求 /user 的时候,执行对应的处理函数
app.delete("/user",(req,res) => {
res.send("delete: user!!!!");
})
3.2、请求和响应
Express应用使用路由回调函数的参数:request和response对象来处理请求和响应的数据。
Express 不对Node.js 已有的特性进行二次抽象,只是在它之上扩展了web应用所需的基本功能。
- 内部使用的还是http模块
- 请求对象继承自: http.IncomingMessage
- 响应对象继承自: http.ServerResponse
3.2.1、请求对象
req对象代表HTTP请求,并具有请求查询字符串,参数,正文,HTTP标头等的属性。在本文档中,按照约定,该对象始终称为req (HTTP响应为res),但其实际名称由您正在使用的回调函数的参数确定。
属性
1、 req.baseUrl
2、 req.method
3、 req.query 等等
3.2.2、响应对象
res 对象表示Express应用在收到HTTP请求时发送的HTTP响应。
在本文档中,按照约定,该对象始终称为res(并且HTTP请求为req) ,但其实际名称由您正在使用的回调函数的参数确定。
属性
1、 res.app
2、 res.loacls
3、 res.headersSent 等等
const express = require("express");
const app = express();
app.get("/",(req,res) => {
console.log(req.baseUrl);// 请求地址
console.log(req.method);// 请求方法
console.log(req.header);// 请求头
console.log("请求参数", req.query);// 请求参数
// res.statusCode = 201;// node设置响应状态码
res.status(202);// express设置响应状态码
res.cookie("test","testValue")
res.end();// 结束响应
// res.send("Hello World!!!!");
})
app.listen("3000",() => {
console.log("Server running at http:localhost:3000/");
})
路由是指应用程序的端点(URI)如何响应客户端请求。路由的介绍官网
四、中间件
4.1、中间件的概念
Express的最大特色,也是最重要的一个设计,就是中间件。一个Express应用,就是由许许多多的中间件来完成的。
为了理解中间件,我们先来看一下我们现实生活中的自来水厂的净水流程。
在上图中,自来水厂从获取水源到净化处理交给用户,中间经历了一系列的处理环节,我们称其中的每一个处理环节就是一个中间件。这样做的目的既提高了生产效率也保证了可维护性。
在我理解Express中间件和 AOP 面向切面编程就是一个意思,就是都需要经过经过的一些步骤,不去修改自己的代码,以此来扩展或者处理一些功能。
什么是AOP?中文意思是面向切面编程,听起来感觉很模糊。先举个生产的例子。
农场的水果包装流水线一开始只有 采摘-清洗–贴标签。
为了提高销量,想加上两道工序分类和包装但又不能干扰原有的流程,同时如果没增加收益可以随时撤销新增工序。
最后在流水线中的空隙插上两个工人去处理,形成采摘–分类–清洗–包装-贴标签的新流程,而且工人可以随时撤回。
AOP (Aspect Oriented Programming)面向切面编程:
- 将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率和可维护性。
总结:就是在现有代码程序中,在程序生命周期或者横向流程中加入/减去一个或多个功能,不影响原有功能。
4.2、Express 中的中间件
在Express中,中间件就是一个可以访问请求对象、响应对象和调用next方法的一个函数。
在中间件函数中可以执行以下任何任务:
- 执行任何代码
- 修改request或者response 响应对象
- 结束请求响应周期
- 调用下一个中间件
注意:如果当前的中间件功能没有结束请求-响应周期,则必须调用next()将控制权传递给下一个中间件功能。否则,该请求将被挂起。
4.3、Express 中间件分类
在Express 中应用程序可以使用以下类型的中间件:
- 应用程序级别中间件
- 路由级别中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
4.3.1、应用程序级别中间件
不关心请求路径:
const express = require('express')
const app = express ( )
app.use((req, res, next) => {
console.log( 'Time:' , Date.now())
next()
})
限定请求路径:
app.use("/user/:id",(req, res, next) => {
console.log('request Type:' , req.method)
next()
})
限定请求方法+请求路径:
app.get("/user/:id",(req, res, next) => {
res.send("USER")
})
多个处理函数:
app.use("/user/:id",(req, res, next) => {
console.log('request URL:' , req.original)
next()
},(req, res, next) => {
console.log('request Type:' , req.method)
})
为同一个路径定义多个处理中间件:
app.get("/user/:id",(req, res, next) => {
console.log('request ID:' , req.params.id)
next()
},(req, res, next) => {
res.send("User Info")
})
app.get("/user/:id",(req, res, next) => {
res.send(req.params.id)
})
要从路由器中间件堆栈中跳过其余中间件功能,请调用next('route')将控制权传递给下一条路由。
注意:next('route')仅在使用app.METHOD()或router .METHOD()函数加载的中间件函数中有效。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id路径的GET请求。
app.get("/user/:id",(req, res, next) => {
if(req.params.id == 1){
next("route")
}else{
next()
}
},(req, res, next) => {
res.send("regular")
})
app.get("/user/:id",(req, res, next) => {
res.send("special")
})
中间件也可以在数组中声明为可重用。此示例显示了一个带有中间件子堆栈的数组,该子堆栈处理对/user/: id路径的GET请求
function logoriginalurl(req,res,next){
console.log('Request URL:' , req.originalUrl)
next()
}
function logMethod(req,res,next){
console.log('Request Type:', req.method)
next()
}
var logStuff = [logoriginalurl, logMethod]
app.get('/user/:id', logStuff, (req,res,next) => {
res.send('User Info')
})
4.3.2、路由级别中间件
路由器级中间件与应用程序级中间件的工作方式相同,只不过它绑定到的实例 express.Router()
var router = expres s.Router()
使用 router.use() 和 router.METHOD() 函数加载路由器级中间件。
以下示例代码通过使用路由器级中间件来复制上面显示的用于应用程序级中间件的中间件系统:
路由模块
const express = require("express");
1、创建路由实例
// 路由实例其实就相当于一个mini Express实例
const router = new express.Router();
配置路由
router.get("/foo",(req,res) => {
res.send("/foo get")
})
router.post("/foo",(req,res) => {
res.send("/foo post")
})
导出路由实例
module.exports = router;
4、将路由挂载集成到Express实例应用中
在 app.js 中挂载路由
// app.use(router);
给路由限定访问前缀
app.use("/todos",router);
4.3.3、错误处理中间件
以与其他中间件函数相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数(特别是使用签名(err, req, res, next))之外:
在所有的中间件之后挂载错误处理中间件
app.use((err, req, res, next)=>{
console.log("错误:", err);
res.status(500).json({
error: err.message
})
})
通常会在所有的路由之后配置处理404的内容
请求进来从上到下依次匹配
app.use((req, res, next)=>{
res.status(404).send("404 Not Found")
})
错误处理中间件始终带有四个参数。您必须提供四个参数以将其标识为错误处理中间件函数。即使不需要使用该next对象,也必须指定它以维护签名。否则,该next对象将被解释为常规中间件,并且将无法处理错误。
如果将任何内容传递给该next()函数(字符串除外'route') , Express都会将当前请求视为错误,并且将跳过所有剩余的非错误处理路由和中间件函数。
next() 往后匹配下一个中间件
next('route') 往后匹配当前中间件堆栈中的下一个
next(任意数据) 跳过所有剩余的无错误处理路由和中间件函数。
4.3.4、内置中间件
Express具有以下内置中间件函数:
- express.json() 解析 Content-Type 为 application/json 格式的请求体
- express.urlencoded() 解析 Content-Type 为 application/ x-www-form-urlencoded 格式的请求体
- express.raw() 解析 Content-Type 为 application/octet-stream 格式的请求体
- express.text() 解析 Content-Type 为 text/plain 格式的请求体
- express.static() 托管静态资源文件
4.3.5、第三方中间件
早期的Express内置了很多中间件。后来Express在4.x之后移除了这些内置中间件,官方把这些功能性中间件以包的形式单独提供出来。这样做的目的是为了保持Express本身极简灵活的特性,开发人员可以根据自己的需要去灵活的使用。
有关Express常用的第三方中间件功能的部分列表,请参阅:http://expressjs.com/en/resources/middleware.html。