Express

Express

1、什么是Express

Express时基于Node.js平台,快速、开放、极简的Web开发框架

通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建web服务器的

Express的本质:是一个npm 上的第三方包,提供了快速创建Web服务器的便捷方法

Express官网:https://www.expressjs.com.cn/    本人使用Express 4.17.1 版本进行学习

2、安装Express

npm i express@4.17.1

3、使用Express创建基本的服务器

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

// 2.创建web服务器
const app = express()

// 4.监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user',(req,res)=>{
  //调用express提供的res.send()方法,向客户端响应一个JSON对象
  res.send([{name:'zs',age:20,gender:'男'},{name:'ls',age:22,gender:'女'}])
})

app.get('/',(req,res)=>{
  // 通过req.query可以获取到客户端发过来的查询参数
  //默认情况下,req.query是一个空对象
  res.send(req.query)
})

app.get('/user/:id/:name',(req,res)=>{
  // 通过req.params,可以通过 :参数名 的形式 匹配动态参数值
  res.send(req.params)
})

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

// 3.启动web服务器
app.listen('80',()=>{
  console.log("express server running at http:127.0.0.1");
})

4、nodemon的使用

好处:代码被修改后会被nodemon监听到,从而实行自动重启项目的效果

nodemon的安装,在终端内输入:

npm i -g nodemon

终端运行项目:

nodemon 项目文件名

遇见问题vscode权限不够:

image-20220321155212349

解决办法:

以管理员身份打开PowerShell(按住shift不要松 然后右击桌面空白区域, 就可以看到打开PowerShell的选择项了)
打开后,输入get-ExecutionPolicy,回复Restricted,表示状态是禁止的
然后执行:set-ExecutionPolicy RemoteSigned
选择Y

5、Express路由

5.1.路由的概念

image-20220323235459888

5.2.路由的简单使用

const express = require('express')
// 创建web服务器,并命名为app
const app = express()

// 挂载路由
app.get('/',(req,res)=>{
  res.send("get succeed")
})

app.post('/',(req,res)=>{
  res.send('post succeed')
})

// 启动web服务器
app.listen('80',()=>{
  console.log('express server running at http://127.0.0.1');
})

5.3.创建路由模块

0.3router.js:

// 1、导入express
const express = require('express')

// 2、创建路由对象
const router = express.Router()

router.get('/user/list',(req,res)=>{
  res.send('Get user list')
})

// 3、挂载具体路由
router.post('/user/add',(req,res)=>{
  res.send('Add new user')
})

//4、向外导出路由对象
module.exports = router

使用路由:

02.使用模块化路由.js:

const express = require('express')

const app = express()

// 1、导入路由模块
const router = require('./03.router')

// 2、注册路由模块
app.use('/api',router)

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

5.4.使用路由前缀:

​ app.use('/api',router)

6、Express中间件

6.1.Express的中间的本质

image-20220324210907683

6.2.next函数的作用:

image-20220324210825519

6.3.全局生效的中间件:

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

通过调用app.use(中间件函数),即可定义一个全局生效的中间,代吗如下

const express = require('express');

const app = express()

//全局生效中间件
// const mw = function(req,res,next){
//   console.log("这是最简单的路由中间件");
//   next()
// }
// app.use(mw)

//全局生效中间件的简写形式:
app.use((req,res,next)=>{
  console.log('这是最简单的路由中间件2');
  next()
})

app.get('/',(req,res)=>{
  console.log('get succeed');
  res.send('get succeed')
})

app.listen(80,()=>{
  console.log("express server running at http://127.0.0.1");
})

运行结果:会最先运行中间件,然后再运行get/post请求

image-20220324213446109

6.4.中间件的作用:

image-20220324214058478

实例代码:

const express = require('express');

const app = express()

app.use((req, res, next) => {
  const time = Date.now()
  req.startTime = time
  next()
})

app.get('/', (req, res) => {
  res.send('05 --- get succeed:' + req.startTime)
})

app.post('/', (req, res) => {
  res.send('05 --- post succeed:' + req.startTime)
})

app.listen(80, () => {
  console.log("express server running at http://127.0.0.1");
})

6.5.局部生效的中间件

const express = require('express')

const app = express()

