Node.js -- express 框架

文章目录

  • 1. express 使用
  • 2. 路由
    • 2.1 路由的使用
    • 2.2 获取请求报文参数
    • 2.3 获取路由参数
    • 2.4 路由参数练习
  • 3. express 响应设置
  • 4. 中间件
    • 4.1 全局中间件
    • 4.2 路由中间件
    • 4.3 静态资源中间件
  • 5. 获取请求体数据 body-parser
  • 6. 防盗链
  • 7. 路由模块化
  • 8. 模板引擎
    • 8.1 了解EJS
    • 8.2 列表渲染
    • 8.3 条件渲染
    • 8.4 在express 中使用ejs
  • 9. express-generator
  • 10. 文件上传

express是一个基于Node.js平台的极简、灵活的WEB应用开发框架,官方网址:https://www.expressjs.com.cn/
简单来说,express是一个封装好的工具包,封装了很多功能,便于我们开发WEB应用(HTTP服务)

1. express 使用

// 1. 导入express 包
const express = require('express')

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

// 3. 创建路由
app.get('/home', (req, res) => {
    res.end('Hello Express')
})
// 如果请求方法为GET 且URL中路径为/home 就会执行后面的回调函数

// 4. 监听端口 启动服务器
app.listen(3000, () => {
    console.log('服务已经启动,端口3000 正在监听中...');
})

2. 路由

什么是路由?

官方定义:路由确定了应用程序如何响应客户端对特定端点的请求

2.1 路由的使用

一个路由的组成有请求方法路径回调函数组成
express中提供了一系列方法,可以很方便的使用路由,使用格式如下:

app.< method >(path,callback)

请求报文加载过来之后就开始与路由的规则开始比对;之前的判断我们是通过if / else if 来进行的,而现在express 框架对这种判断方法做了封装

app.get('/', (req, res) => {
    res.end('/')
})

app.post('/login', (req, res)=> {
    res.end('login')
})
app.post()('/login', (req, res) => {
    res.end('login')
})
// 匹配所有的方法
app.all('/test', (req, res) => {
    res.end('test')
})
// 404 响应
app.all('*', (req, res) => {
    res.end('404 not found')
})

2.2 获取请求报文参数

express框架封装了一些API来方便获取请求报文中的数据,并且兼容原生HTTP模块的获取方式

// 原生操作
console.log(req.method);
console.log(req.url);
console.log(req.httpVersion);
console.log(req.headers);
// express操作
console.log(req.path);
console.log(req.query);
// 获取ip
console.log(req.ip);
// 获取请求头
console.log(req.get('host'));

2.3 获取路由参数

路由参数指的是URL路径中的参数(数据)

app.get(‘/:id.html’,(req,res)=>{
res.send(‘商品详情,商品id为’ + req.params.id);
});

const express = require('express')

const app = express()

app.get('/:id.html', (req, res) => {
    // 获取URL 路由参数 其中路径中
    // req.params 存储了请求报文中所有路由id 
    console.log(req.params.id);
    res.setHeader('content-type','text/html;charset=utf-8')
    res.end('test')
})

app.listen(3000, () => {
    console.log('服务已经启动...');
})

2.4 路由参数练习

根据路由参数响应歌手的信息
路径结构如下
/singer/1.html
显示歌手的姓名和图片

const express = require('express')
const {singers} = require('./singers.json')

const app = express()

// 练习内容

app.get('/singer/:id.html', (req, res) => {
    // 获取路由参数
    let { id } = req.params; // 该变量是字符串形式
    // 在数组中寻找对应id的数据
    let result = singers.find(item => {
        if (item.id === Number(id)) {
            return true;
        }
    })
    console.log(result)
    // 判断:如果result 没有数据就 返回404
    if (!result) {
        res.statusCode = 404
        res.end(`<h1>404 not found</h1>`)
    }
    res.end(`
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>${result.singer_name}</h1>
        <img src="${result.singer_pic}" alt="">
    </body>
    </html>
    `);
})
app.listen(3000, () => {
    console.log('服务已经启动...');
})

获取 URL 中的动态参数
通过req.params对象,可以访问到 URL 中,通过:匹配到的动态参数:

3. express 响应设置

express框架封装了一些API来方便给客户端响应数据,并目兼容原生HTTP模块的获取方式

  1. express中设置响应的方式兼容HTTP模块的方式
