用前端的语言写后端——Node.js之Express

Express

Express 是一种流行的模型视图控制器(MVC)Node.js框架,具有快速、极简和灵活的优点,为Web和移动应用程序开发提供了强大的功能集合。

最受欢迎的Node.js框架!

文章目录

  • Express
    • 安装Express
    • HelloWorld
    • 路由
    • 中间件
      • 全局中间件
      • 应用中间件
      • 开放跨域请求
      • 几种常用的Express内置中间件函数
        • 1. JSON格式数据中间件函数
        • 2. 静态文件中间件函数
        • 3. 路由中间件函数
    • 文件上传与下载
      • 文件上传
      • 文件下载
    • 常用API
      • Application
      • Request
      • Response
      • Response

安装Express

  1. 安装Node.js(你肯定已经安装好了Node.js,这点我们无需多言)

  2. 为你的应用创建一个目录,进入此目录并以此目录为你当前的工作目录:

    $ mkdir myapp
    $ cd myapp
    
  3. 通过npm init为你的应用创建一个package.json文件

  4. 接下来终端会让你输入一些package.json中的几个参数,推荐按回车默认即可,但有一个需要注意:

    entry point: (index.js)
    

    这个表示当前应用的入口文件,你可以根据自己的个人习惯进行适当的修改(例如:app.js

  5. myapp目录下安装Express并将其保存至依赖列表中:

    $ npm install express --save
    
  6. (不常用)如果临时安装express,不需要将其添加至依赖列表中:

    $ npm install express --no-save
    

HelloWorld

app.js文件中编写如下代码:

const express = require('express')
const app = express()
const port = 8080

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

执行命令启动Web服务器:

$ node app.js

终端输出Example app listening on port 8080即为开启成功

打开浏览器访问localhost:8080,浏览器主页面显示Hello World!

那么恭喜你!Express 在向你招手!

路由

路由指的是确定应用程序如何响应客户机对特定端点的请求,该端点是URI(或路径)和特定的HTTP请求方法。

路由定义采取以下结构:

app.METHOD(PATH, HANDLER)
  • app是 的一个实例express
  • METHOD是HTTP 请求方法,小写。
  • PATH是服务器上的路径。
  • HANDLER是路由匹配时执行的函数。

让我们举一个小例子(默认你已经引用了express方法):

app.get('/', () => {
    res.send('Hello World!')
})

中间件

中间件函数是可以访问请求对象 ( req)、响应对象( res) 以及next应用程序请求-响应周期中的函数的函数。该next函数是 Express 路由器中的一个函数,当被调用时,它会执行当前中间件之后的中间件。

中间件功能可以执行以下任务:

  • 执行任意代码。
  • 更改请求和响应对象。
  • 结束请求-响应周期。
  • 调用堆栈中的下一个中间件。

从 Express 5 开始,返回 Promise 的中间件函数将next(value)在拒绝或抛出错误时调用。next将使用拒绝的值或抛出的错误来调用。

全局中间件

全局中间件是指在应用程序中的所有路由中都会执行的中间件函数。这些中间件函数可以处理请求对象 (req) 和响应对象 (res),以及调用 next() 函数将控制权传递给下一个中间件或路由处理程序。

全局中间件通常通过 app.use() 方法添加到 Express 应用程序中。例如:

const express = require('express')
const app = express()

// 全局中间件示例1
app.use((req, res, next) => {
  console.log('This is a global middleware')
  //给req添加一个属性
  req.requestTime = Date.now()
  next()
})

// 路由处理程序
app.get('/', (req, res) => {
  res.send('Hello World!')
})

无论用户请求的是什么路径,都会首先执行该中间件函数。

应用中间件

应用级中间件可以选择性地应用于特定的路由或路由组。

const express = require('express')
const app = express()

// 应用级中间件示例
const authenticate = function(req, res, next) {
    // 检查用户是否经过身份验证
    const isAuthenticated = true; // 这里应该是根据你的实际逻辑来判断用户是否已经身份验证
    if (isAuthenticated) {
        // 用户已经通过身份验证,继续下一个中间件或路由处理程序
        next()
    } else {
        // 用户未通过身份验证,返回未经授权的消息
        res.status(401).send('Unauthorized')
    }
}

// 将中间件应用于特定路由
app.get('/secured', authenticate, (req, res) => {
    res.send('This is a secured route')
})

// 不受中间件保护的路由
app.get('/public', (req, res) => {
    res.send('This is a public route')
})

在这个示例中,authenticate 函数是一个应用级中间件,它会检查用户是否经过身份验证。在 /secured 路由上,通过使用 authenticate 中间件,我们确保只有通过身份验证的用户才能访问该路由。

而对于 /public 路由,没有任何中间件,因此对所有用户都是公开可访问的。

开放跨域请求

cv在你的程序即可,没什么好解释的哈哈

app.use(function (req, res, next) {
  //设置允许跨域的域名,*代表允许任意域名跨域
  res.header("Access-Control-Allow-Origin", "*")
  //允许的header类型
  res.header("Access-Control-Allow-Headers", "content-type")
  //跨域允许的请求方式
  res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS")
  if (req.method == "OPTIONS") res.sendStatus(200) //让options尝试请求快速结束
  else next()
})

几种常用的Express内置中间件函数

1. JSON格式数据中间件函数

express.json

通常情况下,当客户端发送 JSON 格式的数据到 Express 服务器时,我们需要使用 express.json() 中间件来解析这些数据。例如:

const express = require('express')
const app = express()

// 使用 express.json() 中间件来解析 JSON 数据
app.use(express.json())

// POST 请求示例
app.post('/api/data', (req, res) => {
  console.log(req.body); // 访问 JSON 数据
  // 处理请求
})
2. 静态文件中间件函数

express.static()

通过使用这个中间件,你可以将指定目录下的静态文件(如图像文件、JavaScript 文件、文本文件等)映射到一个 URL 路径上,使得客户端可以直接访问这些静态文件。例如:

const express = require('express')
const app = express()
// 通常和path一起使用比较方便
const path = require('path')

// 通过path的方法获取到存放静态资源的相对路径
app.use(express.static(path.join(__dirname, 'public')))
3. 路由中间件函数

(注意:与上面所述路由含义不同,要加强辨析)

express.Router()

  • 使用 express.Router() 可以创建一个新的路由对象,并向其添加路由处理程序。然后,你可以将这个路由对象挂载到你的 Express 应用程序的特定路径上,使得这些路由处理程序只会对与该路径匹配的请求进行处理。

  • 它允许你将路由处理程序组织成模块化的方式,以便更好地管理和维护你的 Express 应用程序。

首先我们需要创建一个路由模块,例如:

// routers/testRouter.js
const express = require("express")
let router = express.Router()

// 定义路由处理程序
router.get('/', (req, res) => {
  res.send('Test')
})

// 导出路由对象
module.exports = router

接下来,我们可以将这个路由模块挂载到 Express 应用程序中:

// app.js(初始入口)
const express = require('express')
const app = express()

// 导入用户路由模块
const userRouter = require('./routes/user')

// 将用户路由模块挂载到指定路径上
app.use('/test', userRouter)

当客户端发出 /test/test/config 这些路径的请求时,Express 将会调用 testRouter 中定义的路由处理程序来处理这些请求。

文件上传与下载

文件上传

我们需要使用 Node.js 中间件:multer,附上github的官方multer中文文档。

我下面将分享一些常用的方法。

  1. 安装multer:
$ npm install multer
  1. 使用指定临时存储目录,例如:
const express = require('express')
const multer = require('multer')

const upload = multer({
  // 上传临时存放在此目录
  dest: "./public/uploads/temp",
})
//所有接口都允许有上传功能
app.use(upload.any())

(说明一下为什么指定临时存储目录:当上传文件时,Multer 将会把文件暂存到指定的临时目录中,然后你可以在路由处理程序中获取到文件并进行相应的处理。这种方式适合对文件的存储方式没有特别要求的情况,简单方便。)

  1. 上传接口,例如:
app.post("/upload", (req, res) => {
  //检测是否有文件
  if (!req.files) {
    res.send({
      code: 400,
      msg: "上传文件不能为空",
    })
    return
  }
  
  //保存文件
  let files = req.files
  let ret_files = []
  for (let file of files) {
    //获取名字后缀
    let file_ext = file.originalname.substring(file.originalname.lastIndexOf(".") + 1)
    //使用时间戳作为文件名字
    let file_name = new Date().getTime() + "." + file_ext
    // 移动文件并且修改文件名字
    fs.renameSync(
      // 因为multer生成临时文件的问题,file.filename会是乱码
      process.cwd() + "/public/upload/temp/" + file.filename,
      process.cwd() + "/public/upload/" + file_name
    )
    // 将上传成功的文件路径添加到返回数组中
    ret_files.push("/public/upload/" + file_name)
  }

  // 返回上传成功的响应
  res.send({
    code: 200,
    msg: "ok",
    data: ret_files,
  })
}

上述let files = req.files的文件信息包括:

  • fieldname:字段名,即表单中文件上传字段的名称。
  • originalname:原始文件名,即客户端上传的文件的原始名称。
  • encoding:文件编码,即文件的编码方式。
  • mimetype:文件的 MIME 类型,即文件的媒体类型。
  • destination:文件的存储目录,即文件上传后存储的目录路径。
  • filename:文件名,即文件在存储目录中的名称。
  • path:文件路径,即文件在服务器中的绝对路径。
  • size:文件大小,即文件的字节数。

补充multer使用自定义存储方式的场景,例如:

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

// 配置 Multer 的存储引擎
const storage = multer.diskStorage({
  // 设置上传文件的存储目录
  destination: function (req, file, cb) {
    cb(null, './public/uploads/') // 回调函数指定存储目录为 'uploads/'
  },
  // 设置上传文件的文件名
  filename: function (req, file, cb) {
    cb(null, file.originalname) // 回调函数指定文件名为上传文件的原始文件名
  }
})

通常,一般的网页应用,只需要使用使用指定临时存储目录!

文件下载

使用res.download()方法即可,例如:

//下载文件
router.get("/download", async (req, res) => {
  // 从请求的查询参数中获取要下载的文件名
  let file_name = req.query.file_name
  // 构建要下载文件的完整路径
  let file_path = process.cwd() + "/public/upload/" + file_name
  res.download(file_path)
})

常用API

Application

老规矩,先附上Express官方的API汇总文档

  1. app.all(path, callback [, callback …])

    此方法类似于标准app.METHOD()方法,只不过它匹配所有 HTTP 动词。

    举个小例子:

    app.all('/secret', (req, res, next) => {
      console.log('HELLO WORLD!')
      next()
    })
    

    无论你使用哪种HTTP请求,控制台总会输出HELLO WORLD!

  2. app.use([path,] callback [, callback…])

    在指定路径挂载指定的一个或多个中间件函数:当请求路径的基址匹配时,执行中间件函数path

    由于path默认为“/”,因此对于应用程序的每个请求都将执行没有路径安装的中间件。

    例如,这个中间件函数将针对应用程序的每个请求执行:

    app.use((req, res, next) => {
      console.log('Time: %d', Date.now())
      next()
    })
    

    再例如,这个中间件函数将匹配/abcd开头的路径:

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

    路径示例:

    路径 匹配路径
    '/abcd' /abcd
    '/ab(c?)d' /abcd、/abd
    `//abc /xyz/`
    ['/abcd', '/xyz'] /abcd、/xyz
  3. app.delete(path, callback [, callback …])

  4. app.get(path, callback [, callback …])

  5. app.post(path, callback [, callback …])

  6. app.put(path, callback [, callback …])

Request

  1. req.baseUrl 获取基础路径
  2. req.body 获取body里面的内容
  3. req.hostname 域名
  4. req.ip 访问ip
  5. req.method 请求的方法
  6. req.originalUrl 原始路径
  7. req.params 获取属性
  8. req.path 获取路径
  9. req.protocol 请求协议
  10. req.query 获取query属性
  11. req.route 当前路由信息

Response

  1. res.download(path [, filename] [, options] [, fn]) 下载文件

  2. res.end([data] [, encoding]) 结束响应

  3. res.get(field) 获取相应HTTP头

  4. res.redirect([status,] path) 重定向

  5. res.status(code) 设置响应的HTTP状态

  6. req.baseUrl 获取基础路径

  7. req.body 获取body里面的内容

  8. req.hostname 域名

  9. req.ip 访问ip

  10. req.method 请求的方法

  11. req.originalUrl 原始路径

  12. req.params 获取属性

  13. req.path 获取路径

  14. req.protocol 请求协议

  15. req.query 获取query属性

  16. req.route 当前路由信息

Response

  1. res.download(path [, filename] [, options] [, fn]) 下载文件
  2. res.end([data] [, encoding]) 结束响应
  3. res.get(field) 获取相应HTTP头
  4. res.redirect([status,] path) 重定向
  5. res.status(code) 设置响应的HTTP状态

好啦!如果你觉得我的文章对你有帮助,请给我点个赞吧!非常感谢你能看到这里!

你可能感兴趣的:(前端,前端,node.js,express)