Node.js express framework learning experience

Node.js: Subversion of traditional server-side development

Node.js, the JavaScript runtime built on top of Chrome's V8 engine, takes a completely different development model. Node.js uses event-driven and non-blocking I/O to process requests, and achieves efficient concurrent processing through single-threaded and asynchronous mechanisms. This means that in Node.js, one thread can handle thousands of concurrent connections, greatly improving the performance and scalability of the server.

First, understand the Web framework

image.png

2. Express installation

image.png

3. Basic usage of Express

image.png

const express = require('express')

// 1.创建express的服务器
const app = express()

// 客户端访问URL: /login和/home
app.post('/login', (req, res) => {
    
    
  // 处理login请求
  res.end('登录成功, 欢迎回来~')
})

app.get('/home', (req, res) => {
    
    
  res.end('首页的轮播图/推荐数据列表~')
})

// 2.启动服务器, 并且监听端口
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4. Understanding middleware

image.png

image.png

4.1. Register ordinary middleware

image.png

const express = require('express')

const app = express()

// 总结: 当express接收到客户端发送的网络请求时, 在所有中间中开始进行匹配
// 当匹配到第一个符合要求的中间件时, 那么就会执行这个中间件
// 后续的中间件是否会执行呢? 取决于上一个中间件有没有执行next

// 通过use方法注册的中间件是最普通的/简单的中间件
// 通过use注册的中间件, 无论是什么请求方式都可以匹配上
// login/get
// login/post
// abc/patch
app.use((req, res, next) => {
    
    
  console.log('normal middleware 01')
  // res.end('返回结果了, 不要等了')
  next()
})

app.use((req, res, next) => {
    
    
  console.log('normal middleware 02')
})


// 开启服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.2. Register path matching middleware

const express = require('express')

const app = express()

// 注册普通的中间件
// app.use((req, res, next) => {
    
    
//   console.log('match normal middleware')
//   res.end('--------')
// })

// 注册路径匹配的中间件
// 路径匹配的中间件是不会对请求方式(method)进行限制
app.use('/home', (req, res, next) => {
    
    
  console.log('match /home middleware')
  res.end('home data')
})

app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.3. Middleware for method and path matching

const express = require('express')

const app = express()


// 注册中间件: 对path/method都有限制
// app.method(path, middleware)
app.get('/home', (req, res, next) => {
    
    
  console.log('match /home get method middleware')
  res.end('home data')
})


app.post('/users', (req, res, next) => {
    
    
  console.log('match /users post method middleware')
  res.end('create user success')
})


app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.4. Match multiple middleware

const express = require('express')

const app = express()

// app.get(路径, 中间件1, 中间件2, 中间件3)
app.get('/home', (req, res, next) => {
    
    
  console.log('match /home get middleware01')
  next()
}, (req, res, next) => {
    
    
  console.log('match /home get middleware02')
  next()
}, (req, res, next) => {
    
    
  console.log('match /home get middleware03')
  next()
}, (req, res, next) => {
    
    
  console.log('match /home get middleware04')
})

app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.5, middleware case 1

Match ordinary middleware first, and then continue to match downwards with next()

const express = require('express')

const app = express()

// 1.注册两个普通的中间件
app.use((req, res, next) => {
    
    
  console.log('normal middleware01')
  next()
})

app.use((req, res, next) => {
    
    
  console.log('normal middleware02')
  next()
})


// 2.注册路径path/method的中间件
app.get('/home', (req, res, next) => {
    
    
  console.log('/home get middleware01')
  next()
}, (req, res, next) => {
    
    
  console.log('/home get middleware02')
  next()
})

app.post('/login', (req, res, next) => {
    
    
  console.log('/login post middleware')
  next()
})


// 3.注册普通的中间件
app.use((req, res, next) => {
    
    
  console.log('normal middleware03')
  next()
})

app.use((req, res, next) => {
    
    
  console.log('normal middleware04')
})


app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.6, middleware case two

const express = require('express')

const app = express()

// 注册两个实际请求的中间件
// 案例一: 用户登录的请求处理 /login post => username/password
app.post('/login', (req, res, next) => {
    
    
  // 1.获取本次请求过程中传递过来的json数据
  let isLogin = false
  req.on('data', (data) => {
    
    
    const dataString = data.toString()
    const dataInfo = JSON.parse(dataString)
    if (dataInfo.username === 'coderwhy' && dataInfo.password === '123456') {
    
    
      isLogin = true
    }
  })

  req.on('end', () => {
    
    
    if (isLogin) {
    
    
      res.end('登录成功, 欢迎回来~')
    } else {
    
    
      res.end('登录失败, 请检测账号和密码是否正确~')
    }
  })
})