const express = require('express')
const app = express()
app.get('/response', (req, res) => {
    // 获取请求的路由规则
    app.get("/response", (req, res) => {
        // 1.express中设置响应的方式兼容HTTP模块的方式
        res.statusCode = 404;
        res.statusMessage = 'xxx'
        res.setHeader('abc', 'xyz');
        res.write('响应体')
        res.end('xxx')
    })

在这里插入图片描述
2. express的响应方法


    // 2.express的响应方法
    res.status(500);//设置响应状态码
    res.set('aaa', 'bbb');//设置响应头
    res.send('中文响应不乱码');//设置响应体 自动添加字符集的设置
    // 连贯操作
    res.status(404).set('xxx', 'yyy').send('你好朋友')
   
  1. express的响应方法
 // 3.其他响应
    res.redirect('http://atguigu.com')//重定向 
    res.download('./package.json');//下载响应 返回下载形式的响应
    res.json();//响应JS0N
    res.sendFile(__dirname + '/home.html')//响应文件内容
})

app.listen(3000, () => {
    console.log('服务已启动...');
})

4. 中间件

中间件(Middleware)本质是一个回调函数
中间件函数可以像路由回调一样访问请求对象(request),响应对象(response)

中间件的作用就是使用函数封装公共操作,简化代码

中间件类型:

  • 全局中间件
  • 路由中间件

4.1 全局中间件

每一个请求到达服务端之后都会执行全局中间件函数
(路由函数只有在满足请求方法和请求路径一致时才会执行回调函数)

全局中间件实践:

const express = require('express')
const fs = require('fs')
const path = require('path')
const app = express()
app.get('/home', (req, res) => {
    // 获取url ip
    let { url, ip } = req;
    // 将信息保存在record.log 中
    fs.readFileSync(path.resolve(__dirname + 'record.log'),`${url} ${ip}\r\n`)
    res.end('home')
})
app.all('*', (req, res) => {
    // 获取url ip
    let { url, ip } = req;
    // 将信息保存在record.log 中
    fs.readFileSync(path.resolve(__dirname + 'record.log'),`${url} ${ip}\r\n`)
    res.end('all')
})
app.listen(3000,()=> {
    console.log('服务启动...')
})

如果我们每创建一个路由就在其中定义url和ip 再存入到文件中,那么将会产生很多重复的代码,这时候我们可以让重复的代码部分写入全局中间件中

function recordMiddleware(req,res,next) {
    // 获取url ip
    let { url, ip } = req;
    // 将信息保存在record.log 中
    fs.readFileSync(path.resolve(__dirname + 'record.log'), `${url} ${ip}\r\n`)
    next()// 表示执行完全局中间件函数之后继续执行下面的路由中间件或者其他的全局中间件
}
// 使用全局中间件函数
app.use(recordMiddleware)
app.get('/home', (req, res) => {
    res.end('home')
})
app.all('*', (req, res) => {
    res.end('all')
})

4.2 路由中间件

// 针对/admin/setting的请求,要求URL携带code=521参数,如末携带提示『暗号错误」
// const { log } = require('console')
const express = require('express')
const path = require('path')
const app = express()
let CheckCodeMiddleware = (req, res, next) => {
    // 其中路由中间件函数 必须要加上 表示在满足条件时就可以继续执行next()
    //判断code 参数是否为666
    if (req.query.code === '666') {
        next()
    }
    else {
        res.send('不能调用')
    }
}
app.get('/home', CheckCodeMiddleware, (req, res) => {
    res.send('首页')
});
app.get('/admin', CheckCodeMiddleware, (req, res) => {
    res.send('后台')
});
app.all('*', (req, res) => {
    res.send('all')
});
app.listen(3000, () => {
    console.log('go');
})

4.3 静态资源中间件

静态资源:长时间不发生改变的资源,例如:css,js,图片…

express.static(文件夹路径) --> 返回文件中的全局中间件

app.use(express.static(__dirname+'/public'))

之前我们通过读取文件url ,拼接文件路径,读取文件,响应文件,设置meta 类型等多项操作完成了以上操作,但是在这里一行代码就搞定了!

注意事项:

  1. index.html 为默认打开的资源,也就是可以作为网站首页,因为我们在不添加路径的时候访问网站,返回的会是index.html ,但是这也反映出一个问题(也就是第二个注意事项)!
  2. 如果静态资源与路由规则同时匹配,谁先匹配谁就像响应
  3. 路由响应动态资源,静态资源中间件响应静态资源

练习:
要求:局域网内可以访问小米商城的网页

