重温express

news2024/12/26 10:25:38

前言

很久之前囫囵吞枣的学过一点node,最近决定用node+vue写个博客项目,所以重新学习了express的相关内容。

初始搭建

创建项目

  1. npm init给项目命名创建项目
  2. 终端进入项目,安装express依赖,npm i express
  3. js文件中引入express使用
const express = require('express');

const app = express();

app.get('/', (req, res) => {
    res.send('有人请求了根路径')
})

app.listen(3000, function () {
    console.log("服务器正在运行 http://localhost:3000")
});

之后终端使用node index.js(tab键补全)运行上面代码

0.png

路由和中间件

express完全是由路由和中间件构成的框架,本质上来说express应用就是为了监听不同的路径调用各种中间件,中间件本身是一个函数,也可以叫插件,只是在express里面更习惯叫做中间件

路由

路由:前端访问不同的地址,后端返回不同的数据,这就是后端路由
如果/users/login接口是登录用的,/users/reg接口是注册用的。
监听不同的路径执行不同的函数,从而处理不同的请求

这个路由一般是在app上使用的,一般称为应用级别的路由

中间件

中间件就是一个函数,带有三个参数,req,res,next
req 请求的相关信息
res 响应的相关信息
next函数 如果调用了next,就会去执行下一个匹配到路由的中间件

app.use(
    function (req, res, next) {
        console.log("中间件1")
        res.send("中间件1")
        next()
    },
    function (req, res, next) {
        console.log("中间件2")
        next()
    },
    function (req, res, next) {
        console.log("中间件3")
    });

终端全部显示

3.png

注意下面这样两个中间件都不会正常运行

app.get("/user/login", function (req, res, next) {
    console.log("登录中间件")
    next()
})
app.get("/user/login", function (req, res, next) {
    console.log("最后一个中间件")
    res.send("nice ")
})

正确的写法应该是

app.use(
    function (req, res, next) {
        console.log("中间件1")
        res.send("中间件1")
        next()
    },
    function (req, res, next) {
        console.log("中间件2")
        next()
    },
    function (req, res, next) {
        console.log("中间件3")
        next()
    });
app.use(
    function (req, res, next) {
        console.log("中间件4")
        next()
    });
app.get(
    "/user/login",
    function (req, res, next) {
        console.log("登录中间件")
        next()
    }, function (req, res, next) {
        console.log("最后一个中间件")
    }
)

若没有第二个app.use里面的next,那么就不执行后面get请求了
中间件也可以是写在外面的js文件里面,然后导入使用
比如新建login.js

function fn(req, res, next) {
    console.log("登录中间件")
    next()
}
module.exports = fn;

之后在index.js中引入使用

let login = require("./login.js");
app.get(
    "/user/login",
    login,
    function (req, res, next) {
        console.log("最后一个中间件")
    }
)

附上一个终端运行截图

4.png

通过路由挂载中间件

app.use(中间件监听的路径,中间件函数)
参数两个:路径,*是匹配任何路径;回调函数,找到路径之后会执行回调函数。回调函数一般都是第三方封装好的函数,这个函数叫做中间件。

// 通过路由挂载中间件
app.use("/user/login", function (req, res) {
    console.log("打开/user/login")
    res.send("用户登录成功")
})

因为之前运行脚本开启了3000端口,需要关闭重启才能在规定目录看到想看的。

1.png

我们需要注意的是:修改了 server.js 文件,需要停止服务(ctrl + c),再次启动才会生效;
有了 nodemon,就不用频繁手动重启 server.js ,因为 nodemon 可以监视源码改动,并自动重启服务。这样我们只需要专注写代码逻辑,不需要过多关注服务。

全局安装nodemon

npm install -g nodemon

package.json 中的 nodemonConfig 选项中配置nodemon

"nodemonConfig": {
  "watch":["src/"],
  "ext":"js json"
}

之后修改代码不需要重启服务只需刷新页面即可
使用匹配所有路径,下面的就不匹配了

app.use("*", function (req, res) {
    console.log("匹配所有路径")
    res.send("匹配所有路径 ")
})

// 通过路由挂载中间件
app.use("/user/login", function (req, res) {
    console.log("打开/user/login")
    res.send("用户登录成功hahah ")
})

