【Node.js工程师养成计划】之express框架

一、Express

官网:http://www.expressjs.com.cn

express 是一个基于内置核心 http 模块的,一个第三方的包,专注于 web 服务器的构建。

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。

  • 定义了路由表用于执行不同的 HTTP 请求动作。

  • 可以通过向模板传递参数来动态渲染 HTML 页面。

Express适合做什么

  • 传统web网站
  • API接口服务器
  • 服务端渲染中间层
  • 开发辅助工具
  • 自定义集成框架

二、Express项目构建

npm init -y
npm install express --save
npx express-generator

使用 npx express-generator 命令可以自动创建一个包含所有基本目录和文件的 Express.js 应用模板,这样开发者就可以直接开始编写业务代码,而不需要从零开始设置项目结构。
这个生成的项目通常包括以下部分:

  • bin 目录:存放可执行文件,包括启动应用的脚本。
  • public 目录:用于存放静态文件,如图片、JavaScript 和 CSS 文件。
  • routes 目录:存放路由文件,定义应用的路由逻辑。
  • views 目录:存放视图文件,通常是模板文件,用于生成 HTML 响应。
  • app.js:应用的主入口文件,配置中间件、路由等。
    在这里插入图片描述

三、express框架的基本使用

// 引入express
const express = require('express')
// 创建应用对象
const app = express();

