前言

若文章有误,欢迎读者留言反馈

一篇文章学会express后台框架

express介绍

链接地址:https://www.expressjs.com.cn

Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。搭建web服务器

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

使用Express开发框架可以非常方便、快速的创建Web网站的服务器或API接口的服务器

基本流程

创建项目文件夹

安装一个nodemon工具,代码改变之后自动重启

1
2
3
4
5
# 全局安装【全局安装一次后就不需要重复安装了】
npm i -g nodemon

# 执行node脚本
nodemon 脚本文件名

初始化生成包管理文件package.json

1
2
3
npm init -y[不询问]

npm init

安装express生产包

1
npm i -S express

在项目文件夹下创建一个js文件

使用express

  1. 导入express模块
    • const express = require('express')
  2. 创建web实例
    • const app = express()
  3. 监听请求
    • 用户通过get方式访问根/输出hello world
    • app.get('/', (req, res) => { res.send('hello world') })
    • 用户通过post访问/post输出hello post
    • app.post(‘/post’, (req, res) => { res.send(‘hello post’) })
  4. 启动后台服务
    • app.listen(8080, () => { console.log('server is running at http://127.0.0.1:8080') })

请求类型

  1. GET: 查询请求类型
    1. 主要用于获取数据,一般用于首屏,展示首页,通过get方式,更快获取到数据进行渲染。
  2. POST:新增请求类型
    1. 发送更多的数据给后端,不像get是在地址栏,数据放到body中以form或者json【raw】格式向后台发送
  3. PUT:修改请求类型
    1. 修改是要条件的,修改条件的传递是通过地址栏传递的(restful规范)
    2. 修改的数据主体是通过请求体传递的(请求体发送方式与post一致)
    3. PUT也是由POST封装的
  4. DELETE:删除请求类型
    1. 删除是要条件的,删除条件的传递是通过地址栏传递的(restful规范)
    2. PUT也是由POST封装的

GET方式传参如何获取

通过req.query对象,可以访问到客户端通过查询字符串的形式发送到服务器的参数:

1
2
3
4
// http://localhost:8080/?id=12&name=aa
app.get('/',(req,res)=>{
console.log(req.query) // 获取到的直接就是个对象,{ id: '12', name: 'aa' }
})

动态参数传参

Express也支持类似于Vue中动态路由的形式传递参数,传递的参数通过 req.params 对象可以访问到:

1
2
3
4
5
6
7
8
9
10
11
// http://localhost:8080/123

// 必须的路由参数(不传就匹配不上,返回404错误)
app.get('/:id',(req,res)=>{
console.log(req.params.id) // 123
})

// 可选的路由参数(传递与否都不会报错)
app.get('/:id?',(req,res)=>{
console.log(req.params.id) // 123,没有就undefined
})

==通过?可以指定可传可不传,与正则表达式?一样==

静态资源托管

express提供了一个非常好用的方法,叫做 express.static(),通过此方法,可以非常方便地创建一个静态web资源服务器:

1
2
3
4
app.use(express.static('assets'))
// app.use()表示使用(中间件)
// 现在可以访问assets目录下所有的文件
// 如assets/a.jpg文件,则可以通过 : http://xxxx/a.jpg

express还支持给静态资源文件创建一个虚拟的文件前缀(实际上文件系统中并不存在),可以使用 express.static 函数指定一个虚拟的静态目录,就像下面这样:

前缀的使用意义:

  • 可以迷惑别人,一定程度上阻止别人猜测我们服务器的目录结构
  • 可以帮助我们更好的组织和管理静态资源
1
app.use('/static', express.static('assets'))

现在你可以使用 /static 作为前缀来加载 assets 文件夹下的文件了:

1
2
http://localhost:8080/static/a.jpg
http://localhost:8080/static/css/style.css

==使用app.use()方法一般写在具体的路由监听之前。==

静态资源托管eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
静态资源托管
+ 静态资源服务器,把静态资源变成url请求的样式。
+ express.static 是express封装好的中间件,专门用来设置静态资源托管的目录。
+ 需求:把某些图片放入服务器上。

*/
const express = require('express')//1.使用已经安装好的express

