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 没有数据就 返回404if (!result) {res.statusCode = 404res.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();//响应JS0Nres.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 iplet { url, ip } = req;// 将信息保存在record.log 中fs.readFileSync(path.resolve(__dirname + 'record.log'),`${url} ${ip}\r\n`)res.end('home')
})
app.all('*', (req, res) => {// 获取url iplet { 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 iplet { 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 参数是否为666if (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) => {// 获取refererlet referer = req.get('referer')if (referer) {// 实例化let url = new URL(referer)let hostname = url.hostnameif (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.mzph.cn/diannao/5862.shtml

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

相关文章

【C++】深入理解string类

一、熟悉string类 1.1 string类的由来&#xff1a; C语音中的字符串需要我们自己管理底层空间&#xff0c;容易内存泄露。而C是面向对象语音&#xff0c;所以它把字符串封装成一个string类。 C中对于string的定义为&#xff1a;typedef basic_string string; 也就是说C中的str…

java面试(微服务)

SpringCloud五大组件 Nacos&#xff1a;注册中心Ribbon&#xff1a;负载均衡Feign&#xff1a;远程调用sentinel&#xff1a;服务熔断Gateway&#xff1a;网关 注册中心 Eureka Nacos 负载均衡 Ribbon负载均衡流程 Ribbon的负载均衡策略 RoundRobinRule&#xff1a;简单的…

C++中把Lambda 表达式作为参数传递给模板函数。

例子&#xff1a; template<class fun> void mytest(fun f) {_string s1 "abc";_string s2 "abc";if (f(s1, s2)){std::cout << "相等。\n";}}int main() {mytest([](const _string s1, const _string& s2) { return s1 s2; …

python学习笔记----异常、模块与包(九)

一、异常 1.1 什么是异常 在Python中&#xff0c;异常是程序执行时发生的错误。当Python检测到一个错误时&#xff0c;它会引发一个异常&#xff0c;这可能是由于多种原因&#xff0c;如尝试除以零、访问不存在的文件&#xff0c;或者尝试从列表中获取不存在的索引等。异常处…

数组的拷贝

数组的拷贝 文章目录 数组的拷贝浅拷贝内存分析 深拷贝内存分析 浅拷贝 概念&#xff1a;数组的浅拷贝是指新数组保存的是原数组的内存地址&#xff0c;并没有拷贝真正的值&#xff0c;如果原数组的内容发生改变那么新数组的内容也会发生相应改变。 代码实现&#xff1a; pu…

C语言/数据结构——每日一题(合并两个有序链表)

一.前言 嗨嗨嗨&#xff0c;大家好久不见&#xff01;今天我在LeetCode看到了一道单链表题&#xff1a;https://leetcode.cn/problems/merge-two-sorted-lists想着和大家分享一下&#xff0c;废话不多说&#xff0c;让我们开始今天的题目分享吧。 二.正文 1.1题目描述 1.2题…

phpstudy 搭建 upload-labs 文件上传靶场

phpstudy 搭建靶场&#xff1a;下载安装好phpstudy后&#xff0c;下载靶场源码&#xff1a; upload-labs下载地址&#xff1a; https://github.com/c0ny1/upload-labs 下载完压缩文件&#xff0c;解压文件&#xff0c;解压后的文件夹命名为upload--labs 将解压后到文件夹放…

docker如何生成springboot镜像

1、在springboot的jar包所在的目录下创建Dockerfile文件&#xff0c;此案例的目录为/usr/java Dockerfile的文件内容如下&#xff1a; FROM openjdk:8 LABEL author"zengyanhui" LABEL email"1181159889qq.com" WORKDIR /usr/java/springbootdemo COPY s…

负债56亿,购买理财产品遭违约,操纵虚假粉丝,流量在下滑,客户数量减少,汽车之家面临大量风险(六)

本文由猛兽财经历时5个多月完成。猛兽财经将通过以下二十二个章节、8万字以上的内容来全面、深度的分析汽车之家这家公司。 由于篇幅限制&#xff0c;全文分为&#xff08;一&#xff09;到&#xff08;十&#xff09;篇发布。 本文为全文的第十四章、第十五章、第十六章。 目…

机器人系统ros2-开发实践04-ROS 2 启动文件管理大型项目的最佳实践

机器人上的大型应用通常涉及多个互连的节点&#xff0c;每个节点可以有许多参数。海龟模拟器中模拟多只海龟就是一个很好的例子。海龟模拟由多个海龟节点、世界配置以及 TF 广播器和监听器节点组成。在所有节点之间&#xff0c;存在大量影响这些节点的行为和外观的 ROS 参数。 …

《与 Apollo 共创生态——Apollo7周年大会干货分享》

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 阿波罗X企业自动驾驶解决方案自动驾驶技术提升与挑战自动驾驶系统功能与性能的详细解析<td alig…

python可视化学习笔记折线图问题-起始点问题

问题描述&#xff1a; 起始点的位置不对 from pyecharts.charts import Line import pyecharts.options as opts # 示例数据 x_data [1,2,3,4,5] y_data [1, 2, 3, 4, 5] # 创建 Line 图表 line Line() line.add_xaxis(x_data) line.add_yaxis("test", y_data) li…

数字阅览室的优势

近年来&#xff0c;随着我国社会经济的快速发展&#xff0c;信息技术的发展也得到了广泛的应用&#xff0c;我国高校图书馆和图书管理系统进入了快速发展的快车道。在这种环境下&#xff0c;数字化阅览室在校园中非常流行。数字阅览室是一套真正意义上的面向中小学图书管理、浏…

Golang | Leetcode Golang题解之第58题最后一个单词的长度

题目&#xff1a; 题解&#xff1a; func lengthOfLastWord(s string) (ans int) {index : len(s) - 1for s[index] {index--}for index > 0 && s[index] ! {ansindex--}return }

python基础语法--函数

一、函数概述 函数就是执行特定任务完成特定功能的一段代码。可以在程序中将某一段代码定义成函数&#xff0c;并指定一个函数名和接收的输入&#xff08;参数&#xff09;&#xff0c;这样就可以在程序的其他地方通过函数名多次调用并执行该段代码了。 每次调用执行后&#…

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

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

AI 图像无损放大器:多平台支持,轻松上手 | 开源日报 No.241

upscayl/upscayl Stars: 25.5k License: AGPL-3.0 upscayl 是一个免费开源的 AI 图像放大器&#xff0c;支持 Linux、MacOS 和 Windows 平台&#xff0c;并且秉承着“Linux 优先”理念构建。 使用先进的 AI 算法对低分辨率图像进行放大和增强在不损失质量的情况下放大图像&am…

ubuntu开启message文件

环境&#xff1a;ubuntu 20.04 1、首先需要修改 /etc/rsyslog.d/50-default.conf 文件&#xff1b;源文件中message被注释&#xff0c;如下图&#xff1a; 2、打开注释&#xff1a; 3、重启服务 systemctl restart rsyslog.service 如此即可&#xff01;

嵌入式学习59-ARM7(自动设备号和混杂设备)

知识零碎&#xff1a; 头文件查找&#xff1a; /arm/路径下的头文件 linux驱动程序的编写&#xff0c;编译&#xff0c;运行过程 -------------------------------------------------------------------------------------------------------------------------------- 1.…

java-函数式编程-函数对象

定义 什么是合格的函数&#xff1f;无论多少次执行函数&#xff0c;只要输入一样&#xff0c;输出就不会改变 对象方法的简写 其实在类中&#xff0c;我们很多参数中都有一个this&#xff0c;被隐藏传入了 函数也可以作为对象传递&#xff0c;lambda就是很好的例子 函数式接口中…