app.get('/', function(req, res){
  // 响应消息内容
  res.send('全体起立!')
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

在这里插入图片描述
request 和 response 对象的具体介绍:

Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。常见属性有:

req.app:当callback为外部文件时,用req.app访问express的实例
req.baseUrl:获取路由当前安装的URL路径
req.body / req.cookies:获得「请求主体」/ Cookies
req.fresh / req.stale:判断请求是否还「新鲜」
req.hostname / req.ip:获取主机名和IP地址
req.originalUrl:获取原始请求URL
req.params:获取路由的parameters
req.path:获取请求路径
req.protocol:获取协议类型
req.query:获取URL的查询参数串
req.route:获取当前匹配的路由
req.subdomains:获取子域名
req.accepts():检查可接受的请求的文档类型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
req.get():获取指定的HTTP请求头
req.is():判断请求头Content-Type的MIME类型

Response 对象 - response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。常见属性有:

res.app:同req.app一样
res.append():追加指定HTTP头
res.set()在res.append()后将重置之前设置的头
res.cookie(name,value [,option]):设置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():传送指定路径的文件
res.get():返回指定的HTTP头
res.json():传送JSON响应
res.jsonp():传送JSONP响应
res.location():只设置响应的Location HTTP头,不设置状态码或者close response
res.redirect():设置响应的Location HTTP头,并且设置状态码302
res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
res.send():传送HTTP响应
res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
res.set():设置HTTP头,传入object可以一次设置多个头
res.status():设置HTTP状态码
res.type():设置Content-Type的MIME类型

四、Express管理用户数据信息

项目目录:
在这里插入图片描述
db.json

{
  "users": [
    {
      "id": 1,
      "username": "Monica",
      "age": "22"
    },
    {
      "id": 2,
      "username": "Alen",
      "age": "26"
    }
  ],
  "video": []
}
// 引入express
const express = require('express')
const fs = require('fs');
const { json } = require('stream/consumers');
// 创建应用对象
const app = express();

app.get('/', function(req, res){
  fs.readFile('./db.json', 'utf-8',(err, data) => {
    if (!err) {
      const back = JSON.parse(data)
      res.send(back.users)
    } else {
      res.status(500).json({err})
    }
  })
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

在这里插入图片描述
在这里插入图片描述
可以使用apifox去管理接口
在这里插入图片描述
解决回调地狱问题:

// 引入express
const express = require('express')
const fs = require('fs');
const { promisify } = require('util')
const readFile = promisify(fs.readFile)

// 创建应用对象
const app = express();

app.get('/', async function(req, res){
  try {
    let back = await readFile('./db.json', 'utf-8')
    res.send(JSON.parse(back))
  } catch (err) {
    res.status(500).json({err})
  }
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

五、处理客户端Post请求数据

// 引入express
const express = require('express')
const fs = require('fs');
const { promisify } = require('util')
const readFile = promisify(fs.readFile)

// 创建应用对象
const app = express();
// app.use(express.urlencoded())
app.use(express.json())

app.get('/', async function(req, res){
  try {
    let back = await readFile('./db.json', 'utf-8')
    res.send(JSON.parse(back))
  } catch (err) {
    res.status(500).json({err})
  }
})

app.post('/', async (req, res) => {
  console.log(req.headers)
  console.log(req.body)
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

在这里插入图片描述
app.use(express.urlencoded()) 是 Express 框架中的一个中间件,用于解析来自客户端的 URL 编码的请求体数据,并将其转换为 JavaScript 对象。这通常用于处理 POST 请求中的表单数据。使用这个中间件后,你可以在路由处理程序中通过 req.body 来访问表单数据。
app.use(express.json()) 来解析 JSON 格式的请求体数据

六、添加用户信息到db文件

拿到提交的表单值:

// 引入express
const express = require('express')
const fs = require('fs');
const { promisify } = require('util')
const readFile = promisify(fs.readFile)

// 创建应用对象
const app = express();
// app.use(express.urlencoded())
app.use(express.json())

app.get('/', async function(req, res){
  try {
    let back = await readFile('./db.json', 'utf-8')
    res.send(JSON.parse(back))
  } catch (err) {
    res.status(500).json({err})
  }
})

app.post('/', async (req, res) => {
  console.log(req.headers)
  // console.log(req.body)

  let body = req.body
  if (!body) {
    res.status(403).json({
      err: '缺少用户信息'
    })
  }
  let back = await readFile('./db.json', 'utf-8')
  const jsonObj = JSON.parse(back)
  // 给输入的用户信息添加个id
  body.id = jsonObj.users[jsonObj.users.length-1].id + 1
  jsonObj.users.push(body)
  console.log(body);

  res.send(body)
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

文件写入:

// 引入express
const express = require('express')
const fs = require('fs');
const { promisify } = require('util')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)

// 创建应用对象
const app = express();
// app.use(express.urlencoded())
app.use(express.json())

app.get('/', async function(req, res){
  try {
    let back = await readFile('./db.json', 'utf-8')
    res.send(JSON.parse(back))
  } catch (err) {
    res.status(500).json({err})
  }
})

app.post('/', async (req, res) => {
  console.log(req.headers)
  // console.log(req.body)

  let body = req.body
  if (!body) {
    res.status(403).json({
      err: '缺少用户信息'
    })
  }
  let back = await readFile('./db.json', 'utf-8')
  const jsonObj = JSON.parse(back)
  // 给输入的用户信息添加个id
  body.id = jsonObj.users[jsonObj.users.length-1].id + 1
  jsonObj.users.push(body)
  // 写入文件
  try{
    let w = await writeFile('./db.json', JSON.stringify(jsonObj))
    if(!w){
      res.status(200).send({
        msg: '添加成功'
      })
    }
  } catch(err){
    res.status(500).json({err})
  }
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

在这里插入图片描述
逻辑抽离:
db.js

const { promisify } = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)

exports.getDb = async () => {
  let data = await readFile('./db.json', 'utf-8')
  return JSON.parse(data)
}

exports.serveDb = async (data) => {
  return await writeFile('./db.json', JSON.stringify(data))
}

app.js

// 引入express
const express = require('express')
const db = require('./db')



// 创建应用对象
const app = express();
// app.use(express.urlencoded())
app.use(express.json())

app.get('/', async function(req, res){
  try {
    let back = await db.getDb()
    res.send(back)
  } catch (err) {
    res.status(500).json({err})
  }
})

app.post('/', async (req, res) => {
  // console.log(req.headers)
  // console.log(req.body)

  let body = req.body
  if (!body) {
    res.status(403).json({
      err: '缺少用户信息'
    })
  }
  let back = await db.getDb()
  const jsonObj = back
  // 给输入的用户信息添加个id
  body.id = jsonObj.users[jsonObj.users.length-1].id + 1
  jsonObj.users.push(body)
  // 写入文件
  try{
    let w = await db.serveDb(jsonObj)
    console.log(111, w)
    if(!w){
      res.status(200).send({
        msg: '添加成功'
      })
    }
  } catch(err){
    res.status(500).json({err})
  }
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

七、修改用户信息

// 引入express
const express = require('express')
const db = require('./db')



// 创建应用对象
const app = express();
// app.use(express.urlencoded())
app.use(express.json())

app.get('/', async function(req, res){
  try {
    let back = await db.getDb()
    res.send(back)
  } catch (err) {
    res.status(500).json({err})
  }
})

app.post('/', async (req, res) => {
  // console.log(req.headers)
  // console.log(req.body)

  let body = req.body
  if (!body) {
    res.status(403).json({
      err: '缺少用户信息'
    })
  }
  let back = await db.getDb()
  const jsonObj = back
  // 给输入的用户信息添加个id
  body.id = jsonObj.users[jsonObj.users.length-1].id + 1
  jsonObj.users.push(body)
  // 写入文件
  try{
    let w = await db.serveDb(jsonObj)
    if(!w){
      res.status(200).send({
        msg: '添加成功'
      })
    }
  } catch(err){
    res.status(500).json({err})
  }
})

app.put('/:id', async (req, res) => {
  // console.log(req.params.id) // 传进来的数据
  // console.log(req.body)
  try{
    let userInfo = await db.getDb()
    let userId = Number(req.params.id)
    let user = userInfo.users.find(item => item.id === userId)
    if (!user){
      res.status(403).send({
        msg: '用户不存在'
      })
    }
    const body = req.body
    user.username = body.username ? body.username : user.username
    user.age = body.age ? body.age : user.age
    userInfo.users[userId - 1] = user
    let w = await db.serveDb(userInfo)
    if (!w) {
      res.status(201).send({
        msg: '修改成功'
      })
    }
  } catch(err){
    res.status(500).json({err})
  }
})
 
// 监听服务
app.listen(4000, () => {
  console.log('run http://127.0.0.1:4000');
})

在这里插入图片描述
在这里插入图片描述

八、学到这里,感觉nodeJS还挺有意思的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/583963.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker学习笔记3:VmWare CentOS7安装与静态ip配置

文章目录 一、安装CentOS71、下载centos镜像2、安装二、设置静态ip三、xshell连接centos本专栏的docker环境是在centos7里安装,因此首先需要会安装centos虚拟机。 本篇博客介绍如何在vm虚拟机里安装centos7。 一、安装CentOS7 1、下载centos镜像 推荐清华源,下载如下版本 …

使用量排名前50的GPTs趋势和特征

Chatgpt的gpt商店已经有几千gpts了。目前哪些gpts比较受欢迎呢?有哪些趋势和投资呢? 根据whatplugin.ai(截止日期为2024年3月),使用量最多的50个gpts数据分析结果如下: GPTs类型的分布情况如下: 图像生成…

案例-部门管理-删除

黑马程序员JavaWeb开发教程 文章目录 一、查看页面原型二、查看接口文档三、开发1、Controller2、Service(1)service接口层(3)service实现层 3、Mapper4、Postman 一、查看页面原型 二、查看接口文档 三、开发 1、Controller 因…

Keepalived+LVS实现Nginx集群配置

Nginx1和Nginx2组成集群,为了实现负载均衡,在集群的前端配置了LVS服务,但是一台LVS容器产生单点故障,因此需要过Keepalived实现LVS的高可用集群 192.168.136.55node1keepalived192.168.136.56node2keeplived192.168.136.57 node3n…

Excel 中用于在一个范围中查找特定的值,并返回同一行中指定列的值 顺序不一样 可以处理吗

一、需求 Excel 中,在一列(某范围内)查找另一列特定的值,并返回同一行中另一指定列的值, 查找列和返回列的顺序不一样 二、 实现 1、下面是一个使用 INDEX 和 MATCH 函数的例子: 假设你有以下数据&…

CI/CD:基于kubernetes的Gitlab搭建

1. 项目目标 (1)熟悉使用k8s环境搭建Gitlab (2)熟练应用Gitlab基本配置 2. 项目准备 2.1. 规划节点 主机名 主机IP 节点规划 k8s-master 10.0.1.1 kube_master k8s-node1 10.0.1.2 kube_node k8s-node2 10.0.1.3 k…

影响外汇交易盈利的因素有哪些?

外汇交易就是通过汇率的差价来赚取相应的利润。在外汇交易中,投资者是否可以盈利,主要取决于是否正确的判断了市场趋势和行情。投资者在交易过程中受到主观和客观的因素影响,具体包含这些内容。 影响外汇交易盈利的因素有哪些? 1、…

【酱浦菌-爬虫项目】爬取学术堂论文信息

1. 首先,代码定义了一个名为 url 的变量,它是一个包含三个网址的集合(或者说是一个集合的字典)。这些网址分别是: - ‘http://www.xueshut.com/lwtimu/127966.html’ - ‘http://www.xueshut.com/lwtimu/12…

nmap扫描工控设备的脚本支持

参考资料 转自(http://www.360doc.com/content/15/1201/11/26186435_517125254.shtml) 介绍 NMAP是一款强大的网络扫描工具,除了普通的TCP/IP网络扫描之外,NMAP的扩展脚本功能为我们提供了更为广阔的应用范围。 针对脚本学习可…

Python使用设计模式中的建筑模式将数据写入Excel且满足条件内容标红

对于这个任务,适合使用"Builder"设计模式。Builder模式的主要目的是将对象的构建与其表示分离,以便相同的构建过程可以创建不同的表示。在这个情况下,我们需要一个构建器来逐行构建Excel表格,并根据给定的数据添加相应的…

C++中auto关键字的用法详解

1.简介 auto作为一个C语言就存在的关键字,在C语言和C之间却有很大区别。 在C语言中auto修饰的变量,是具有自动存储器的局部变量,但因为局部变量默认类别默认是auto修饰导致一直没有人去使用它。 C11中,标准委员会赋予了auto全新…

【MySQL | 第八篇】在MySQL中,如何定位慢查询以及对应解决方法?

文章目录 8.在MySQL中,如何定位慢查询以及对应解决方法?8.1MySQL慢查询日志8.1.1开启慢查询(1)修改配置文件(2)设置全局变量 8.1.2日志记录在表上(实践)8.1.3日志记录在文件上&#…

android studio 4.2.1运行java文件报错

当运行某个带main函数的java文件报这个错误的时候 Could not create task :app:Test.main(). > SourceSet with name main not found. 解决办法&#xff1a;在工程的.idea下的.gradlew.xml文件下添加 <option name"delegatedBuild" value"false"…

InternVL——GPT-4V 的开源替代方案

您的浏览器不支持 video 标签。 在人工智能领域&#xff0c;InternVL 无疑是一颗耀眼的新星。它被认为是最接近 GPT-4V 表现的可商用开源模型&#xff0c;为我们带来了许多惊喜。 InternVL 具备强大的功能&#xff0c;不仅能够处理图像和文本数据&#xff0c;还能精妙地理解…

基于H.264的RTP打包中的组合封包以及分片封包结构图简介及抓包分析

H.264视频流的RTP封装类型分析&#xff1a; 前言&#xff1a; NULL Hearder简介(结构如下)&#xff1a; ---------------|0|1|2|3|4|5|6|7|--------|F|NRI| Type |--------------- F&#xff1a;forbidden_zero_bit&#xff0c; 占1位&#xff0c;在 H.264 规范中规定了这…

Python数据分析大作业(ARIMA 自回归积分滑动平均模型) 4000+字 图文分析文档 销售价格库存分析+完整python代码

资源地址&#xff1a;Python数据分析大作业 4000字 图文分析文档 销售分析 完整python代码 完整代码分析 ​ 同时销售量后1000的sku品类占比中&#xff08;不畅销产品&#xff09;如上&#xff0c;精品类产品占比第一&#xff0c;达到66.7%&#xff0c;其次是香化类产品&#x…

【架构】后端项目如何分层及分层领域模型简化

文章目录 一. 如何分层1. 阿里规范2. 具体案例分析 二. 分层领域模型的转换1. 阿里规范2. 模型种类简化分析 三. 小结 本文描述后端项目中如何进行分层&#xff0c;以及分层领域模型简化 一. 如何分层 1. 阿里规范 阿里的编码规范中约束分层逻辑如下: 开放接口层&#xff1a…

Apache Seata基于改良版雪花算法的分布式UUID生成器分析1

title: Seata基于改良版雪花算法的分布式UUID生成器分析 author: selfishlover keywords: [Seata, snowflake, UUID] date: 2021/05/08 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Seata基于改良版雪花算法的分布式UUID生成器分析…

NLP(10)--TFIDF优劣势及其应用Demo

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 TF*IDF&#xff1a; 优势&#xff1a; 可解释性好 可以清晰地看到关键词 即使预测结果出错&#xff0c;也很容易找到原因 计算速度快 分词本身占耗时最多&#xff0c;其余为简单统计计算 对标注数据依赖小 可以使用无标注语…

请编写函数fun,该函数的功能是:将放在字符串数组中的M个字符串(每串的长度不超过N),按顺序合并组成一个新的字符串。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…