2.png

http请求
http有很多请求方式,常见的:
get请求、post上传、put修改、patch修改、delete删除
使用app.get 可以监听get请求,其他类似
postman可以发起不同的请求,可以作为请求测试工具。

postman使用描述
服务器启动的时候,使用postman进行测试
新建collection集合 Blog接口测试
接着在集合里面添加请求add request

路由中间件

专门处理路由的中间件就是路由中间件,路由中间件是express内置的一个中间件。后端编写接口,前端调用接口。
后端接口功能包括用户相关操作(登录,注册),文章相关操作(发布文章,删除文章,修改文章,文章列表,文章详情等等)
借助路由中间件将用户和文章相关操作分散在不同的js文件中
这种路由主要对应用级别的路由做了细分处理,就是路由级别的路由

操作步骤

  1. 获取路由中间件,新建routes/users.js
  2. 处理get请求,router.get(监听请求的路径,处理回调函数)
  3. 处理post请求,router.post(监听请求的路径,处理回调函数)
  4. 导出router对象
    代码展示
    users.js是用户相关操作
const express = require("express");
//创建一个路由中间件
const router = express.Router();
// /user/reg
//配置路由
router.get("/reg", function (req, res) {
    console.log("reg请求");
    // 向服务器发送json数据
    res.send({ username: "zhangsan" });
})

// 导出路由中间件
module.exports = router;

之后导入app.js(一开始我把index.js作为入口文件,后来将index移动到demo文件夹,新建了app.js作为新的入口文件)

let userRouter = require("./routes/users");
app.use("/users", userRouter)

之后启动服务器运行截图

5.png

路由中间件请求参数获取

get请求参数的获取

req.query
下面代码是users.js中的,因为users.js是app.js中的路由所以下面是监听/ users / login路径的get请求,如果在前端请求的url里面输入
http://localhost:3000/users/login?username=Angle&password=123456,在终端可以看到打印的请求的query参数

// 监听get请求 / users / login
//url中的搜索参数
router.get("/login", function (req, res) {
    // 获取get请求的query参数
    console.log(req.query);
    // 返回json数据
    res.json({ name:小米糕});
});

6.png

7.png

get请求的另外一种传参

获取get请求的url中的参数

router.get("/info/:id", function (req, res) {
    console.log(req.params);
    res.json(req.params);
})

8.png

9.png

post请求参数的获取

//user.js
router.post('/profile', (req, res, next) => {
    console.log(req.body)
    res.json(req.body)
})

//app.js
app.use(express.json()) 
app.use(express.urlencoded({ extended: true })) 

上面users.js中req.body包含在请求正文中提交的数据键值对。默认情况下,它是 undefined
app.js中解析前端请求的请求体的数据 ,解析json和x-www-form数据
post请求需要借助工具apipost或者postman来发送
我是用postman
两个小时遇到的问题是发送post请求服务器返回undefined。

11post请求返回undefined.png

12正确的post请求.png

静态资源托管中间件

html,css,js图片等都是静态资源,静态资源一般不需要处理直接返回给浏览器。
网页中发起请求,请求接口返回的数据叫做动态资源,比如JSON数据。
动态资源一般后端会处理,比如解析前端的请求过来的url和参数,根据url和参数返回不同的json数据。
使用express创建一个静态资源服务器,express.static()
当前目录下的文件夹public为静态资源文件夹,有请求发过来会先到静态资源文件夹下找有没有静态文件,有的话就直接返回静态文件,比如访问http://localhost:3000/a.js,就会去pubilc文件夹找a.js文件,在app.js里server.use(express.static(‘public’));

app.use(express.static("public"));

可以在浏览器地址栏输入http://localhost:3000/cool.jpg查看静态资源图片
这里一开始实践的时候我在地址栏输入之后回车get不到,后来检查发现我的public在demo子文件夹里面,于是删除,重新在Blog文件夹下面新建public文件夹。之后可以正常看。

假如在public文件夹下面还有多个文件夹,比如图片放在img文件夹。
那么访问的时候需要在url里面加上public的子文件夹路径。
http://localhost:3000/img/cool.jpg

express脚手架创建项目

