Express 基本使用
1. Express 安装
Express 的安装可以直接使用 npm 安装,首先要对需要安装的文件夹进行初始化
npm init
再输入
npm install
执行命令后,在文件夹的根目录下会出现 node_modules 文件夹,接下来进行安装 express
npm i express
在命令行中输入
express -v
如果出现版本号则安装成功
2. 运行原理
底层:http 模块,建立在 node 内置的 http 模块上,express 是对 http 模块的再次封装,下面是对比
const http = require('http')
const app = http.createServer((req,res) => {
res.writeHead(200,{"Content-Type":"text/plain"})
res.end("Hello World!")
})
app.listen(3000)
const express = require('express')
const app = express()
app.get('/',(req,res) => {
res.send('Hello World!')
})
app.listen(3000)
express 相当于在 http 模块上加了一个中间层
中间件
- 中间件(Middleware)是处理 HTTP 请求的函数。最大的特点是一个中间件处理完后,会传递给下一个中间件。App 实例在运行过程中会处理一系列中间件
- 每个中间件可以从 App 实例中接受三个参数,顺序为 request 对象,代表 HTTP 请求;response 对象,代表 HTTP 响应,next 回调函数,代表下一个中间件。每个中间件都可以对 HTTP 请求进行加工,并且决定是否调用 next 方法,将 request 请求对象传递给下一个中间件
- 最简单的中间件,不进行任何处理,只进行传递的中间件:
function uselessMiddleware(req,res,next) {
next()
}
- next() 表示进行下一个中间件操作,如果带有参数 next('Error') 表示抛出一个错误,参数就是错误文本
- 只要有一个中间件抛出错误,后面的中间件都不会执行,直到发现一个错误处理函数为止
function uselessMiddleware(req,res,next) {
next(new Error('出错了'))
}
- 错误处理函数有四个参数,顺序为 error,代表错误对象,request 对象,response 对象,next 回调函数
function useErrorMiddleware(error,req,res,next) {
res.status(500).json({
message: error.message
})
}
注意:中间件是按照顺序依次处理,所以错误处理函数必须在所有中间件最后在定义,否则可能会被跳过
3. Express 方法
Express 路由
路由表示应用程序端点 (URI) 的定义以及响应客户端请求的方式。它包含一个请求方时(methods)、路径(path)和路由匹配时的函数(callback)
app.methods(path,callback)
app.get('/',(req,res) => {
// 函数内容
})
Express 路由方法
get、post、put、head、delete、options、trace、copy、lock、mkcol、move、purge、propfind、proppatch、unlock、report、mkactivity、checkout、merge、m-search、notify、subscribe、unsubscribe、patch、search 和 connect
下面是几个基本的路由示例:
const express = require('express')
const app = express()
app.get('/home',(req,res) => {
res.send('Hello World!')
res.send(`
<html><h2>Hello World</h2></html>
`)
// 第二个 send 不生效
})
// 写完一个 send,后面所有跟路由有关的都不会执行
// 会自动响应对应的数据类型
// 使用混合使用函数数组处理时如果前面有 res.send();那么后面和路由处理相关代码都不生效
app.post('/login',(req,res) => {
res.send('登陆成功')
})
app.all("*",(req,res,next) => {
res.writeHead(200,{"Content-Type":"text/plain"})
next()
})
// 匹配 search 的所有请求方法
app.all('/search',(req, res) => {
res.send('1 秒钟为您找到相关结果约 100,000,000 个');
});
app.all("*",(req,res) => {
res.send('<h1>404 Not Found</h1>')
})
// 模式匹配
app.get("/hello/:who",(req, res) => {
res.end("Hello, " + req.params.who + ".");
});
app.listen(3000)
- 上面代码的all方法表示,所有请求都必须通过该中间件,参数中的“*”表示对所有路径有效。get方法则是只有GET动词的HTTP请求通过该中间件,它的第一个参数是请求的路径。由于get方法的回调函数没有调用next方法,所以只要有一个中间件被调用了,后面的中间件就不会再被调用了
- 除了get方法以外,Express还提供post、put、delete方法,即HTTP动词都是Express的方法
4. 路径匹配
字符串路径
// 匹配根路径的请求
app.get('/',(req, res) => {
res.send('root');
});
// 匹配 /my路径的请求
app.get('/my',(req, res) => {
res.send('my');
});
// 匹配 /what.text 路径的请求
app.get('/what.text',(req, res) => {
res.send('what.text');
});
字符串模式匹配
// 匹配 acd 和 abcd
app.get('/ab?cd',(req, res) => {
res.send('ab?cd');
});
// 匹配 abcd、abbcd、abbbcd等
app.get('/ab+cd',(req, res) => {
res.send('ab+cd');
});
// 匹配 abcd、abxcd、abRABDOMcd、ab123cd等
app.get('/ab*cd',(req, res) => {
res.send('ab*cd');
});
// 匹配 /abe 和 /abcde
app.get('/ab(cd)?e',(req, res) => {
res.send('ab(cd)?e');
});
正则表达式
// 匹配任何路径中含有 user 的路径:
app.get(/user/,(req, res) => {
res.send('/a/');
});
// 匹配 myapp、whatapp,不匹配 myappmy、whatapp what 等
app.get(/.*app$/,(req, res) => {
res.send('匹配成功')
})
5. 获取参数 req
req.query
req.query() 可以用来获取接口请求中拼接在链接"?"后边的参数,主要用于 get 请求,post 也适用
请求:
http://localhost:81/server?name=tom&friend=jerry
express 接口:
........
app.get('/server',(req,res) => {
console.log(req.query)
res.send('end')
})
........
// 输出:
{ name: 'tom', friend: 'jerry' }
req.params
req.params() 需要在 url 的后台接口提前声明需要传递的参数名
请求:
http://localhost:81/server/tom/jerry
express 接口:
........
app.get('/server/:name/:friend',(req,res) => {
console.log(req.params)
res.send('end')
})
........
// 输出:
{ name: 'tom', friend: 'jerry' }
req.body
请求:
fetch('http://127.0.0.1:81/server',{
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: {name:'tom',friend:'jerry'}
})
express 接口:
........
// 解析 json 数据
app.use(express.json())
app.post('/server',(req,res) => {
console.log(req.body)
res.send('end')
})
........
// 输出:
{ name: 'tom', friend: 'jerry' }
6. res 响应对象
方法 | 描述 |
---|---|
res.download() | 提示要下载的文件。 |
res.end() | 结束响应过程。 |
res.json() | 发送JSON响应。 |
res.jsonp() | 发送带有JSONP支持的JSON响应。 |
res.redirect() | 重定向请求。 |
res.render() | 渲染视图模板。 |
res.send() | 发送各种类型的响应。 |
res.sendFile() | 将文件作为八位字节流发送。 |
res.sendStatus() | 设置响应状态代码,并将其字符串表示形式发送为响应正文。 |
例如:
response.redirect(): 设置网络重定向
response.redirect(301,'http://www.wj.com')
response.sendFile(): 发送文件
response.sendFile('/path/hello.mp4')
response.render():渲染网页模板
app.get("/", function(request, response) {
response.render("index", { message: "Hello World" });
});
7. 中间件
中间件是一个函数,可以访问请求对象,响应对象,回调函数
功能:
- 执行代码
- 修改请求和响应对象
- 终结请求-响应循环
- 调用堆栈中的下一个中间件
Express 应用使用如下的中间件:
- 应用级中间件
- 路由级中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
应用级中间件
绑定到 app 对象,使用 app.use()
const app = express()
const indexRouter = require('./route/indexRouter');
const LoginRouter = require('./route/LoginRouter');
//应用级别(后面的路由都会执行此中间件)
app.use((req, res, next) => {
// 验证用户token过期, cookie过期
console.log('token验证');
let isValid = true;
if (isValid) {
next();
} else {
res.send('error');
}
});
//应用级别(这里不写路径默认/)
//这些use方法是每次访问都是从上往下执行
//如果是/login/a,会先找到/login开头的这个应用级中间件
//然后再进入这个中间件找/a
app.use(indexRouter);
app.use('/login', LoginRouter);
路由级中间件
express.Router() 用于创建模块化路由
└─03_模块化路由
│ app.js
│
└─router
user.js
// /router/user/user.js
const express = require('express')
const router = express.Router()
router.get('/user/:id',(req,res,next) => {
// next('route') 表示跳过当前剩下的中间件
if(req.params.id === 0) next('route')
else next()
},(req,res,next) => {
console.log('Request Type:', req.method)
})
module.exports = router
// /app.js
const express = require('express')
const user = require('./user/user')
const app = express()
app.use('/user',user)
app.listen(81)
错误处理中间件
错误中间件使用四个参数,参数依次为:err,req,res,next
app.use((err,req,res,next) => {
res.status(500).send('error')
})
内置中间件
express.static() 负责托管静态资源
// 托管 public 文件夹
app.use(express.static('public'))
// 可以通过访问 http://localhost:3000/images/kitten.jpg 获取 public/images/kitten.jpg 资源
// 指定访问路径
app.use('/public',express.static('public'))
// 可以通过访问 http://localhost:3000/public/images/kitten.jpg 获取 public/images/kitten.jpg 资源
第三方中间件
例如:cookie-parser
const cookieParser = require('cookie-parser')
app.use(cookieParser())