【Node.js】Express

1、什么是Express

Express是基于Node.js平台,快速、开放、极简的web开发框架,它的作用和Node.js内置的http模块类似,是专门用来创建web服务器的,Express本质上就是一个npm的第三方包,提供了快速创建web服务器的便捷方法。
Express中文网:https://www.expressjs.com.cn/

2、Express的安装

在项目所处的目录中,运行如下的终端命令,即可将express安装到项目中使用。

npm install express@4.17.1

在这里插入图片描述

3、Express的基本使用

3.1 创建基本的web服务器

//导入express模块
const express=require('express');
//创建web服务器
const app=express();
//配置监听
......
//启动web服务器
app.listen(8089,()=>{
  console.log('express server is running at http://127.0.0.1:8089');
})

3.2 配置监听请求

app.get('请求URL'function(req,res){
  //处理函数
  res.send('get')
})

app.post('请求URL'(req,res)=>{
  //处理函数
  res.send('post')
})

3.3 响应客户端数据

通过res.send()方法可以把处理好的内容,发送给客户端。

//监听客户端的GET请求和POST请求,并向客户端响应具体的内容。
app.get('/user',function(req,res){
    //向客户端响应一个JSON对象
    res.send({name:'张三',age:20,gender:'男'})
})

app.post('/user',(req,res)=>{
    res.send('用户信息请求成功')
})

3.4 请求参数处理

(1)获取URL中携带的查询参数:
通过req.query对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数。

//http://127.0.0.1:8086/user?name='admin'&&age=22
app.get('/user',function(req,res){
    //req.query默认是一个空对象,客户端通过使用?username='admin'&password='123'
    //这种查询字符串的形式,发送到服务器的参数,可以通过req.query对象访问到。
    //例如:req.query.username
    console.log(req.query)
})

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

//http://127.0.0.1:8081/user/admin
//URL地址中,可以通过:参数名的形式,匹配动态参数值
app.get('/user/:name',function(req,res){
    //req.params默认是一个空对象
    //里面存放着通过:动态匹配到的参数值
    console.log(req.params)
    res.send(req.params)
})

//http://127.0.0.1:8081/user/admin/123
app.post('/user/:name/:pwd',(req,res)=>{
    res.send("post请求") 
    console.log(req.params)
})

4、Express静态资源处理

4.1 express.static()

express通过提供的函数express.static()。可以方便地创建一个静态资源服务器,将指定目录下的图片、css文件、js文件对外开放。

app.use(express.static('./images'))

注意:
Express在指定的静态目录中查找文件,并对外提供资源的访问路径,因此,存放静态文件的目录名不会出现在URL中,例如,上述代码指定public文件夹中的文件对外开放,访问路径如下:
http://127.0.0.1:8081/1.jpg

4.2 托管多个静态资源目录

如果要托管多个静态资源目录,需要多次调用express.static()函数。

app.use(express.static('./public'))
app.use(express.static('./files'))

访问静态资源文件时,express.static()函数会根据目录的先后顺序查找所需的文件,如果第一个文件中已经找到,就不会继续再往下进行查找。

4.3 挂载路径前缀

如果希望在托管的静态资源访问路径之前挂载路径的前缀,需要进行如下设置:

app.use('/public',express.static('./images'))
//访问路径:http://127.0.0.1:8081/public/images/1.jpg

5、Express路由

5.1 什么是Express中的路由

在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系,它由三部分组成,分别是请求的类型、请求的URL地址、处理函数。

//匹配get请求,且请求URL为/
app.get('/',(req,res)=>{

})

//匹配post请求,且请求URL为/user
app.post('/user',(req,res)=>{

})

5.2 路由的匹配过程

每当一个请求到达服务器后,需要先经过路由的匹配,只有匹配成功后,才会调用对应的处理函数,在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的URL同时匹配成功,则Express会将这次请求,转交给对应的function函数进行处理。

5.3 路由的使用

5.3.1 简单用法

在Express中使用路由最简单的方法就是将路由挂载到app上。