// 案例二: 注册用户的请求处理 /register post => username/password
app.post('/register', (req, res, next) => {
    
    
    // 1.获取本次请求过程中传递过来的json数据
    let isRegister = false
    req.on('data', (data) => {
    
    
      const dataString = data.toString()
      const dataInfo = JSON.parse(dataString)
      // 查询数据库中该用户是否已经注册过
      isRegister = false
    })

    req.on('end', () => {
    
    
      if (isRegister) {
    
    
        res.end('注册成功, 开始你的旅程~')
      } else {
    
    
        res.end('注册失败, 您输入的用户名被注册~')
      }
    })
})

app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.7, middleware case 2 (refactoring)

//下面这个代码就相当于app.use(express.json())的原理,以后开发直接用app.use(express.json())

app.use((req, res, next) => {
    
    
  if (req.headers['content-type'] === 'application/json') {
    
    
    req.on('data', (data) => {
    
    
      const jsonInfo = JSON.parse(data.toString())
      req.body = jsonInfo
    })

    req.on('end', () => {
    
    
      next()
    })
  } else {
    
    
    next()
  }
})
const express = require('express')

const app = express()


// app.use((req, res, next) => {
    
    
//   if (req.headers['content-type'] === 'application/json') {
    
    
//     req.on('data', (data) => {
    
    
//       const jsonInfo = JSON.parse(data.toString())
//       req.body = jsonInfo
//     })

//     req.on('end', () => {
    
    
//       next()
//     })
//   } else {
    
    
//     next()
//   }
// })

// 直接使用express提供给我们的中间件
app.use(express.json())

// 注册两个实际请求的中间件
// 案例一: 用户登录的请求处理 /login post => username/password
app.post('/login', (req, res, next) => {
    
    
  console.log(req.body)
})

// 案例二: 注册用户的请求处理 /register post => username/password
app.post('/register', (req, res, next) => {
    
    
  console.log(req.body)
})

app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

image.png

image.png

4.8, middleware application - urlencoded analysis

const express = require('express')

// 创建app对象
const app = express()

// 应用一些中间件
app.use(express.json()) // 解析客户端传递过来的json
// 解析传递过来urlencoded的时候, 默认使用的node内置querystring模块
// { extended: true }: 不再使用内置的querystring, 而是使用qs第三方库
app.use(express.urlencoded({
    
     extended: true })) // 解析客户端传递过来的urlencoded