const express = require('express')
const app = express()
// 静态资源中间件
app.use(express.static(__dirname + '/小米商城'))

app.listen(3000, () => {
    console.log('服务启动');
})

在电脑上win + R 打开命令行,输入ipconfig 查询本机所在局域网,在链接了同一个局域网的手机上可以通过ip:端口号查看同一个网站(比如自己写好的小米商城网页)

5. 获取请求体数据 body-parser

express可以使用body-parser包处理请求体
第一步:安装

npm i body-parser

第二步:导入body-parser包

const bodyParser = require(‘body-parser’);

第三步:获取中间件函数

// 处理querystring格式的请求体
let urlParser = bodyParser.urlencoded({extended:false});
// 处理JSON格式的请求体
let jsonParser = bodyParser.json();

第四步:设置路由中间件,然后使用request.body来获取请求体数据

app.post('/login',urlParser,(request,response)=>{
//获取请求体数据
//console.log(request.body);
//用户名
console.log(request.body.username);
//密码
console.log(request.body.userpass);
response.send('获取请求体数据')
})

6. 防盗链

有些时候我们在网上存了某张图片的网址链接,但是并不能在自己的html 中打开,这是因为这个网站设置了防盗链(禁止该域名之外的其他网站来对该图片网站访问)

防盗链实践:
在设置防盗链之前,访问127.0.0.1:3000 和访问localhost:3000 效果是一样的,可以得到同一个网页;

// 防盗链
const express = require('express')

const app = express()

// 声明中间件
app.use((req, res, next) => {
    // 获取referer
    let referer = req.get('referer')
    if (referer) {
        // 实例化
        let url = new URL(referer)
        let hostname = url.hostname
        if (hostname !== '127.0.0.1') {
            res.status(404).send('<h1>404 Not Found</h1>')
            return
        }
    }
    next()
})

// 静态资源中间件设置
app.use(express.static(__dirname + '/public'))

app.listen(3000, () => {
    console.log('启动!');
})

7. 路由模块化

homeRouter.js:

const express = require('express')
// 创建路由对象
const router = express.Router()

// 创建路由规则
router.get('/settings',  (req, res) => {
    res.send('设置')
});
router.get('/search',  (req, res) => {
    res.send('搜索')
});
router.get('/home', (req, res) => {
    res.send('首页')
});
router.get('/admin', (req, res) => {
    res.send('后台')
});

// 暴露router
module.exports = router

模块化.js:

const express = require('express')

const homeRouter = require('./routes/homeRouter')
const app = express()
// 设置
app.use(homeRouter)

// app.all('*', (req, res) => {
//     res.send('all')
// });
app.listen(3000, () => {
    console.log('go');
})

8. 模板引擎

模板引擎是分离用户界面和业务数据的一种技术
模板引擎也是一种通用技术,多种语言都有。

8.1 了解EJS

EJS是一个高效的Javascript的模板引擎。
官网:https://ejs.co/
中文站:https://ejs.bootcss…com/

EJS 初体验:
简单理解模板引擎就是把html和js 分离开,但这里的js 指的是服务器相关的js 代码。

下面是之前的一个案例,从中我们可以发现html 和js 是混合到了一起的,而ejs 可以将他们分离开。
在这里插入图片描述

const ejs = require('ejs')
const fs = require('fs')

let china = '中国' // 1处
let weather = 'sunny'

// 声明变量
let str = fs.readFileSync('./10-test.html').toString()

// 使用ejs 渲染
let result = ejs.render(str, { china: china, weather })

console.log(result);

render(str,{}) 第二个属性是对象的形式,属性名对应str中的变量名 属性值对应1处的变量名
在这里插入图片描述

8.2 列表渲染

// 列表渲染
const { log } = require('console');
const ejs = require('ejs')
const fs = require('fs')

const xiyouji = ['冒菜','酸甜麻辣烫','凉菜','菠萝']

// 原生js 
// let str = '<ul>'
// xiyouji.forEach(item => {
//     str += `<li>${item}</li>`
// })
// str += '</ul>'

// ejs 渲染
let str = fs.readFileSync('./11-test.html').toString()
let result = ejs.render(str, { xiyouji: xiyouji })

console.log(result);

8.3 条件渲染

通过变量isLogin 决定最终的输出内容
true --> 输出< span>欢迎回来</ span>
false --> 输出< button>登录</button < button >注册</ button>

// 条件渲染
const ejs = require('ejs')
const fs = require('fs')