const express=require('express')
//创建web服务器
const app=express()
//挂载路由
app.get('/',(req,res)=>{
    res.send("123")
})
app.post('/user',(req,res)=>{
    res.send("345")
})
//启动服务器
app.listen(8082,()=>{
    console.log("服务已启动")
})

5.3.2 模块化路由

为了方便对路由进行模块化的管理,Express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。
将路由抽离为单独的模块步骤:

  1. 创建路由模块对应的.js文件
  2. 调用express.Router()函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. 使用module.exports向外共享路由的对象
  5. 使用app.use()函数注册路由模块
//导入express模块
const express=require('express')
//创建路由对象
const router=express.Router()
//向路由对象上挂载具体的路由
router.get('/list',(req,res)=>{
    res.send("list")
})
router.get('/add',(req,res)=>{
    res.send("add")
})
//向外共享路由
module.exports=router
const express=require('express')
//导入路由模块
const router=require('./router/router')
//创建服务器
const app=express()

//注册路由模块
//app.use()函数的作用就是来注册全局中间件
//为路由模块添加访问前缀:app.use('/api',router)
app.use(router)

//启动服务器
app.listen(8082,()=>{
    console.log("启动服务成功")
})

6、Express中间件

6.1 什么是中间件

中间件,特指业务流程的中间处理环节,当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。Express中间件本质上就是一个function处理函数。
中间件的作用:
多个中间件之间共享同一份req和res,基于这样的特性,我们可以在上游的中间件中统一为req或res对象添加自定义的属性或方法,供下游的中间件或者路由进行使用。

6.2 中间件的使用

6.2.1 定义中间件函数

中间件函数的形参列表中,必须包含next函数,而路由处理函数中只包含req和res。
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。

const mv=function(req,res,next){
  console.log('这是一个最简单的中间件函数')
  //注意:在当前中间件的业务处理完成后,必须调用next函数,表示把流转关系转交给下一个中间件或路由
  next()
}

6.2.2 全局中间件

客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。

const express=require('express')
//创建一个web服务器
const app=express()
//定义一个中间件
const mv=function(req,res,next){
    console.log("我是一个中间件")
    //中间件业务处理完成后必须调用next函数将流转关系给下一个中间件或路由
    next()
}

//将mv设置为全局生效的中间件
app.use(mv)
//监听
app.get('/',(req,res)=>{
    res.send("Hello World")
})

//启动web服务器
app.listen(8082,()=>{
    console.log("服务器启动了")
})

定义全局中间件简化形式:

app.use((req,res,next)=>{
  //业务逻辑
  next();
})

可以使用app.use()连续定义多个中间件,客户端请求到达服务器之后,会按照中间件定义的先后顺序一次进行调用。

6.2.3 局部中间件

//导入express
const express=require('express')
//创建web服务器
const app=express();

//定义一个中间件
const mv=(req,res,next)=>{
    console.log("我是一个局部中间件")
    next()
}
//路由
//将mv设置为局部中间件
app.get('/user',mv,(req,res)=>{
    res.send("user")
})

app.get('/list',(req,res)=>{
    res.send("list")
})

//启动服务器
app.listen(8081,()=>{
    console.log("服务器启动了")
})

定义多个局部中间件:

//将mv设置为局部中间件,两种方式等价
app.get('/user',mv,mv2,(req,res)=>{
    res.send("user")
})

app.get('/user',[mv,mv2],(req,res)=>{
    res.send("user")
})

6.2.4 中间件的作用

多个中间件之间,共享同一份req和res,基于这样的特性,可以在上游中间件中统一为req和res对象添加自定义的属性和方法,供下游的中间件或路由使用。

const express=require('express')
const app=express()

//定义中间件
app.use((req,res,next)=>{
    req.reqTime=Date.now()
    console.log('我是一个中间件')
    next()
})

app.get('/user',(req,res)=>{
    res.send('user,请求时间:'+req.reqTime)
})


app.listen(8082,function(){
    console.log('服务已经启动!')
})