const app = express() //2.创建一个服务
// app.use 使用注册中间件
// 参数1.设置虚拟的目录 提供一些安全性
// 参数2 某个中间件,中间件是某个有特殊功能的一个方法或者函数。
app.use('/a/b/c',express.static('assets'))
// 3. 接口类型,get post put delete
// 参数1 接口名或者请求名
// 参数2 命名这个请求然后返回的内容,回调
app.get('/home',(req,res)=>{ //get传参 query传参
res.send('hello word')
})

app.listen(8080,()=>{
console.log('您的服务已经启动');
})

路由模块化

把路由拆分成多个js文件,每个js文件就是一个模块,【整个模块负责这个页面的所有请求】

路由模块化处理主要分以下几个步骤:

  1. 创建一个目录,一般是router目录,再创建一个js文件
    • 该文件即路由模块化文件
  2. 引入express模块,再通过express.Router方法创建路由模块对象router
    • const express = require(‘express)
    • const router = express.Router()
  3. 使用路由对象完成路由规则对应的业务编写
    • router.get(‘/gethome’, (req, res) => { res.send(‘hello gethome’) })
    • router.post(‘/posthome’, (req, res) => { res.send(‘hello posthome’) })
  4. 使用模块化导出
    • module.exports = router
    • 或者exports = router
  5. 在你的文件需要使用的地方引入路由模块化文件
    • const homeData = require(路径)
  6. 注册使用[使用的该文件也要引入express,创建实例,最后启动监听端口]
    • app.use(homeData)
路由模块化操作eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
路由模块化
+ 模块化,把路由拆分多个js文件,每个js文件就是一个模块。
*/
const express = require('express')//1.使用已经安装好的express

const app = express() //2.创建一个服务
// 1个页面有5接口,1个项目有100页面,我们就有500个接口。
// 模块化,home页面的接口放在一起,user页面接口放在一起,my个人中心接口放在一起。归类,模块化。
// app.get('/home',(req,res)=>{ //get传参 query传参
// res.send('hello home')
// })
// 模块化的导入操作
const homeRouter = require('./router/home.js')
app.use(homeRouter)
// app.get('/user',(req,res)=>{ //get传参 query传参
// res.send('hello user')
// })
const uerRouer = require('./router/user.js')
app.use(uerRouer)
// app.get('/my',(req,res)=>{ //get传参 query传参
// res.send('hello my')
// })
const myRouter = require('./router/my.js')
app.use(myRouter)
app.listen(8080,()=>{
console.log('您的服务已经启动');
})

中间件,post传递参数如何取值

==使用内置中间件 express.urlencoded({ extended: false }) 接收post表单数据的键值对【参数队列】==
==使用内置中间件 express.json() 接收json格式提交的数据 ==
两个可以同时使用,应对不同格式数据来取值,数据放在请求体中【body】
在接收完数据后,会将数据的对象形式挂载到req请求对象的body属性上

中间件操作eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 使用内置中间件 express.urlencoded({extended:false})  接收form数据的
// 使用内置中间 express.json() 接收json数据的
const express = require('express')//1.使用已经安装好的express

const app = express() //2.创建一个服务
app.use(express.urlencoded({extended:false}))
app.use(express.json())
app.post('/post',(req,res)=>{ //get传参 query传参
console.log('获取post参数',req.body); //{ age: '22', name: 'xiaohong' }
res.send('hello post')
})

app.listen(8080,()=>{
console.log('您的服务已经启动');
})

第三方中间件

使用第三方中间件来获取表单的数据 body-parser

  1. 安装 npm i -S body-parser
  2. 使用第三方中间件const body = require('body-parser')
  3. 接口处获取前端发送过来的数据req.body

第三方中间件操作eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 使用第三方中间件来获取表单的数据  body-parser
// 1.安装 npm i -S body-parser
const express = require('express')//1.引入express

const app = express() //2.创建一个服务
// 使用第三方的中间件
const body = require('body-parser') //包和目录 分清?
// app.use(body.urlencoded({extended:false})) //类似内置中间件 express.urlencoded({extended:false})

app.post('/post',body.urlencoded({extended:false}),(req,res)=>{ //3.书写接口
console.log('post参数',req.body); //{ id: '225', name: '小红' }
// throw new Error('参数丢失错误') //抛出一个错误
res.send('hello wrod')
})