// 编写中间件
app.post('/login', (req, res, next) => {
    
    
  console.log(req.body)
  res.end('登录成功, 欢迎回来~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

4.9. Application middleware – third-party middleware

image.png

//记录日志
const fs = require('fs')
const express = require('express')
const morgan = require('morgan')

// 创建app对象
const app = express()

// 应用第三方中间件
const writeStream = fs.createWriteStream('./logs/access.log')
app.use(morgan('combined', {
    
     stream: writeStream }))

// 编写中间件
app.post('/login', (req, res, next) => {
    
    
  res.end('登录成功, 欢迎回来~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

single file upload

const express = require('express')
const multer = require('multer')

// 创建app对象
const app = express()

// 应用一个express编写第三方的中间件
const upload = multer({
    
    
  dest: './uploads'
})

// 编写中间件
// 上传单文件: singer方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {
    
    
  console.log(req.file)
  res.end('文件上传成功~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})



4.9, middleware application - multiple file upload

image.png

const express = require('express')
const multer = require('multer')

// 创建app对象
const app = express()

// 应用一个express编写第三方的中间件
const upload = multer({
    
    
  // dest: './uploads'
  storage: multer.diskStorage({
    
    
    destination(req, file, callback) {
    
    
      callback(null, './uploads')
    },
    // 自定义文件名
    filename(req, file, callback) {
    
    
      callback(null, Date.now() + '_' + file.originalname)
    }
  })
})

// 编写中间件
// 上传单文件: single方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {
    
    
  console.log(req.file)
  res.end('文件上传成功~')
})

// 上传多文件: 
app.post('/photos', upload.array('photos'), (req, res, next) => {
    
    
  console.log(req.files)
  res.end('上传多张照片成功~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.0, middleware application-formdata analysis

image.png

const express = require('express')
const multer = require('multer')

// 创建app对象
const app = express()

// express内置的插件
app.use(express.json())
app.use(express.urlencoded({
    
     extended: true }))

// 编写中间件
const formdata = multer()

app.post('/login', formdata.any(), (req, res, next) => {
    
    
  console.log(req.body)
  res.end('登录成功, 欢迎回来~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.1, client parameter analysis

image.png

image.png

const express = require('express')

// 创建app对象
const app = express()


// 编写中间件
// 1.解析queryString
app.get('/home/list', (req, res, next) => {
    
    
  // offset/size
  const queryInfo = req.query
  console.log(queryInfo)

  res.end('data list数据')
})

// 2.解析params参数
app.get('/users/:id', (req, res, next) => {
    
    
  const id = req.params.id

  res.end(`获取到${
      
      id}的数据~`)
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.2. Server response data type

image.png

const express = require('express')

// 创建app对象
const app = express()


// 编写中间件
app.post('/login', (req, res, next) => {
    
    
  // 1.res.end方法(比较少)
  // res.end('登录成功, 欢迎回来~')

  // 2.res.json方法(最多)
  // res.json({
    
    
  //   code: 200,
  //   message: '欢迎回来~',
  //   list: [
  //     { name: 'iPhone', price: 111 },
  //     { name: 'iPad', price: 111 },
  //     { name: 'iMac', price: 111 },
  //     { name: 'Mac', price: 111 },
  //   ]
  // })

  // 3.res.status方法: 设置http状态码
  res.status(201)
  res.json('创建用户成功~')
})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.3, Express routing

image.png

router/userRouter.js


const express = require('express')

// 1.创建路由对象
const userRouter = express.Router()

// 2.定义路由对象中的映射接口
userRouter.get('/', (req, res, next) => {
    
    
  res.json('用户列表数据')
})
userRouter.get('/:id', (req, res, next) => {
    
    
  const id = req.params.id
  res.json('某一个用户的数据:' + id)
})
userRouter.post('/', (req, res, next) => {
    
    
  res.json('创建用户成功')
})
userRouter.delete('/:id', (req, res, next) => {
    
    
  const id = req.params.id
  res.json('删除某一个用户的数据:' + id)
})
userRouter.patch('/:id', (req, res, next) => {
    
    
  const id = req.params.id
  res.json('修改某一个用户的数据:' + id)
})

// 3.将路由导出
module.exports = userRouter

const express = require('express')
const userRouter = require('./router/userRouter')

// 创建app对象
const app = express()


// 编写中间件
app.post('/login', (req, res, next) => {
    
    

})

app.get('/home', (req, res, next) => {
    
    

})

/** 用户的接口 */
// 1.将用户的接口直接定义在app中
// app.get('/users', (req, res, next) => {})
// app.get('/users/:id', (req, res, next) => {})
// app.post('/users', (req, res, next) => {})
// app.delete('/users/:id', (req, res, next) => {})
// app.patch('/users/:id', (req, res, next) => {})

// 2.将用户的接口定义在单独的路由对象中
// const userRouter = express.Router()
// userRouter.get('/', (req, res, next) => {
    
    
//   res.json('用户列表数据')
// })
// userRouter.get('/:id', (req, res, next) => {
    
    
//   const id = req.params.id
//   res.json('某一个用户的数据:' + id)
// })
// userRouter.post('/', (req, res, next) => {
    
    
//   res.json('创建用户成功')
// })
// userRouter.delete('/:id', (req, res, next) => {
    
    
//   const id = req.params.id
//   res.json('删除某一个用户的数据:' + id)
// })
// userRouter.patch('/:id', (req, res, next) => {
    
    
//   const id = req.params.id
//   res.json('修改某一个用户的数据:' + id)
// })

// 让路由生效
app.use('/users', userRouter)

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.4, ​​express static resource server

const express = require('express')

// 创建app对象
const app = express()

// 内置的中间件: 直接将一个文件夹作为静态资源
app.use(express.static('./uploads'))
app.use(express.static('./build'))

// 编写中间件
app.post('/login', (req, res, next) => {
    
    

})

// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

5.5. Error handling scheme in express

const express = require('express')

// 创建app对象
const app = express()

app.use(express.json())

// 编写中间件
app.post('/login', (req, res, next) => {
    
    
  // 1.获取登录传入的用户名和密码
  const {
    
     username, password } = req.body

  // 2.对用户名和密码进行判断
  if (!username || !password) {
    
    
    next(-1001)
  } else if (username !== 'coderwhy' || password !== '123456') {
    
    
    next(-1002)
  } else {
    
    
    res.json({
    
    
      code: 0,
      message: '登录成功, 欢迎回来~',
      token: '323dfafadfa3222'
    })
  }
})


// 错误处理的中间件
app.use((errCode, req, res, next) => {
    
    
  const code = errCode
  let message = '未知的错误信息'

  switch(code) {
    
    
    case -1001:
      message = '没有输入用户名和密码'
      break
    case -1002:
      message = '输入用户名或密码错误'
      break
  }

  res.json({
    
     code, message })
})


// 启动服务器
app.listen(9000, () => {
    
    
  console.log('express服务器启动成功~')
})

Guess you like

Origin blog.csdn.net/weixin_45506717/article/details/132036776