官网:http://expressjs.com/
Express 是一个快速,简单,极简的 Node.js web 应用开发框架。通过它,可以轻松的构建各种 web 应用,通过中间件的方式集成了许许多多的外部插件来处理 HTTP 请求。
Wxpress可用于
接口服务
服务端渲染中间层
开发工具
准备一个空文件夹。
1、安装Express:cnpm install express
2、创建app.js
const express = require('express')
const app = express()
// req 和 res 对象来处理请求和响应的数据。
app.get('/', (req, res) => {
res.send('Hello World!')
res.end()
})
app.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000`)
})
路由是指确定应用程序如何响应客户端对特定端点的请求,该特定端点是URI(或路径)和特定的HTTP请求方法(GET,POST等)。每个路由可以具有一个或多个处理程序函数,这些函数在匹配该路由时执行。
格式:app.METHOD(PATH, HANDLER)
// get请求
app.get('/user', (req, res) => {
res.send('get')
res.end()
})
//post请求
app.post('/user', (req, res) => {
res.send('post')
res.end()
})
// put请求
app.put('/user', (req, res) => {
res.send('put')
res.end()
})
// delete请求
app.delete('/user', (req, res) => {
res.send('delete')
res.end()
})
通过案例进行了解。对JSON数据进行CRUD操作
1、app.json
{
"todos": [
{
"id": 1,
"todo": "写作业"
},
{
"todo": "吃饭",
"id": 2
}
]
}
2、封裝数据库操作 db.js
const { promisify } = require('util')
const fs = require('fs')
const path = require('path')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const dbPath = path.join(__dirname, './app.json')
exports.getDb = async () => {
const data = await readFile(dbPath, 'utf8')
return JSON.parse(data)
}
exports.setDB = async (body) => {
const currentData = await readFile(dbPath, 'utf8')
let cd = JSON.parse(currentData)
console.log(cd)
cd.todos.push({
todo: body.todo,
id: cd.todos.length
})
await writeFile(dbPath, JSON.stringify(cd, null, ' '), 'utf8')
}
3、app.js
const express = require('express')
// const fs = require('fs')
const {getDb, setDB} = require('./db')
const app = express()
// ---不配置则req.body获取不到值
// 配置解析表单JSON请求体
app.use(express.json())
// app.use(express.urlencoded()) // 来解析表单中的 url-encoded 格式的数据
//获取todo列表
app.get('/todo/list', async (req, res) => {
// console.log(req.url) // 请求链接
// console.log(req.method) // 请求方法
// console.log(req.headers) //请求头
// console.log(req.search) //请求头
const data = await getDb()
res.send(data)
res.end()
})
// 获取某一个todo
app.get('/todo/:id', async (req, res) => {
console.log(`${req.params.id}`)
const data = await getDb()
res.send(data.todos.filter(item => item.id == req.params.id)[0] || '暂无数据')
res.end()
})
// 添加todo
app.post('/todo/add', async (req, res) => {
console.log(req.body, '===========')
await setDB(req.body)
res.status(200).json({"status": 200})
res.end()
})
app.listen('3000', () => {
console.log('项目启动,端口3000')
})
在 Express 中,中间件就是一个可以访问请求对象、响应对象和调用 next 方法的一个函数。
Express 中间件和 AOP 面向切面编程就是一个意思,就是都需要经过经过的一些步骤,不去修改自己的代码,以此来扩展或者处理一些功能。
在中间件函数中可以执行以下任何任务:
例如我们想输出请求日志,请求方法、请求路径、请求时间,我们可以这样做:
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
限定请求路径:
app.use('/todo/:id', function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
限定请求方法 + 请求路径:
app.get('/user/:id', function (req, res, next) {
res.send('USER')
})
多个请求函数:
app.use('/todo/:id', function (req, res, next) {
console.log(123)
next()
}, async function (req, res) {
console.log(`${req.params.id}`)
const data = await getDb()
res.send(data.todos.filter(item => item.id == req.params.id)[0] || '暂无数据')
})
要从路由器中间件堆栈中跳过其余中间件功能,可以调用 next('route')
将控制权传递给下一条路由。
中间件也可以在数组中声明为可重用。
function time (req, res, next) {
console.log('Request time:', Date.now())
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
var logStuff = [time, logMethod]
app.get('/todo/:id', logStuff, function (req, res, next) {
res.send('todo Info')
})
使用 router.use()
和 router.METHOD()
函数加载路由器级中间件。
按照之前的代码进行修改,创建router.js
const express = require('express')
const {getDb, setDB} = require('./db')
const router = express.Router()
router.get('/', (res, req) => {
req.send("路由级别")
})
router.get('/list', async (req, res) => {
const data = await getDb()
res.send(data)
res.end()
})
router.use('/:id', function (req, res, next) {
console.log(123)
next()
}, async function (req, res) {
console.log(`${req.params.id}`)
const data = await getDb()
res.send(data.todos.filter(item => item.id == req.params.id)[0] || '暂无数据')
})
router.post('/add', async (req, res) => {
await setDB(req.body)
res.status(200).json({"status": 200})
res.end()
})
module.exports = router
app.js
简化
const router = require('./router')
const app = express()
//使用,注意:第一个参数如果存在,则证明访问route中的路由访问时需要添加第一个参数,/todo/
app.use('/todo', router)
如果将任何内容传递给该next()函数(字符串除外’route’),Express都会将当前请求视为错误,并且将跳过所有剩余的非错误处理路由和中间件函数。
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
在所有路由中间件最后添加下面中间件,没有被路由匹配到的请求都将进入这里。
app.use((req, res, next) => {
res.status(404).send('404 Not Found.')
})
例如:日志输出中间件morgan
安装方法:cnpm install morgan --save
使用:
const morgan = require('morgan')
const app = express()
app.use(morgan('dev'))