express

简介

利用nodejs中http创建的服务器,在处理请求的时候,只能放在一个回调函数中,且判断也较为复杂。为了方便基于nodejs服务器的开发,有人对nodejs服务器的创建、请求处理等操作,进行了封装,比较常见的就是express。

可以说,express就是基于nodejs封装的一个框架,专业用于提供方便易操作的web服务器。

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

使用Express开发框架可以非常方便、快速的创建Web服务器的便捷方法。

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

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

初体验

下载安装:

npm init -y
npm i express -S

使用步骤

1.导入包

2.创建服务器

3.处理请求

4.监听端口

const express = require('express')
const app = express()
app.get(路由,回调) // get是请求方法
app.listen(端口号)

路由

含义:请求路径跟响应内容之间的对应关系。简单的说,这次路由:什么方式来的,请求路径是什么,响应什么。

路由方法

app.get()
app.post()
app.put()
app.delete()
app.all()

路径匹配

完全匹配

请求的路径必须跟定义好的完全相等,才会处理

// 匹配根路径的请求
app.get('/', function (req, res) {
  res.send('root');
});

// 匹配 /about 路径的请求
app.get('/about', function (req, res) {
  res.send('about');
});

// 匹配 /random.text 路径的请求
app.get('/random.text', function (req, res) {
  res.send('random.text');
});

不完全匹配

请求路径符合定义好的路径的规则即可处理:

// 匹配 acd 和 abcd
app.get('/ab?cd', function(req, res) {
  res.send('ab?cd');
});

// 匹配 abcd、abbcd、abbbcd等
app.get('/ab+cd', function(req, res) {
  res.send('ab+cd');
});

// 匹配 abcd、abxcd、abRABDOMcd、ab123cd等
app.get('/ab*cd', function(req, res) {
  res.send('ab*cd');
});

// 匹配 /abe 和 /abcde
app.get('/ab(cd)?e', function(req, res) {
 res.send('ab(cd)?e');
});

正则匹配

请求到的路径符合定义好的正则规则就可以处理:

// 匹配任何路径中含有 a 的路径:
app.get(/a/, function(req, res) {
  res.send('/a/');
});

// 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等
app.get(/.*fly$/, function(req, res) {
  res.send('/.*fly$/');
});

restful风格匹配

另外一种路径书写风格

app.get('/about/:id', function (req, res) {
  res.send('about');
});

表示在请求的时候,/about后面必须加一个id才可以成功去处理。

若要表示id为可选项的话,使用

app.get('/about/:id?', function (req, res) {
  res.send('about');
});

路由处理

处理某个请求路径的时候,可以使用一个函数,也可以使用多个函数,也可以使用多个函数组成的数组,也可以将数组和函数结合起来使用。

单函数处理

app.get('/home', function (req, res) {
  res.end('home');
});

多函数处理

app.get('/home', function (req, res, next) {
  console.log('这处理完之后会交给下一个函数处理');
  next();
}, function (req, res) {
  res.end('home');
});

注意:前面的函数必须加next,否则不走到下一个函数,因为next表示交给下一个函数处理的意思。

函数数组处理

var cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

var cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

var cb2 = function (req, res) {
  res.end('home')
}

app.get('/home', [cb0, cb1, cb2])

函数和数组混合处理

var cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

var cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

app.get('/home', [cb0, cb1], function (req, res, next) {
  console.log('CB')
  next()
}, function (req, res){
  res.end('home')
})

路由对象处理路由

路由除了可以使用服务器变量app处理外,还可以使用express提供的路由变量来处理:

const express = require('express')
const app = express()
const router = express.Router() // 创建路由变量
router.get(路由,回调)
app.listen(端口号)

use处理路由

use方法也可以用来处理路由:

const express = require('express')
const app = express()
app.use('/home', (req, res) => {
    res.end('hello')
})
app.listen(12345)

使用浏览器请求的时候,如下两个路径都可以处理:

http://localhost:12345/home

http://localhost:12345/home/a

也就是说use方法,是一种不完全匹配路由的处理方法,他的匹配是只要/home开头的都可以处理。

如果后面的请求路径,希望在被use方法处理后,可以继续被后面的处理方法处理,可以给use方法的回调函数中,调用next方法。

app.use('/home', (req, res, next) => {
    console.log(111);
    next()
})

app.get('/home/a', (req, res) => {
    res.end('hello222')
})

use方法还可以进行过滤请求路径,如果use方法中将请求路径省略掉的话,就表示所有请求都会先经过这个路由:

app.use((req, res, next) => {
    console.log(111);
    next()
})

app.get('/home', (req, res) => {
    res.end('home')
})

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

use方法配合路由对象来处理,可以将路径截取:

完整请求路径为:/used/add

app.use('/user', router)

router.get('/add', (req, res) => {
    res.end('/user/add')
})')})

将这次路由交给router去处理,router在进行具体处理的时候,路径不能在前面加use中的路径了,因为被use截取了。

路由模块化

利用use方法和router结合,我们可以将某一部分的请求单独封装到一个文件中,例如,所有有关用户的请求,都会是/use开头的请求路径,将所有有关用户请求的路由处理,单独封装在一个文件中。

app.js