6.2.5 使用中间件的注意事项

  1. 一定要在路由之前注册中间件
  2. 客户端发过来的请求,可以连续调用多个中间件进行处理
  3. 执行完中间件的业务代码之后,不要忘记调用next函数
  4. 为了防止代码逻辑混乱,调用next函数后不要再写额外的代码
  5. 连续调用多个中间件,多个中间件之间,共享req、res对象

6.3 中间件的分类

6.3.1 应用级别的中间件

通过app.use()或app.get()或app.post(),绑定到app实例上的中间件,叫做应用级别的中间件。

const express=require('express')
const app=express()

//应用级别中间件(全局中间件)
app.use((req,res,next)=>{
  console.log('我是一个全局中间件')
  next()
})

//应用级别中间件(局部中间件)
const mv=(req,res,next)=>{
  console.log('我是一个局部中间件')
  next()
}
app.get('/',mv,(req,res)=>{
  res.send('Home page')
})

app.listen(8081,function(){
  console.log('express server is running at http://127.0.0.1:8081')
})

6.3.2 路由级别的中间件

绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别,只不过,应用级别中间件是绑定到app实例上,路由级别中间件是绑定到router实例上。

const express=require('express')
const router=express.Rouer()
router.use((req,res,next)=>{
  next()
})
module.exports=router

6.3.3 错误级别的中间件

错误级别中间件的作用:专门用来捕获整个项目中发送的异常错误,从而防止项目异常崩溃的问题。
格式:错误级别中间件的function处理函数中,必须有4个形参,形参顺序从前往后,分别是(err,req,res,next)
注意:
错误级别的中间件必须注册到所有路由之后

const express=require('express')
const app=express()

app.get('/',(req,res)=>{
    throw new Error('服务器内部发送错误')
    res.send('Home page')
})

//错误级别中间件
app.use((err,req,res,next)=>{
    res.send('Error:'+err.message)
})

app.listen(8082,()=>{
    console.log('express server is running at http://127.0.0.1:8082')
})

6.3.4 Express内置中间件

自Express4.16.0版本开始,Express内置了3个常用的中间件,极大的提高了Express项目的开发效率和体验。

  1. express.static快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性)
  2. express.json解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
  3. express.urlencoded解析URL-encoded格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
//通过express.json()这个中间件,解析表单中的JSON格式的数据
//默认情况下,如果不配置解析表单数据的中间件,则req.body默认等于undefined
app.use(express.json())
app.post('/user',(req,res)=>{
    res.send(req.body)
    console.log(req.body)
})
//通过express.urlencoded()这个中间件,解析表单中url-encoded格式的数据
app.use(express.urlencoded({extend:false}))
app.post('/add',(req,res)=>{
    res.send(req.body)
    console.log(req.body)
})

6.3.5 第三方中间件

非express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,可以按需下载并配置第三方中间件,从而提供项目的开发效率。
例如:在express@4.16.0之前的版本中,经常使用body-parser这个第三方中间件,来解析请求数据,使用步骤如下:

  1. 运行npm install body-parser安装中间件
  2. 使用require导入中间件
  3. 调用app.use(parser.urlencoded({extended:false}))注册并使用中间件
const express=require('express')
const parser=require('body-parser')
const app=express()
app.use(parser.urlencoded({extended:false}))

app.post('/user',(req,res)=>{
    res.send(req.body)
    console.log(req.body)
})

app.listen(8084,function(){
    console.log('服务器已启动!')
})

7、接口跨域问题

正常通过express编写的接口由于访问协议的不同,不支持跨域请求。解决跨域请求的方案主要有两种:

  1. cors:主流方案,推荐使用
  2. jsonp:有缺陷的方案,只支持get请求

什么是cors?
cors(Cross-Origin Resources Sharing,跨域资源共享)由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。
浏览器的同源安全策略默认会阻止网页跨域获取资源,但如果接口服务器配置了cors相关的HTTP响应头就可以解决浏览器的跨域访问限制。
cors是Express的一个第三方中间件,通过安装和配置cors中间件,可以很方便地解决跨域问题。