let isLogin = true
// 原生js
// if (isLogin) {
//     console.log('<span>come back</span>');
// } else {
//     console.log(`<button>登录</button>
//     <button>注册</button>`);
// }

//ejs
let html = fs.readFileSync('./12-test.html').toString()
let result = ejs.render(html, { isLogin: isLogin })
console.log(result);

8.4 在express 中使用ejs

const express = require('express')
const path = require('path')

const app = express()

// 1. 设置模板引擎
app.set('view engine', 'ejs')
// 2. 设置模板文件存放位置 模板文件:具有模板语法内容的文件
app.set('views',path.resolve(__dirname,'./views'))

app.get('/home', (req, res) => {
    // 3. render 响应
    // res.render('模板文件名', '数据')
    let title='在思考中学习!'
    res.render('view', {title})
})

app.listen(3000, () => {
    console.log('go!');
})

9. express-generator

express-generator 是Express 应用程序生成器,帮助我们生成express 文件骨架。

  1. 安装

npm i -g express-generator

  1. express - h/v --> 查看相关帮助
  2. express - e 文件路径 --> 添加ejs 的模板引擎支持
  3. 添加依赖

npm i

10. 文件上传

文件上传场景:
更换头像;网盘上传文件;短视频平台上传视频…

注:
enctype=“multipart/form-data” 是上传表单时表单必要的属性

处理文件上传 – 安装formidable 包

// 显示网页表单
router.get('/portrait', (req, res) => {
  res.render('portrait')
})

