46 express

 

 

46 express

一、简介

Express是基于基于 Nodejs平台,快速、开放、极简的 Web 开发框架

官网地址:https://www.expressjs.com.cn/

作用:使用 Express,我们可以方便、快速的创建 Web 网站的服务器或 API 接口(纯json数据)的服务器。

本质上:express是一个第三方包存在于npm社区中。

二、安装及基本使用

2.1安装

初始化package.json:npm init -y

下包:npm i express

2.2深刻体会一下模块化的好处

我们项目中使用express,所以只下载express即可。而express使用什么我们不关心,由express来进行管理 。

 

2.3初体验express

原生node 比较麻烦:编码、路径判断的问题、响应js对象:原生node只能返回字符串或buffer(不允许)

const express = require('express')

// console.log( express );
const app = express()  //创建一个服务器应用



app.listen( 3000,()=>{
   console.log( 'http://localhost:3000 可以访问' )
} )

2.4 app对象

注意:所有的路径都以 / 打头

app.get( 路径,兼听函数 )

兼听客户发送的get请求

callback( req,res )

前端要做的是会向服务器发get请求

除了表单的mthod="post"和ajax( method:'post' ),在浏览器中的其它请求都是get。

mthod="get" ajax( method:'get' ) img:src link:href script:src 这些通通都是get请求。

 

app.post(路径,兼听函数 )

兼听客户端发送的post请求

表单的mthod="post"和ajax( method:'post' )

2.5response对象

res.send( 字符串|对象 )。

可以发送字符串,也可以发送对象。并且这个方法会根据数据自动设置Content-type。

express框架基于原生http的,express没有覆盖原生httpp。原生的req和res对象上的方法还都可以用。res.end()

res.sendFile( absolute filepath )

把服务器上的某一个文件响应给用户。

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

   //let filepath = path.join( __dirname,'./pages/03register.html' )
   let filepath = path.join( __dirname,'./pages/erha.jpg' )

   res.sendFile( filepath )
})

总结:前端用户发的请求,拿的结果完全取决于后端返回的是什么。跟路径没有必然联系(这是比较抽象的一句)。

 

2.6 request对象

req.query

作用:接收 url地址栏 ?后面的查询字符串参数。简称get的参数

// 前端应该也是必须会拼接url地址。
// http://localhost:3000/login?username=swk&age=20
app.get('/login',(req,res)=>{
   console.log( req.query,'默认是一个空对象' )  //:获取get参数。默认是一个空对象
   console.log( req.query.username )

   if( req.query.uage > 18 ){
       res.send('我成年了')
  }else{
       res.send('呵呵,不要惹熊孩子')
  }
   
})

req.params

专业名称:动态路径(路由)

https://movie.douban.com/subject/34841067/

https://movie.douban.com/subject/26826330/

https://book.douban.com/subject/35315159/

url / :变量名称[参数名称]

比如豆瓣电影的地址: https://movie.douban.com/subject/ ids

而这类的路径上的参数用 req.params 获取 。

 

往服务器传递的参数都是字符串。由http协议规定的。互联网中传递数据只能传递字符串。

三、工具的使用

nodemon

开发web服务器后端代码,每次修改代码需要重新node一下。

而nodemon工具帮我们这个问题。它是一个全局包( 是个工具 )

使用步骤

  • npm i nodemon -g

  • 使用nodemon去运行后端js代码。如 : nodemon app.js

Rest Client

测试接口的工具,简单来说类似于ajax,类似于浏览器地址栏 。

有了此工具那么测试任意请求就非常方便 。

基于vscode的插件而已。

优点:测试记录都有保存留痕

使用步骤

  • 安装插件

     

  • 创建以http为后缀的文件

    比如:api22.http

  • 书写请求地址,发送请求

 


@url = http://localhost:5000

###
GET {{url}}/login


### 3个#来区分每一个请求
# 也可以写注释
post http://localhost:3000/login

 

四、路由

1.路由概述

什么是路由?

广义上来讲,路由就是映射关系。

对于我们网络请求中的路由是:每一次请求对应每一个请求处理的函数。

现实中的路由

例如手机或者电话进行拨号可以根据映射关系得到不同的服务。

 

路由的作用

在web开发中,路由是非常重要的一个体系。访问不同的路由可以得到对应路由的服务。

/login 登录功能

/register 注册功能

/pay 支付功能

2.Express中的路由(Node的路由)

语法:

app.method( 路径地址,callback )

app: 由express() 返回的app实例对象

method:函数的通用名称。 get/post( 定义get路由 ,定义post路由)

路径地址:必须以 “/” 开头

callback:请求处理的函数。准确的说有4个参数。前两个:第1个request对象 ,第2个response对象

完整的路由定义一定是由此语法决定的,缺一不可。

 

匹配流程:

(1)每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数

匹配成功( 一个请求方法、请求路径地址 )

(2)在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理

主要是处理业务,并且把最终的结果响应给前端

(3)如果从上到下有相同的路由,则会匹配第1个。定义相同的路由是没有意义的

 

//get的路由匹配
app.get('/login',(req,res)=>{
   res.send('我匹配到了get请求,并且是login1')
})

app.get('/login',(req,res)=>{
   res.send('我匹配到了get请求,并且是login2')
})

//post的路由匹配
app.post('/login',(req,res)=>{
   res.send('我匹配到了post请求,并且是login')
})

//动态路由匹配
app.post('/su/:id',(req,res)=>{
   res.send('动态路由匹配')
})

3.模块化路由