express内置了许多中间件,逐个配置较复杂,一个后端项目需要一些别的中间件比如日志插件,错误处理插件等等,借助通用的项目模板可以简化配置过程。
通过应用生成器工具express-generator可以快速创建一个应用的骨架。
安装express-generator

npm install express-generator -g

创建项目

express -e Dreamlab

-e是指定了项目中的模板引擎。

前后端不分离

MVC是一种经典的设计模式,全名Model-View-Controller即模型-视图-控制器。这种模式用于应用程序的分层开发。大致就是模型和视图需要通过控制器来进行粘合。例如,用户发送一个HTTP请求,此时该请求首先会进入控制器,然后控制器去获取数据并将其封装为模型,最后将模型传递到视图中展现。,需要说明的是这个View可以采用Velocity,Freemaker等模板引擎,可使开发过程中人员分工更明确提高开发效率。

14.png

前后端分离

前后端分离(解耦)的核心思想:前端html页面通过ajax调用后端的Restful API并使用Json数据进行交互。
前端负责开发页面,通过接口(ajax)获取数据,采用Dom操作对页面进行数据绑定,最终是由前端把页面渲染出来。
在互联网架构中一般有两种服务器:web服务器:一般指像nginx,apache这类的服务器,他们一般只能解析静态资源,
应用服务器:一般指像tomcat,jetty,resin这类服务器可以解析静态资源和动态资源,但是解析静态资源的能力没有web服务器好。
一般只有web服务器才能被外网访问,应用服务器只能内网访问。
模板引擎是一个将页面模板和要显示的数据结合起来生成html页面的工具。如果说express中的路由控制方法相当于MVC中的控制器,那么模板引擎相当于MVC中的视图。

模板引擎的使用

下面两行代码设置模板文件的存储位置和使用的模板引擎

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

通过调用res.render()渲染模板,将其产生的页面直接返回给客户端,接收两个参数一个是模板名称,views目录下的模板文件名,拓展名.ejs可选。第二个参数是传递给模板的数据对象,用于模板翻译。
routes/index.js

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

get请求路径的时候使用{ title: ‘Express’ }渲染views目录下的模板index模板,把渲染后的数据返回给客户端。其实就是把一个对象传递给了index.ejs文件,得到一个html字符串,把html字符串返回给了前端。

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
  </body>
</html>

restful设计规范

restful-api是目前比较成熟的api设计理念。

域名

api的根入口点应尽可能保持足够简单,例如
api.example.com/(子域名下)
example.com/api/
(主域名下)
域名应该考虑拓展性,如果不确定API后续是否会拓展,应该将其放在子域名下,这样可以保持一定的灵活性。

路径

路径又称为端点,表示API的具体地址路径设计遵循下面约定:

  1. 明明必须全部小写
  2. 资源(resource)命名必须是名词复数形式
  3. 连字符使用"-“而不是”,"字符可能会在某些浏览器或屏幕中被部分遮挡或全部隐藏
  4. 易读
    例如:
    反例:
    api.example.com/getUser
    api.example.com/addUser
    正例:
    api.example.com/students
    api.example.com/students/girl…

HTTP请求

对于如何操作资源,有相应的HTTP请求对应,常用有下面5个(括号对应sql语句)

  1. get(select) 从服务器取出一项或者多项资源
  2. post(create)在服务器新建一个资源
  3. put(update)在服务器更新资源(客户端提供改变后的完整资源)
  4. patch(update)在服务器更新资源(客户端提供改变的属性)
  5. delete(delete)从服务器删除资源

下面通过几个简单增删改查demo演示上面的请求

user.js里面

router.get('/', function (req, res, next) {
  res.send('respond with a resource');
  res.json(
    {
      code: 1, msg: "查询成功",
      data: [
        id: 1, username: "zhangsan",
        id: 2, username: "lisan",
      ],
    }
  )
});

Postman中几个body请求格式区别及使用说明

Params与Body

二者区别在于请求参数在http协议中位置不一样。
Params 它会将参数放入url中以?区分以&拼接
Body则是将请求参数放在请求体中

get请求测试