// 定义中间件函数1
const  mw1 = (req,res,next)=>{
  console.log("调用了局部中间件1");
  next()
}
// 定义中间件函数2
const  mw2 = (req,res,next)=>{
  console.log("调用了局部中间件2");
  next()
}
// 局部中间件的使用方法,只在此路由中生效
app.get('/Home',[mw1,mw2],(req,res)=>{
  res.send('Home page')
})
// 使用多个局部中间件可以用 []  或者单独写都可以
// app.get('/Home',mw1,mw2,(req,res)=>{
//   res.send('Home page')
// })

// 中间件的局部调用不会影响↓这个路由
app.get('/user',(req,res)=>{
  res.send('User Page')
})

app.listen(80,()=>{
  console.log("express server running at http://127.0.0.1");
})

6.6.使用中间件的注意事项

  • 一定要在路由之前注册中间件
  • 客户端发送过来的请求,可以连续调用多个中间件进行处理
  • 执行完成中间件的业务代码之后,不要忘记调用next()函数
  • 为了放置代码逻辑混乱,调用next()函数后不要再写额外的代码
  • 连续调用多个中间件时,多个中间件之间,共享req和res对象

6.7中间件的分类

1.应用级别中间件:

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

2.路由级别的中间件:

image-20220325204025351

3.错误级别中间件

作用:专门用来捕获整个项目中发生的错误,从而防止项目一次奔溃的问题

const express = require('express')

const app = express()

app.get('/',(req,res)=>{
  // 认为制造错误
  throw new Error("系统内部错误")
  res.send('index page')
})

// 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的奔溃
app.use((err,req,res,next)=>{
  console.log('发生了错误:'+err.message);
  res.send('Error:'+err.message)

})

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

4.内置中间件的使用:

image-20220326154248695

POST Json类型的数据:

image-20220326162010324

POST urlencoded类型数据:

image-20220326162213033

服务器收到的数据为:

image-20220326162323997

示例代码:

const express = require('express')

const app = express()

// 注意:出了错误级别的中间件,其他中间件,必须在路由之前进行配置
// 通过express.json() 这个中间件,解析表单中的json格式的数据
app.use(express.json())
// 通过express.urlencoded()中间件,来解析表单中的url-encoded格式的数据
app.use(express.urlencoded({extended:false}))

app.post('/user',(req,res)=>{
  // 在服务器,可以使用req.body这个属性,来接收客户端发来的请求数据
  // 默认情况下,如果不配置解析表单数据的中间件,则req.body 默认等于undefined
  console.log(req.body);
  res.send('ok')  
})

app.post('/book',(req,res)=>{
  // 在服务器端:可以通过req.body来获取json格式的表单数据和url-encoded格式的数据
  console.log(req.body);
  res.send('ok')  
})

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

6.8自定义中间件

实现步骤:

1.定义中间件

2.监听req的data时间

3.监听req的end时间

4.使用querystring模块解析请求体的数据

5.将解析出来的对象挂载伟req.body,以便于后续的使用

6.将自定义中间件封装为模块

示例代码:

const express = require('express')
 
const app = express()
// 导入Node.js内置的querystring模块
const qs = require('querystring')

app.use((req,res,next)=>{
  //自定义中间件的业务逻辑
  // 1.定义一个str字符串,专门用来存储客户端发过来的请求体数据
  let str = ''
  // 2.监听req的data时间
  req.on('data',(chunk)=>{
    str += chunk
  })
  // 3.监听req的end时间
  req.on('end',()=>{
    // 在str中存放的是完整的请求体数据
    // TODO:把字符串格式的请求体数据,解析成对象格式
    const body = qs.parse(str)
    req.body = body
    console.log(req.body)
    next()
  })
})

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

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

对自定义中间件进行模块化的封装

​ 14.custom-body-parser.js:

// 导入Node.js内置的querystring模块
const qs = require('querystring')

const bodyParser =  (req,res,next)=>{
  //自定义中间件的业务逻辑
  // 1.定义一个str字符串,专门用来存储客户端发过来的请求体数据
  let str = ''
  // 2.监听req的data时间
  req.on('data',(chunk)=>{
    str += chunk
  })
  // 3.监听req的end时间
  req.on('end',()=>{
    // 在str中存放的是完整的请求体数据
    // TODO:把字符串格式的请求体数据,解析成对象格式
    const body = qs.parse(str)
    req.body = body
    console.log(req.body)
    next()
  })
}
module.exports = bodyParser