// 处理文件上传
router.post('/portrait', (req, res) => {
  // 创建form 对象
  const form = formidable({
    multiples: true,
    // 设置上传文件的保存目录 一般都保存在用户很容易获取到的地方
    uploadDir: __dirname + '/../public/images',
    // 保持文件后缀
    keepExtensions:true

  });

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

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

相关文章

面试二十四、继承多态

一、继承的本质和原理 组合&#xff08;Composition&#xff09;&#xff1a; 组合是一种"有一个"的关系&#xff0c;表示一个类包含另一个类的对象作为其成员。这意味着一个类的对象包含另一个类的对象作为其一部分。组合关系通常表示强关联&#xff0c;被包含的对象…

【Week-Y7】使用自己的数据集训练YOLO-v8

文章目录 一、官方环境配置与测试1. 配置环境2. 用官方图片测试&#xff08;图片下载失败&#xff09;3. 用本地图片测试&#xff0c;检查配置的环境是否可用 二、使用自己的数据集进行训练测试1. 执行split_train_val.py文件2. 执行python .\voc_label.py文件3. 创建fruit.yam…

[Python基础知识]05函数和模块

一、函数的定义 格式&#xff1a;def 函数名&#xff08;参数列表&#xff09;: 注&#xff1a; 函数代码块以 def 关键词开头&#xff0c;后接函数标识符名称和圆括号()。即使该函数不需要接收任何参数&#xff0c;也必须保留一对空的圆括号 函数形参不需要声明其类型&#x…

layui中禁用div标签等操作

为了实现点击表格行后触发事件 然后去触发后进行操作 页面流程操作设置规定 不可编辑直接添加属性 class"layui-disabled"如果在最大的 div 设置不可编辑 但是内部有些还是可以触发使用的 所以就重写一下 取到当前 div 下的 所有的子元素 然后在给所有的子元素…

闲话 ASP.NET Core 数据校验(二):FluentValidation 基本用法

前言 除了使用 ASP.NET Core 内置框架来校验数据&#xff0c;事实上&#xff0c;通过很多第三方框架校验数据&#xff0c;更具优势。 比如 FluentValidation&#xff0c;FluentValidation 是第三方的数据校验框架&#xff0c;具有许多优势&#xff0c;是开发人员首选的数据校验…

抢先体验:MacOS成功安装PHP8.4教程

根据官方消息&#xff0c;PHP 8.4将于2024年11月21日发布。它将通过三个 alpha 版本、三个 beta 版本和六个候选版本进行测试。 这次的重大更新将为PHP带来许多优化和强大的功能。我们很高兴能够引导您完成最有趣的更新升级&#xff0c;这些更改将使我们能够编写更好的代码并构…

解决React报错Encountered two children with the same key

当我们从map()方法返回的两个或两个以上的元素具有相同的key属性时&#xff0c;会产生"Encountered two children with the same key"错误。为了解决该错误&#xff0c;为每个元素的key属性提供独一无二的值&#xff0c;或者使用索引参数。 这里有个例子来展示错误是…

YOLOv8主要命令讲解

YOLOv8主要有三个常用命令&#xff0c;分别是&#xff1a;train&#xff08;训练&#xff09;、predict&#xff08;预测&#xff09;、export&#xff08;转化模型格式&#xff09;&#xff0c;下面我将展开讲讲三个常用命令的常用参数与具体使用方法。 一、训练 通过自己标…

STM32单片机通过串口控制DDSM210 直驱伺服电机

1 电机介绍 官方资料&#xff1a;https://www.waveshare.net/wiki/DDSM210 DDSM210 直驱伺服电机是基于一体化开发理念&#xff0c;集外转子无刷电机、编码器、伺服驱动于一体的高可靠性永磁同步电动机&#xff0c;其结构紧凑&#xff0c;安装方便&#xff0c;运行稳定&#x…

react核心知识

1. 对 React 的理解、特性 React 是靠数据驱动视图改变的一种框架&#xff0c;它的核心驱动方法就是用其提供的 setState 方法设置 state 中的数据从而驱动存放在内存中的虚拟 DOM 树的更新 更新方法就是通过 React 的 Diff 算法比较旧虚拟 DOM 树和新虚拟 DOM 树之间的 Chan…

【PCL】教程 supervoxel_clustering执行超体聚类并可视化点云数据及其聚类结果

[done, 417.125 ms : 307200 points] Available dimensions: x y z rgba 源点云milk_cartoon_all_small_clorox.pcd > Loading point cloud... > Extracting supervoxels! Found 423 supervoxels > Getting supervoxel adjacency 这段代码主要是使用PCL&#xff08;Po…

Linux进程——进程的创建(fork的原理)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经会使用getpid/getppid函数来查看pid和ppid,本篇文章会介绍第二种查看进程的方法&#xff0c;以及如何创建子进程&#xff01; 本篇主要内容&#xff1a; 查看进程的第二种方法创建子进程系统调用函数fork 在开始前&#xff…

【华为】路由综合实验(基础)

【华为】路由综合实验 实验需求拓扑配置AR1AR2AR3AR4AR5PC1PC2 查看通信OSPF邻居OSPF路由表 BGPBGP邻居BGP 路由表 配置文档 实验需求 ① 自行规划IP地址 ② 在区域1里面 启用OSPF ③ 在区域1和区域2 启用BGP&#xff0c;使AR4和AR3成为eBGP&#xff0c;AR4和AR5成为iBGP对等体…

buuctf-misc-22.神秘龙卷风1

22.神秘龙卷风1 题目&#xff1a;暴力破解-翻译Brainfuck计算机语言 根据提示是4位密码&#xff0c;直接破解密码即可 解压后发现是这样一个文档 我们尝试使用网站翻译这个 内容由“”、“.”、“>”三种符号组成&#xff0c;我刚开始认为这是一种密文&#xff0c;经过搜索…

thinkpad电脑文件隐藏了怎么恢复?教你几招

在使用ThinkPad电脑时&#xff0c;有时我们可能会发现一些文件或文件夹突然“消失”了&#xff0c;这通常是因为它们被隐藏了。本文将为您介绍几招恢复ThinkPad电脑上隐藏文件的方法&#xff0c;帮助您轻松找回丢失的文件。 图片来源于网络&#xff0c;如有侵权请告知 一、了解…

【实时数仓架构】方法论

笔者不是专业的实时数仓架构&#xff0c;这是笔者从其他人经验和网上资料整理而来&#xff0c;仅供参考。写此文章意义&#xff0c;加深对实时数仓理解。 一、实时数仓架构技术演进 1.1 四种架构演进 1&#xff09;离线大数据架构 一种批处理离线数据分析架构&#xff0c;…

when to create a ViewRootImpl

when to create a ViewRootImpl when method setView is called: when method dispatchDetachedFromWindow is called:

预训练模型介绍

一、什么是GPT GPT 是由人工智能研究实验室 OpenAI 在2022年11月30日发布的全新聊天机器人模型, 一款人工智能技术驱动的自然语言处理工具 它能够通过学习和理解人类的语言来进行对话, 还能根据聊天的上下文进行互动,能完成撰写邮件、视频脚本、文案、翻译、代码等任务 二、 为…

TypeScript学习笔记:迈向更安全的JavaScript编程

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux专栏05:Linux基本指令之目录处理指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之目录处理指令 编号&#xff1a;05 文章目录 Linux基…
最新文章