为什么使用experss?
因为nodejs内置模块http使用起来较为复杂,开发效率低,而experss是由http模块进一步封装出来的,能够提升开发效率
experss跟koa有什么区别?
koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。
使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。
koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。
使用experss创建基本的web服务器
1.导入experss
const experss = require(‘experss’)
2.创建web服务器
const app=experss()
3.调用app.listen(端口号,成功的回调函数)启动服务器
路由方法
请求方法支持:
get - 查询请求 - 条件在地址栏
post - 新增请求 - 数据在请求主体
put - 修改请求 - 条件在地址栏 - 数据在请求主体
delete - 删除请求 - 条件在地址栏
各个动词方法用来处理对应的请求。不过有一个方法除外:
app.all() // 可以用来处理任意请求方式
响应方法
res.download() // 提示下载文件。
res.end() // 终结响应处理流程。
res.json() // 发送一个 JSON 格式的响应。
res.jsonp() // 发送一个支持 JSONP 的 JSON 格式的响应。
res.redirect() // 重定向请求。
res.render() // 渲染视图模板。
res.send() // 发送各种类型的响应。
res.sendFile() // 以八位字节流的形式发送文件。
res.sendStatus() // 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。
download示例:
// 响应下载 - res.download(被下载的源文件,下载后的文件名称,回调函数)
res.download("./test.html",'b.html',err=>{
if(err){
console.log("下载失败");
}else{
console.log("下载成功");
}
})
json示例:
// 给客户端响应json数据
// res.json(json格式的数据)
let obj = {
name:"张三",
age:12,
wife:"翠花",
children:['阿大','阿二','小明']
}
res.json(obj)
jsonp示例:
// 给客户端发起的jsonp请求做响应,响应的是json数据
// res.jsonp(json格式的数据)
let obj = {
name:"张三",
age:12,
wife:"翠花",
children:['阿大','阿二','小明']
}
res.jsonp(obj)
redirect示例:
// res.redirect() 用来跳转路由的 - /a这个路由,其实/b这个路由就正好可以处理他,就可以在/a这个路由处理中,将这次请求交给/b这个路由去处理
res.redirect('/index')
app.get('/index',(req,res)=>{
let data = fs.readFileSync('./test.html')
res.end(data)
})
render示例:
send示例:
// res.send() - 用于给客户端响应字符串的 - 字符串中如果是标签,可解析成html - 自动设置数据类型和编码
let html = `<h2>这是一个h2标签</h2>`
// res.end 不会自动设置数据类型,也不会设置编码
// res.end(html)
res.send(html)
sendFile示例:
// res.sendFile() 用于给客户端响应一个文件
res.sendFile(__dirname + '/test.html')
sendStatus示例:
// sendStatus是自动设置响应状态码,并将对应的响应状态描述响应给客户端
res.sendStatus(404) // 响应 not found
res.sendStatus(200) // 响应 ok
把内容响应给客户端
通过res.send()把内容响应给客户端
app.get('utl',function(req,res){
res.send(内容)
})
app.post('utl',function(req,res){
res.send(内容)
})
请求对象的属性
req.url // 请求的路径 - 如果有?传参,这个路径中也会带有参数
req.method // 请求方法
req.path // 请求路径 - 如果有?传参,这个路径中不包含参数
req.protocol // 协议
req.params // 获取get请求的参数 - 针对动态路由传参 - restful风格的参数 - 最终获取到的是对象,对象的键,就是路径指定的名称
req.query // 获取get请求的参数 - 针对传统形式传参 - 使用?参数 - 最终获取到的是对象
混合使用函数和函数数组处理路由:
var cb0 = function (req, res, next) {
console.log('CB0')
next()
}
var cb1 = function (req, res, next) {
console.log('CB1')
next()
}
app.get('/example/d', [cb0, cb1], function (req, res, next) {
console.log('response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from D!')
})
中间件
中间件(middleware)可以理解为业务流程的中间处理环节,可以理解成中间过滤器。
1656462685049.png
中间件的分类
中间件可以分类可分如下几类:
内置中间件,也就是express本身自带无需npm安装
express.static()
第三方中间件
非 Express 官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中可以通过npm进行安装第三方中间件并配置,从而提高项目的开发效率。例如body-parser (解析post数据的)此中间件可以很方便帮助我们获取到post提交过来的数据。
自定义中间件,开发者自己编写的(中间件的本质其实就是一个function)
从使用层面去考虑中间件
可以划分为:
应用级别中间件(通过app.get/post/use等方法绑定到app实例的中间件)
全局使用中间件(所有路由都生效)
app.use(中间件)
局部使用中间件(当前路由生效)
app.请求方法(地址,[中间件…,]回调函数)
app.请求方法(地址,中间件1,中间2,中间3…,]回调函数)
路由级别中间件(绑定到express.Router()上的中间件)
其用法与应用级别的中间件没有任何区别,只是一个绑在app实例上,一个绑在router上
router.use(中间件)
router.请求方法(地址,[中间件…,]回调函数)
experss内置中间件
experss提供了一个experss.static(),通过它我们可以非常方便的创建一个静态资源服务器
app.use(experss.static(名称))
例:app.use(experss.static(public))(通过这行代码可以将public下的图片,css,js对外开放访问了,experss在指定的静态目录中查找文件,并对外提供资源的访问路径,因此,存放静态文件的目录名不会出现在url里,托管多个静态资源请多次调用experss.static)
const experss = require(‘experss’)
const app=experss()
app.use(experss.static(public))
app.listen(80,function(){
})
experss.static挂载路径前缀 app.use('/public',experss.static(public))
在express中,除了内置的express.static()中间件,还内置了另外2个常用的中间件:
express.json() 作用:接收json格式提交的数据
// 兼容性问题:express >= 4.16.0
app.use(express.json())
其在接收完数据后,会将数据的对象形式挂载到req请求对象的body属性上
使用示例:
// 有了这个中间件以后,我们可以从客户端给服务器端发送json数据,这个json数据会放到请求对象req的body属性上
app.use(express.json())
app.post('/p1',(req,res)=>{
// express.json中间件可以让数据挂在req的body属性上
console.log(req.body);
res.send('this p1 request is ended')
})
首先必须是post请求,然后必须有数据,但是数据不能是以前的 x-www-form-urlencoded这样的数据,必须是raw的数据
然后请求头的content-type 必须是 application/json
express.urlencoded()作用:处理post表单数据
//兼容性问题:express >= 4.16.0
app.use(express.urlencoded({extended: false}))
其在接收完数据后,会将数据的对象形式挂载到req请求对象的body属性上
注意:后面提及的这2个内置中间件存在兼容性问题。上述2个中间件都说把数据处理之后挂到req.body上,但是实际上并不会出现我们想的覆盖的问题。
自定义中间件
自定义中间件,其本质就是定义一个处理请求的函数。
只是此函数中除了有request和response参数外还必须包含一个next参数,此参数可以使中间件让流程向下执行下去直到匹配到的路由中发送响应给客户端。
也可以通过给request对象添加属性来进行中间件数据的向下传递,自定义中间件例子:
function mfn(req,res,next){
//. 自己需要定义的逻辑流程
// 中间件最后一定要执行此函数,否则程序无法向下执行下去
next()
}
注意:在整个请求链路中,所有中间件与最终路由共用一份req和res
第三方中间件
在express中,其允许我们使用第三方的中间件来进行对数据进行处理。比较典型的例如:可以使用第三方中间件来接收post数据。
以使用body-parser中间件来接收post数据为例,步骤如下:
安装三方中间件body-parser
npm i -S body-parser
应用文件中导入body-parser
通过中间件调用 app.use(body.urlencoded({extended: false}))
在匹配的路由中通过req.body获数post中数据
在使用的时候,body-parser库的语法与前面看的express内置的express.urlencoded中间件的语法非常相似 ,因为Express内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件进一步封装出来的。但内置的有版本兼容问题,所以一般项目选择使用第三方的中间件
异常处理中间件
作用:专门用来捕获整个项目发生的异常错误,从而防止项目异常崩溃的问题产生(友好显示异常)
格式:错误级别中间件的函数参数中,必须有四个形参,分别是(err,req,res,next)
注意:异常处理中间件相较于多出来的err参数里面包含了错误信息,可以输出给用户看
app.get('/',(req,res) => {
throw new Error('服务器内部发生了致命的错误!')
res.send('Welcome to my homepage')
})
app.use((err,req,res,next) => {
console.log('发生了错误:' + err.message)
res.send('Error!' + err.message)
})
404中间件
作用:用于处理404的请求响应
// 假设定义这个路由,但是实际请求的时候请求了/12345,这个时候就会404
app.post("/1234", (req, res, next) => {
res.send('你请求成功了')
});
// 404的输出
// 该中间件也需要写在最后(与异常中间件的顺序无所谓,只要确保其在所有的路由方法之后就可)
app.use((req,res,next) => {
// 输出404错误
res.status(404).send('<h1>404</h1>')
// 先指定404状态码,然后再输出错误信息
})
404错误中间件也要求在所有的正常请求路由的后面去声明使用,不要放在路由的前面,否则会导致后面的路由都是404错误。
注意点:错误级别的中间件,必须在所有路由之后注册,至于404中间件与异常中间件,谁先谁后无所谓。
cookie
cookie的原理是在浏览器中开辟了一个用来存储http请求中的数据,第一次保存之后,下次请求只要还是使用的当前浏览器,就能访问到浏览器这个空间中的数据。
cookie会作为键值对,在响应头和请求头之间携带。
cookie的特点:
域名限制,当前域名下设置的cookie,只能在当前域名下使用
时效性,cookie不会永久存储在浏览器,具有一定的有效期
数量限制,正常情况下,每个域名最多不能超过50个cookie
空间限制,cookie只能存储4kb
数据类型限制,cookie中只能存储字符串
获取cookie:
npm i cookie-parser -S
// 导入
const cookieParser = require('cookie-parser')
// 中间件
app.use(cookieParser());
// 请求头获取
req.headers.cookie // 获取所有cookie
// 响应头设置
res.cookie(键,值,{maxAge: 有效期-毫秒}) // 设置cookie
session
cookie是存储在浏览器的,所以安全性不高,所以一些重要数据就不能存储在cookie中,且cookie的存储空间有限制,所以就有了session。
session是存储服务器端的,session需要依赖cookie,session数据存储会在cookie中存放一个sessionid,这个sessionid会跟服务器端之间产生映射关系,如果sessionid被篡改,他将不会跟服务器端进行隐射,因此安全系数更高。且session的有效期比较短。通常是20分钟左右,如果浏览器在20分钟内没有跟服务器进行交互,服务器就会删除session数据。
使用:
npm i cookie-session -S
// 导入:
const session = require('cookie-session')
// session配置
session({
name:"sessionId",
secret:"asdfasdfqwer", // 给sessioinId加密使用的秘钥,随便填写
maxAge:20*60*1000 // 20分钟
})
// 设置session
req.session[键] = 值
// 获取session
req.session[键]
加密
npm i bcryptjs -S
使用:
(bcryptjs是bcrypt的替代模块,bcryptjs是纯js实现,bcrypt是c++实现,有时候你升级node版本的时候会有问题)
var bcrypt = require('bcryptjs');
// 加密
密文 = bcryptjs.hashSync(明文[,数字]); // 数字,将使用指定的轮数生成盐并将其使用。推荐 10
// 验证
bcryptjs.compareSync(明文,密文); // 通过返回true,失败返回false
jwt
使用:
npm install jsonwebtoken
// 加密生成token
var jwt = require('jsonwebtoken');
var token = jwt.sign(被加密的对象, 盐);
// 验证
jwt.verify(token, 盐, function(err, decoded) {
// decoded是解密后的对象
});
文件上传
使用:
npm i multer -S
var multer = require('multer')
var upload = multer({ dest: path.join(__dirname,'public','image') }) // 指定上传的文件路径
app.post('/profile', upload.single('上传表单name值'), function (req, res, next) {
// req.file 是上传的文件信息 - 可以从中获取到文件名称、路径、后缀 - 拼接路径存入mongodb
})
mysql
使用:
npm i mysql -S
// 导入
const mysql = require("mysql");
// 创建连接对象
const db = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"test"
});
// 连接
db.connect(err=>{
if(err){
console.log("连接失败,错误:"+err);
return;
}
console.log("连接成功");
});
// 执行语句
db.query("",(err,result)=>{
if(err){
console.log("失败,错误:"+err);
return;
}
console.log("成功");
console.log(result);
});
验证码
使用:
npm i svg-captcha -S
const svgCaptcha = require('svg-captcha')
// 创建验证码
let captcha = svgCaptcha.create();
// captcha是是一个对象,其中包含data键和text键,text是验证码上的字符,data是一个svg标签直接可以显示为一张图片
邮件发送
使用:
npm install nodemailer --save
const nodemailer = require('nodemailer')
// 1. 创建发送器
const transport = nodemailer.createTransport({
// 需要你发送放邮箱的 stmp 域名和密码和一些其他信息
// 需要你去复制一下, 找到下载的 nodemailer 第三方包
// nodemailer -> lib -> well-known -> services.json
"host": "smtp.qq.com",
"port": 465,
"secure": true,
// 证明你的身份
auth: {
// 发送方邮箱的用户名
user: '邮箱号',
// stmp 允许密码
pass: '授权码'
}
})
// 2. 发送邮件
transport.sendMail({
// 从那个邮箱发送
from: '发送方邮箱',
// 发送到哪里, 可以写一个字符串, 书写邮箱, 也可以写一个数组, 写好多邮箱
to: ['接收方邮箱', '接收方邮箱'],
// 邮件标题
subject: '标题',
// 本次邮件的 超文本 内容
html: `
您好: 本次的验证码是
<h1 style="color: red;"> 2345 </h1>
请在 3 分钟内使用
<br>
------------------------<br>
前途无限股份有限公司
`,
// 本次邮件的 文本 内容
// text: ''
}, function (err, data) {
if (err) return console.log(err)
console.log('邮件发送成功')
console.log(data)
})
本文内容参照了CSDN博主「贪吃ღ大魔王」的文章,链接:https://blog.csdn.net/weixin_44070254/article/details/118480069
网友评论