const express = require('express')
const app = express()
const userRouter = require('./user')
app.use('/user', userRouter)
const goodsRouter = require('./goods')
app.use('/goods', goodsRouter)
app.listen(12345)

user.js

const express = require('express')
const router = express.Router()
router.get('/add', (req, res) => {
    res.end('/user/add')
})
router.get('/edit', (req, res) => {
    res.end('/user/edit')
})
module.exports = router

good.js

const express = require('express')
const router = express.Router()
router.get('/add', (req, res) => {
    res.end('/goods/add')
})
router.get('/edit', (req, res) => {
    res.end('/goods/edit')
})
module.exports = router

响应方法

res.end() // 终结响应处理流程。
res.json() // 发送一个 JSON 格式的响应。
res.redirect() // 重定向请求。
res.send() // 发送各种类型的响应。
res.sendFile() // 以八位字节流的形式发送文件。
res.sendStatus() // 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。
res.render() // 渲染视图模板。

中间件

中间件(middleware)可以理解为业务流程的中间处理环节,可以理解成中间处理器。

简单的说,中间件就是一个中间处理器,每次经过最终处理的回调函数前,先经过这个中间处理器,这个中间处理器就是中间件。

中间件的分类

根据中间件的开发者,可以将中间件分为三类:

1.内置中间件 - express系统自带

2.自定义中间件 - 自己开发的中间件

3,第三方中间件

根据中间件的使用情况,可以将中间件分为两类:

1.应用级别中间件 - 由app调用的

  • 全局应用级别的中间件 - 当前路由后面的所有请求都会经过这个中间件
  • 局部应用级别的中间件 - 只在当前路由处理中有效

2.路由级别中间件 - 由router调用的

  • 全局路由级别中间件
  • 局部路由级别中间件 

中间件其实多个函数处理路由器时,前面的、必须调用next的函数,就是中间件。所以说,中间件本质上是一个函数。

中间件在使用的时候,必须要用use方法使用。

应用级别的使用:

app.use(中间件函数)

 路由级别的使用:

router.use(中间件函数)

上面两种使用都是全局的,表示他们后面的路由处理都要经过这个中间件。

局部的使用:

应用级别

app.use(路径, 中间件, 回调函数)

路由级别

router.use(路径, 中间件, 回调函数)

内置中间件

express提供了好用的内置中间件。

1.静态资源服务器中间件:express.static()

app.use(express.static('托管目录地址')) 

此时我们可以通过 /静态资源名称 就能访问到指定文件夹中的静态资源

app.use('前缀',express.static('托管目录地址'))

为了方便区分静态资源路径和其他请求的处理,可以指定静态资源的时候,使用指定的路径前缀,

此时我们可以通过 /前缀/静态资源名称 来访问到指定文件夹的静态资源。

2.获取post请求传递的请求主体:express.urlencoded()

app.use(express.urlencoded({extended: false}))

此后的post请求都可以通过 req.body获取到post请求传递的请求主体了。

这个中间件有版本要求:express>=4.16.0

自定义中间件

自定义中间件,本质上是一个函数,相当于我们使用多个函数处理请求的时候,中键经历的函数。

function mfn(req,res,next){	
    //. 自己需要定义的逻辑流程
	// 中间件最后一定要执行此函数,否则程序无法向下执行下去
	next()
}

注意:在整个请求链路中,所有中间件与最终路由公用一份req和res

第三方中间件

很多功能都可以通过别人写好的插件来实现,例如body-parser

body-parser这个中间件的功能是用来获取post请求传递的请求主体的。使用步骤如下:

1.下载

npm i body-parser

2.导入

const bodyParser = require('body-parser')

3.使用中间件

app.use(bodyParser.urlencoded({extended: false}))

异常处理中间件

当我们在某次请求处理的时候,发生了错误,会给客户端抛出报错,这个报错会让用户有不好的体验感,也容易将自己服务器所在的文件目录解构暴露。为了能解决以上两个缺点,我们可以在发生错误的时候,给用户以比较友好的自定义内容响应。这就是异常处理中间件

app.get('/',(req,res) => {
    throw new Error('服务器内部发生了致命的错误!')
    res.send('Welcome to my homepage')
})

app.use((err,req,res,next) => {
    console.log('发生了错误:' + err.message) // err.message代表具体的错误信息
    res.send('Error!' + err.message)
})

404中间件

当用户发起了一个服务器并没有处理的请求,此时会在页面中输出404,会给用户造成不好的体验感,为了能避免这个问题发生,我们可以在访问到没有处理请求的时候,给用户响应自定义的内容。

// 该中间件也需要写在最后(与异常中间件的顺序无所谓,只要确保其在所有的路由方法之后就可)
app.use((req,res,next) => {
    // 输出404错误
    res.status(404).send('<h1>404</h1>')
    // 先指定404状态码,然后再输出错误信息
})

模板页面:页面:404模板网_重新定义404页面

express脚手架

脚手架:就是一个用来自动生成项目的工具,可以快速生成项目解构。

使用步骤:

# 下载安装
npm i -g express-generator
# 安装好以后,有一个命令可以使用:express
# 生成项目
express 项目名称

安装依赖模块:进入项目目录,执行命令:npm i

运行项目:npm start

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值