输入地址get请求,选择body然后点击发送请求
15.png
中间很多次不清楚什么原因一直报错,postman返回的消息不是json数据,后来重启了几次注释,开启注释,重新启动,发送get测试成功返回json数据,如果没有语法错误和符号错误,重启服务器可能可以解决这个问题。

16.png

17.png

post请求测试

router.post('/', function (req, res, next) {
  console.log(req.body)//请求的参数
  res.json({
    code: 1,//code1操作成功0操作失败
    msg: '新建成功',
    data: { id: 1, username: "zhangsan" },
  });
});

18.png

19.png

get请求动态id相关信息

一开始多次get请求都是返回404,然后重启服务器就正常了

20.png

patch修改请求

router.patch('/:id', function (req, res, next) {
  // 1.获取参数
  console.log(req.params);
  console.log(req.body)
  // 2.数据库操作
  // 3. 返回json数据
  res.json({
    code: 1,
    msg: "更改成功",
    data: { id: 1, username: "zhangsan" },
  });
});

21.png

删除操作

router.delete('/:id', function (req, res, next) {
  // 1.获取参数
  console.log(req.params);

  // 2.数据库操作
  // 3. 返回json数据
  res.json({
    code: 1,
    msg: "删除成功",
  });
});

(删除请求postman中可以不添加password那个参数,虽然这个测试只是一个小demo)

22.png

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「C++系列」C++ 常量知识点-细致讲解

文章目录 一、C 常量定义1. 使用#define预处理指令2. 使用const关键字3. 局部常量4. 全局常量5. 指针常量6. 枚举&#xff08;Enumerations&#xff09;7. constexpr&#xff08;C11及以后&#xff09; 二、C 整数常量1. 十进制整数常量2. 八进制整数常量3. 十六进制整数常量4.…

RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化

接前一篇:RAG实践:ES混合搜索BM25+kNN(cosine) https://blog.csdn.net/Xin_101/article/details/140230948 本文主要讲解混合搜索相关理论以及计算推导过程, 包括BM25、kNN以及ES中使用混合搜索分数计算过程。 详细讲解: (1)ES中如何通过BM25计算关键词搜索分数; (2)…

Postman使用指南①网页版使用

postman官网地址&#xff1a;Postman API Platform 进入后点击右上角免费注册&#xff0c;注册后登录 登录之后即可在网页使用&#xff0c;无需下载

static的理论学习

在说到static之前&#xff0c;需要先明确变量类型&#xff1a; 而在聊到变量类型之前我们可以将变量的两个属性好好学一学 变量的两个属性 作用域&#xff08;scope&#xff09;&#xff1a; 从内存的角度来看&#xff0c;就是变量存放在栈&#xff08;stack&#xff09;中&…

最新版Python安装教程

一、安装Python 1.下载Python 访问Python官网&#xff1a; https:/www.oython.orgl 点击downloads按钮&#xff0c;在下拉框中选择系统类型(windows/Mac OS./Linux等) 选择下载最新稳定版本的Python 以下内容以演示安装Windows操作系统64位的python 左边是稳定发布版本Stabl…

6000字以上论文参考:基于Java+SpringMvc+Vue技术的实验室管理系统设计与实现

可参考&#xff1a;基于JavaSpringMvcVue技术的实验室管理系统设计与实现&#xff08;6000字以上论文参考&#xff09;-CSDN博客 论文参考&#xff1a;

算法day03 桶排序 数据结构分类 时间复杂度 异或运算

学数据结构之前 必看_哔哩哔哩_bilibili 1.认识复杂度和简单排序算法_哔哩哔哩_bilibili 桶排序&#xff08;Bucket sort&#xff09;------时间复杂度为O(n)的排序方法&#xff08;一&#xff09;_多桶排序时间复杂度-CSDN博客 桶排序 测试场景&#xff1a;数组中有10000个随…

【Excel】输入内容自动添加边框线

1. 选中表格区域 → 新建条件规则 2. 设置公式 3. 设置格式 测试生效

[激光原理与应用-100]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 4 - 3C电池行业应用 - 不同的电池类型、焊接方式类型

目录 前言&#xff1a; 一、激光在3C行业的应用概述 1.1 概述 1.2 激光焊接在3C-电池行业的应用 1.3 动力电池的激光焊接工艺 1.3.1 概述 1.3.2 动力电池常见的焊接应用 1.电池壳体与盖板焊接 2.电池防爆阀密封 焊接 二、不同的电池的外形 2.1 软包锂电池 2.1.1 概述…