app.post('/data',(req,res)=>{ //3.书写接口
console.log('post参数',req.body); //{ id: '225', name: '小红' }
// throw new Error('参数丢失错误') //抛出一个错误
res.send('hello wrod')
})

// 错误类型中间件 放在最末尾,用来捕获错误的,只要接口报错就执行错误中间件。来提示用户。
app.use((err,req,res,next)=>{
res.send('报错了,请从新访问')
})
app.use((req,res,next)=>{ //如果访问的接口不存在,就通知用户,提高体验度。
res.status(404).send('<h1>您访问的请求不存在,请确认后在从新访问!!!</h1>')
})
//启动服务
app.listen(8080)

404处理

404错误中间件也要求在所有的正常请求路由的后面去声明使用,不要放在路由的前面,否则会导致后面的路由都是404错误。

1
2
3
4
5
6
7
8
9
10
11
12
// 假设定义这个路由,但是实际请求的时候请求了/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状态码,然后再输出错误信息
})

cookie后台获取

HTTP是一个无状态协议,客户端每次发出请求时候,下一次请求得不到上一次请求的数据,我们如何将上一次请求和下一次请求的数据关联起来呢?如用户登录成功后,跳转到其他页面时候,其他的页面是如何知道该用户已经登录了呢?此时就可以使用到cookie中的值来判断用户是否登录,cookie可以保持用户数据。

cookie简介:cookie它是一个由浏览器(存储cookie)和服务器(产生cookie)共同协作实现的(cookie是存储于浏览器中)。cookie分为如下几步实现:

  • 服务器端向客户端发送cookie并指定cookie的过期时间。
  • 浏览器将cookie保存起来。
  • 之后每次请求都会将cookie发向服务器端,在cookie没有过期时间内服务器都可以得到cookie中的值。

express中操作的cookie使用cookie-parser模块。

cookie-parser模块(也是中间件),所以其也会去操作req,res对象;

  1. 设置cookie是通过res.cookie(name,value,[选项])
  2. 读cookie的时候需要通过req.cookies对象来获取。

安装cookie-parser模块

1
npm i -S cookie-parser

cookie操作eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
cookie
+ 前端的所有请求都默认是携带cookie的。
+ cookie有效期内,后端服务是可以获取cookie的值的。
1.npm i -S cookie-parser
*/
const express = require('express')//1.引入express
const cookie = require('cookie-parser')
const app = express() //2.创建一个服务
app.use(cookie()) //使用这个中间件
app.get('/post',(req,res)=>{ //3.书写接口
if(req.cookies.username){
res.send('欢迎您'+req.cookies.username+'再次回来')
}else{
res.cookie('username','小明',{ maxAge:1000 * 60 * 60 * 8 }) //8小时
res.send('小明登陆了')
}
})
//启动服务
app.listen(8080)

session

cookie操作很方便,但是使用cookie安全性不高,cookie中的所有数据存储在客户端浏览器中,数据很容易被伪造;所以一些重要的数据就不能放在cookie当中了,并且cookie还有一个缺点就是不能存放太多的数据,一般浏览大约在4k左右,为了解决这些问题,session就产生了,session中的数据保留在服务端的

数据放到cookie中是不安全的,我们可以在cookie中存放一个sessionId值,该sessionId会与服务器端之间会产生映射关系,如果sessionId被篡改的话,那么它就不会与服务器端数据之间产生映射,因此安全性就更好,并且session的有效期一般比较短,一般都是设置是20分钟左右,如果在20分钟内客户端与服务端没有产生交互,服务端就会将数据删除。

express操作session使用cookie-session模块

cookie-session包对session设置与获取都是基于req请求对象

安装:npm i -S cookie-session

session操作eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const express = require("express");
const session = require("cookie-session");
const app = express();
// cnpm i -S cookie-session
// session现在很少用,redis 缓存框架,速度超快,cookie+redis搭配
app.use(
session({
name: "sessionId", //类似token
// 给sessionid加密的key,随便填写,擦下键盘即可
secret: "afsfwefwlfjewlfewfef", //盐 提供加密的复杂度
maxAge: 20 * 60 * 1000, // 20分钟
})
);
app.get("/", (req, res) => {
if (!req.session["view"]) {
req.session["view"] = 1;
} else {
req.session["view"]++;
}
res.send(`欢迎您第 ${req.session["view"]} 次访问!`);
});
app.listen(8080);