使用步骤如下:

  1. 运行npm i cors安装中间件
  2. 使用const cors=require(‘cors’)导入中间件
  3. 在路由之前调用app.use(cors())配置中间件

cors注意事项:

  1. cors主要在服务器端进行配置,客户端浏览器无须做任何额外的配置,即可请求开启了cors的接口
  2. cors在浏览器中有兼容性,只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了cors的服务接口(例如:IE10+,Chrome4+,FireFox3.5+)

8、nodemon

在编写测试node.js项目的时候,如果修改了项目的代码,则需要频繁的手动关闭再重新启动项目,非常繁琐,可以通过nodemon这个工具监听项目文件的变动,当代码被修改后,nodemon会自动重启项目,极大方便了开发和测试。
安装:

#全局安装
npm i nodemon -g
#本地安装
npm i nodemon -D

使用nodemon:

nodemon 要执行项目的路径

如果在终端执行nodemon命令时出现以下提示
在这里插入图片描述
在本机上搜索powerShell,再以管理员的方式打开,接着输入
set-ExecutionPolicy RemoteSigned 即可。
在这里插入图片描述

9、Node.js中操作mysql

9.1 安装mysql模块

mysql模块是托管与npm上的第三方模块,它提供了在Node.js项目中连接和操作MySQL数据库的能力。在项目中需要使用时,需要先将mysql安装为项目的依赖包。

npm install mysql

9.2 配置mysql模块

在使用mysql模块操作mysql数据库时,必须先对mysql模块进行必要的配置。

//导入mysql模块
const mysql=require('mysql')
//配置mysql数据库连接信息
const db=mysql.createPool({
    host:'127.0.0.1',
    user:'root',
    password:'123',
    database:'test'  
})
//测试
const sql="select * from user"
db.query(sql,function(err,res){
    if(err) return console.log(err.message)
    console.log(res)
})

9.3 mysql模块操作数据库

9.3.1 查询

const sql="select * from user"
db.query(sql,function(err,res){
    if(err) return console.log(err.message)
    console.log(res)
})

9.3.2 新增

const user={name:'小美',age:22,gender:1,phone:'186'}
const sql="insert into user(name,age,gender,phone) values(?,?,?,?)"
//使用数组的形式,依次为?占位符指定具体的值
db.query(sql,[user.name,user.age,user.gender,user.phone],function(err,res){
    if(err) return console.log(err.message)
    if(res.affectedRows==1){
        console.log('插入数据成功!')
    }
})

插入数据的便捷方式:
如果插入数据时,数据对象的每个属性和数据表的字段一一对应,则可以通过如下方式快速插入数据:

const user={name:'小小',age:21,gender:2,phone:'186'}
const sql="insert into user set ?"
//使直接将数组对象当做占位符的值
db.query(sql,user,function(err,res){
    if(err) return console.log(err.message)
    if(res.affectedRows==1){
        console.log('插入数据成功!')
    }
})

9.3.3 更新

const user={id:5,name:'小小2',age:21,gender:2,phone:'186150'}
const sql="update user set name=?,age=?,gender=?,phone=? where id=?"
db.query(sql,[user.name,user.age,user.gender,user.phone,user.id],function(err,res){
    if(err) return console.log(err.message)
    if(res.affectedRows==1){
        console.log('修改数据成功!')
    }
})

修改数据的便捷方式:
更新数据时,如果数据对象的每个属性与数据表的字段一一对应,则可以通过如下方式快速更新数据:

const user={id:5,name:'小小3',age:21,gender:2,phone:'150'}
const sql="update user set ? where id=?"
db.query(sql,[user,user.id],function(err,res){
    if(err) return console.log(err.message)
    if(res.affectedRows==1){
        console.log('修改数据成功!')
    }
})

9.3.4 删除

//注意:如果sql语句中有多个占位符,必须使用数组为每个占位符指定具体的值
//      如果sql语句中只有一个占位符,则可以省略数组
const sql="delete from user where id=5"
db.query(sql,5,function(err,res){
    if(err) return console.log(err.message)
    if(res.affectedRows==1){
        console.log('删除数据成功!')
    } 
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值