优化入口文件,否则的话你的项目入口太臃肿。按照项目开发规范来说,应该把所有的路由分离出去。

需求:

教务管理系统:人员管理(学生、老师、管理员)。

学生:添加、删除、修改、查询

老师:添加、删除、修改、查询

未模块化的路由的问题

const express = require('express')

const app = express()

// **需求:**

// 教务管理系统:人员管理(学生、老师、管理员)。
// 学生:添加、删除、修改、查询
// 老师:添加、删除、修改、查询

app.get('/student/add',(req,res)=>{
res.send('添加一个学生')
})

app.get('/student/delete',(req,res)=>{
res.send('删除一个学生')
})

app.get('/student/edit',(req,res)=>{
res.send('修改一个学生')
})

app.get('/student/query',(req,res)=>{
res.send('查看一个学生')
})

/////////////////////////////////////////

app.get('/teacher/add',(req,res)=>{
res.send('添加一个学生')
})

app.get('/teacher/delete',(req,res)=>{
res.send('删除一个学生')
})

app.get('/teacher/edit',(req,res)=>{
res.send('修改一个学生')
})

app.get('/teacher/query',(req,res)=>{
res.send('查看一个学生')
})

app.listen(3000,()=>{
console.log( 'http://localhost:3000' )
})

模块化的路由

语法:

const express = require('express')
const router = express.Router() //实例化一个路由对象

//定义路由
router.get('/login',callback)
router.get('/student/add',callback)

module.exports = router //暴露路由对象

/////////////////////////////////////////////////////////////////
//要在使用的地方引入以上的路由模块
let r = require('自定义路由模块的路径地址')
app.use( r )

 

//student.js
const express = require('express')

//实例化路由对象
const app = express.Router()

app.get('/student/add',(req,res)=>{
res.send('添加一个学生')
})

app.get('/student/delete',(req,res)=>{
res.send('删除一个学生')
})

app.get('/student/edit',(req,res)=>{
res.send('修改一个学生')
})

app.get('/student/query',(req,res)=>{
res.send('查看一个学生')
})

//暴露路由
module.exports = app

 

app.use的另一个语法

app.use( ‘/前缀’,路由 )

//teacher.js
app.use( '/teacher',teacherRouter )

 

五、中间件

中间件(Middleware ),特指业务流程的中间处理环节( 指路由当中的处理层:指的就是函数 )。本质上中间件就是函数

中间件其实就是一个特殊的路由、升级版的路由。中间件函数都会被所有的请求匹配到。

好处:提升我们的开发效率 。

现实中的中间件

我们可以把中间件函数比作工厂中的车间

说明中间件的原理。

每一个车间都是独立的功能 。各司其职,谁也别影响谁。

特点:在一个车间(中间件中)处理完了,必须往下走next,必须 匹配一个最终的路由并且响应结果数据

 

中间件执行流程

 

使用中间件

1.语法

中间件没有特殊情况,一般都是在所有的路由前面 。

app.use( [前缀,]中间件函数 )
callback( req,res,next )
中间件和路由中的req是共用 的。
何时加前缀?某些不需要匹配到中间件,有些请求需要匹配到中间件,所以可以为某些路由(中间件)添加一些前缀

2.自定义一个中间件

需求:后端要获取用户的请求时间 。

未使用中间件

const app = express()
const timeStamp = require('time-stamp')
// 后端要获取用户的请求时间 。

// console.log( timeStamp('YYYY年MM月DD日 HH:mm:ss') )


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

let times = timeStamp('YYYY年MM月DD日 HH:mm:ss')
res.send(`login访问时间是:${times},后端想要统计的`)
})

app.get('/register',(req,res)=>{
let times = timeStamp('YYYY年MM月DD日 HH:mm:ss')
res.send(`register访问时间是:${times},后端想要统计的`)
})

 

使用中间件优化好的

const timeStamp = require('time-stamp')
// 后端要获取用户的请求时间 。
// console.log( timeStamp('YYYY年MM月DD日 HH:mm:ss') )

// let times = ''
app.use( (req,res,next)=>{
// console.log('匹配到了中间件函数')
req.times = timeStamp('YYYY年MM月DD日 HH:mm:ss')
next()//往下走,去找真正要匹配的路由规则
} )


app.get('/login',(req,res)=>{
// console.log(times);
res.send(`login.通过中间件往req对象上绑定了times属性。所以时间为 :${req.times}`)
})

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

res.send(`register 通过中间件往req对象上绑定了times属性。所以时间为 :${req.times}`)
})

 

中间件种类

错误中间件

404和逻辑错误

内置中间件

static

urlencoded

json

第三方中间件

server-icon

svg-captcha

 

六、文件上传

七、cookie

介绍

特点

应用场景

实现原理

 

八、session

简介

特点

应用场景

实现原理

九、模板引擎

 

十、express脚手架

 

十七、koa框架

 

 

前后端数据交互总结

 

请求方法编码格式前端要传输的数据格式后端如何获取应用场景
GET url地址后面(querystring) url?key1=value1&key2=value2 不需要中间件:req.query 获取数据
POST applicaion/x-www-form-urlencoded form-data: key1=value1&key2=value2 express.urlencoded( { extend:true } ) 提交数据
POST applicaion/json(只能通过ajax) request-payload: '{ "key1":"value1","key2":"value2" }' express.json()  
POST mutilpart/form-data(可以使用表单) 文件流   文件上传
DELETE 同post     删除数据
PUT 同post     更新数据
posted @ 2021-05-07 22:24  一花一世界111  阅读(87)  评论(0)    收藏  举报