​ 使用自定义中间件模块:

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

// 1.导入自己封装的中间件模块
const cuntomBodyParser = require('./14.custom-body-parser')
// 2.将自定义的中间件函数,注册为全局可用的中间件
app.use(cuntomBodyParser)

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

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

7使用Express写接口

1.使用Express写接口

apiRotter.js

const express = require('express')
const router = express.Router()

//在这里挂载对应的路由
router.get('/get',(req,res)=>{
  // 通过req.query获取客户端查询字符串,发送到服务器的数据
  const query = req.query
  //调用res.send()方法,向客户端响应处理的结果
  res.send({
    status:0,       // 0 表示处理成功   1  表示处理失败
    msg:'GET 请求成功',
    data:query   //需要响应黑客户端的数据
  })
})

router.post('/post',(req,res)=>{
  // 通过req.body 或许请求体中包含的url-urlencoded格式的数据
  const body = req.body
  res.send({
    status:0,       
    msg:'POST 请求成功',
    data:body  
  })
})

module.exports = router

使用apiRouter:

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

// 配置解析表单数据的中间件
app.use(express.urlencoded({extended:false}))

//导入路由模块
const router = require('./16.apiRouter')

//把路由模块注册到app上
app.use('/api',router)

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

2.跨域的问题:

此链接可以获取在线的JQuery https://staticfile.org/

案例:

<!DOCTYPE html>
<html lang="en">

<head>
  
  <title>Title</title>
  <script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.min.js"></script>
</head>

<body>
  <button id="btnGET">GET</button>
  <button id="btnPOST">POST</button>

  <script>
    $(function () {
      $('#btnGET').on('click', function () {
        $.ajax({
          type: 'GET',
          url: 'http://127.0.0.1/api/get',
          data: { name: 'zs', age20 },
          success: function (res) {
            console.log(res);
          }
        })
      })
    })

    $(function () {
      $('#btnPOST').on('click', function () {
        $.ajax({
          type: 'GET',
          url: 'http://127.0.0.1/api/post',
          data: { bookname: '三国演义', author: '罗贯中' },
          success: function (res) {
            console.log(res);
          }
        })
      })
    })
  </script>
</body>
</html>

image-20220327174231777

上面的GET和POST存在跨域问题,解决接口跨域问题的方案有两种:

​ 1.CORS(主流的解决方案,推荐使用)

​ 2.JSONP(有缺陷的解决方案:只支持GET请求)

3.使用cors中间件解决跨域的问题

1.cors中间件的安装和使用

npm i cors 

使用 const cors = require('cors') 导入中间件

在路由之前调用 app.use(cors()) 配置中间件

安装完成后将上面的代码完善后便可以解决跨域问题了:

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

// 配置解析表单数据的中间件
app.use(express.urlencoded({extended:false}))

//在路由之前配置中间件,从而解决接口跨域问题
const cors = require('cors')
app.use(cors())

//导入路由模块
const router = require('./16.apiRouter')

//把路由模块注册到app上
app.use('/api',router)

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

4.什么是CORS?

image-20220327174935750

2.CORS的注意事项

image-20220327175054225

3.CORS响应头部 -Access-Control-Allow-Origin

image-20220327175331347

image-20220327175348530

4.CORS响应头部-Access-Control-Allow-Headers

image-20220327192430083

5.CORS响应头部-Access-Control-Allow-Methods

image-20220327193828878

5.CORS的分类

1.简答请求

image-20220327195310541

2.预检请求

image-20220327195515531

3.简答请求和预检请求的区别

image-20220327200002774

6.JSONP写接口

1.JSONP的概念与特点

image-20220327200326896

2.创建JSONP接口的注意事项

image-20220327200535099

代码的具体实现:

//鼻血在配置cors中间件之前,配置 JSONP 的接口
app.get('/api/jsonp',(req,res)=>{
  // TODO:定义JSONP接口具体的实现过程
  // 1.得到函数的名称
  const funName  = req.query.callback

  //2.定义要发送到客户端的数据对象
  const data = {name:'zs',age:22}
  // 3.拼接出一个函数的调用
  const  scriptStr = `${funName}(${JSON.stringify(data)})`
  // 4.把拼接出的字符串,响应给客户端
  res.send(scriptStr)
})

posted on   IT丶Hatcher  阅读(371)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示