数字传输系统的演变与应用

引言 在现代通信网络中&#xff0c;数字传输系统扮演着至关重要的角色。本文将用简单易懂的语言&#xff0c;向初学者介绍PCM速率体制、SONET/SDH以及光网络&#xff0c;让大家更好地理解这些技术。 2.5.1 PCM速率体制 数字传输系统简介 在早期电话网络中&#xff0c;用户电话…

基于S32K144驱动NSD8381

文章目录 1.前言2.芯片介绍2.1 芯片简介2.2 硬件特性2.3 软件特性 3.测试环境3.1 工具3.2 架构 4.软件驱动4.1 SPI4.2 CTRL引脚4.3 寄存器4.4 双极性步进电机驱动流程 5.测试情况6.参考资料 1.前言 最近有些做电磁阀和调光大灯的客户需要寻找国产的双极性步进电机驱动&#xf…

qemu模拟orangepi

前言 由于qemu目前只支持orange pipc单板&#xff0c;也就是H3型号&#xff0c;故我们就拿这个型号做测试 环境搭建 linux主机环境 我这里采用win10 WSL&#xff0c;且环境用的是openeuler的&#xff0c;在选择服务器类型可以按照自己喜好选择&#xff0c;也就是包安装方式…

玉石风能否接棒黏土风?一探AI绘画新风尚

在数字艺术的浪潮中,AI绘画平台以其独特的创造力和便捷性,正在逐步改变我们对艺术的传统认知。从黏土风的温暖质感到琉璃玉石的细腻光泽,每一次风格的转变都引领着新的潮流。今天,我们将聚焦玉石风,探讨它是否能成为下一个流行的艺术滤镜,并提供一种在线体验的方式,让你…

SUSAN

1995年英国牛津大学的S.M.Smith提出了一种新的图像边缘检测算法SUSAN算法,不同于以前经典边缘检测算法,SUSAN算法基于灰度相似性比较,采用圆形模板,对图像进行灰度差统计,无需计算方向导数,而且具备积分特性,它简单而且有效,适用于图像中边缘和角点的检测,可以去除图像…

CISC和RISC指令集

文章目录 1. 指令集 2. CISC&#xff08;复杂指令集计算&#xff09; 3. RISC&#xff08;精简指令集计算&#xff09; 4. RISC的设计初衷 5. CISC和RISC流程对比 CISC&#xff08;复杂指令集计算&#xff09;的实现 RISC&#xff08;精简指令集计算&#xff09;的实现 …

Bug记录:【com.fasterxml.jackson.databind.exc.InvalidDefinitionException】

bug记录 序列化错误 异常com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 完整错误(主要是FAIL_ON_EMPTY_BEANS) 00:15:20.250 [http-nio-3000-exec-1] ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - S…

【教程】新的Selenium!整合了隐藏浏览器指纹等功能

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 前景提要 driver Driver() 常用driver 接口 最后的话 前景提要 新的selenium&#xff0c;整合了隐藏浏览器指纹&#xff0c;非常好用&#x…

【Linux】网络新手村

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 引言 今天&#xff0c;我们就开始学习Linux网络相关的内容。这篇博客作为Linux网络板块的第一篇博客看&#xff0c;我们首先要带着大家明白Linux网络的一些名词的概念&#xff0c;为之后的学习扫清障碍。然后我…

基于CS模型和CV模型的多目标协同滤波跟踪算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于CS模型和CV模型的多目标协同滤波跟踪算法matlab仿真,在计多目标跟踪领域&#xff0c;基于CS模型和CV模型的多目标协同滤波跟踪算法是近年来发展起来的先进技术…

HackTheBox--Headless

Headless测试过程 1 信息收集 NMAP端口扫描 nmap -sSCV 10.10.11.85000端口测试 检查页面功能&#xff0c;请求 For questions 功能&#xff0c;跳转到 /support 目录 目录扫描 发现 /dashboard 目录 访问 /dashboard 目录&#xff0c;显示未认证&#xff0c;如果通过认证…