这几天天天搞到这么晚,我看明天的内容看起不多啊,不晓得为什么学着学着就到了这么晚。明天的内容还是有点多哈,有点自我矛盾了,再次一一道来。
1.
首先明天先看到路由的概念,什么叫做路由?
路由就是映射关系,在express中路由指的是客户端申请和服务器处理函数的映射关系,路由有三局部组成:申请类型、申请url和处理函数。
app.get(url,callback)其实就跟咱们后面所说的监听事件一样一一样的。
const express = require('express')const app = express()app.get('/', (req, res) => { res.send('收到get申请')})app.listen(80, () => console.log('express server running at http://127.0.0.1'))
这就是一个最简略的路由。路由的匹配过程,每当一个申请达到服务器器后,须要先通过路由匹配,当申请类型和url匹配胜利后才会调用前面的申请函数。、
用法
最简略的用法就是像咱们下面那样间接挂在实例上,这也是不举荐的,因为一个申请就要挂一个很麻烦很繁琐。
迷信的办法应该是创立路由模块。
分为五个步骤:
别离是创立路由js文件、调用express.Router创立路由对象、挂载路由、向外导出路有对象最初咱们的入口文件须要导入,在通过app.use去注册
// 1.导入expressconst express = require('express')// 2.创立路由对象const router = express.Router()// 3.挂载路由// 3.1挂载路由获取用户的信息router.get('/user/:id', (req, res) => { res.send(req.params)})// 3.2挂载路由承受用户发送的申请router.post('/post', (req, res) => { res.send('post胜利')})// 4.向外共享路由成员module.exports = { express, router }
const express = require('./02模块化路由')const app = express.express()// 注册路由app.use(express.router)app.listen(80, () => console.log('express server running at http://127.0.0.1'))
这里说一下app.use昨天也看到了,他其实就是一个用来注册全局中间件的。而后咱们还能够为路由挂载前缀,也是通过app.use来增加办法同昨天根本一样
2.
中间件
指的是业务流程的两头解决环节。
就是当客户申请达到服务器后,可间断调用多个中间件对这个申请进行预处理,最初通过路由发送进去。
中间件的实质是一个函数根路有相似然而多了一个参数,next参数。
next是一个函数它的作用就是实现多个中间件间断调用的要害,把流转关系转给下一个中间件或者路由,每个中间件都有一个next一个转下去转到路由没有了就响应给客户端了。
2.1
咱们先看到全局失效的中间件,意思就是客户发动的任何申请,他都会触发,间接通过app.use来注册即可
const express = require('express')const app = express()// 中间件const mw = function(req, res, next) { // res.send('这是中间件环节') console.log('这是中慢慢环节') next()}// 通过app。use定义为全局失效的中间件app.use(mw)app.get('/user', (req, res) => { res.send('这是get申请')})app.post('/post', (res, req) => { res.send('这是一个post申请')})app.listen(80, () => { console.log('http://127.0.0.1');})
中间件的作用:
多个中间件共享同一个res和req,所以能够在上游的中间件定义好这些对象,上游间接用包含路由也能够用
怎么来定义多个全局中间件,间接通过app.use定义多个即可就像昨天所说的托管动态资源,有多个目录就注册多个
2.2
部分中间件
不是用app.use只对局部的路由无效,路由 的参数规定 也产生了扭转
const express = require('express')const app = express()const mw = function(req, res, next) { req.time = Date.now() next()}app.get('/', mw, (req, res) => { res.send('部分失效' + req.time)})app.get('/user', (req, res) => res.send('没有失效') + req.time)app.listen(80, ()=> { console.log('http://127.0.0.1');})
定义多个部分中间件
写多个函数过后在参数这里能够用逗号隔开,也能够间接写一个数组
有一个注意事项:就是肯定要在路由之前去注册中间件,不然路由执行完了谁还来执行中间件。
2.3
中间件的分类
①利用级别中间件
就是通过get、post、use绑定到app上的中间件
②路由级别中间件
就是在咱们方才的路由模块外面来交叉的一个中间件
③谬误级别中间件
这个有点说法
它是专门用来捕捉错误信息的而且形参变为了四个
他也是惟一一个卸载路由前面的中间件
const express = require('express')const { rename } = require('fs')const app = express()app.get('/', (req, res) => { // 1.人为抛出一个谬误,一旦有错前面的响应就不会执行了 throw new Error('服务器外部产生谬误') res.send('我不能执行进去')})// 2.谬误中间件app.use((err,req,res,next) => { // 2.1向服务器打印谬误 console.log(err.message); // 2.2向客户端发送谬误 res.send(err.message) // 这样做 益处就是,后面如果产生了谬误导致了整个服务器曾经解体了,什么都执行不了了,这样一来,就能够失常输入错误信息,失常执行前面代码})app.listen(80, () => console.log('express server running at http://127.0.0.1'))
④内置中间件
三个内置的中间件别离是express.static这个曾经说过了后面
express.json这是拿来解析json格局数据的
express.urlencoded这是拿来解析urlencoded格局数据的
前面两个个别会配合req.body来拿申请体数据再给他们拿来解析了
const express = require('express')const app = express()// 留神这是中间件 所以必须配置到路由之前app.use(express.json())app.use(express.urlencoded({extended : false}))app.post('/', (req, res) => { // 通过req.body能够拿到申请体数据 // postman在测试的时候抉择body外面的raw再把text抉择json就能够发送json数据了 console.log(req.body); // 没有解析之前对于json数据是undefined})// 测试urlencoded数据体// 这个数据体的格局是x-www-form-urlencoded// 固定写法app.post('/user', (req, res) => { // 没解析前时空对象 console.log(req.body);})app.listen(80, () => console.log('express server running at http://127.0.0.1'))
⑤第三方中间件 间接npm装置导入通过app.use注册即可应用
2.4
自定义中间件
这里做一个案例自定义一个相似于express.urlencoded性能的中间件能够解析申请体数据
const express = require('express')const app = express()// 4.利用node外面的一个内置模块解析申请体数据,在node外面内置了一个querystring模块是专门用来解决查问字符串的,这个模块提供的// parse()函数能够把查问字符串转换为对象const qs = require('querystring')// 1.定义中间件app.use((req, res, next) => {// 2.监听data事件,因为既然是服务器,那么必定会接管到癞子客户端的申请,如果有时候申请量过大,就会分批次传给服务器数据,所以data事件可能触发屡次// 就须要把每一次的数据最初拼接起来let str = ''req.on('data', chunk => { str += chunk})// 3.req的end事件当申请体接管结束会主动登程end事件能够在这里解决残缺的申请体数据req.on('end', () => { console.log(str); str = qs.parse(str) console.log(str); // 5.解说洗出来的对象给到req.body req.body = str next()})})app.post('/', (req, res) => { res.send(req.body)})app.listen(80, () => console.log('http://127.0.0.1'))
而后将自定义中间件进行了一个模块化
// 4.利用node外面的一个内置模块解析申请体数据,在node外面内置了一个querystring模块是专门用来解决查问字符串的,这个模块提供的// parse()函数能够把查问字符串转换为对象const qs = require('querystring')// 因为他人导入进来是间接注册应用所以能够把app开服务器等一些多余的代码省略就保留app.use外面的const bodyParse = (req, res, next) => { // 2.监听data事件,因为既然是服务器,那么必定会接管到癞子客户端的申请,如果有时候申请量过大,就会分批次传给服务器数据,所以data事件可能触发屡次 // 就须要把每一次的数据最初拼接起来 let str = '' req.on('data', chunk => { str += chunk }) // 3.req的end事件当申请体接管结束会主动登程end事件能够在这里解决残缺的申请体数据 req.on('end', () => { console.log(str); str = qs.parse(str) console.log(str); // 5.解说洗出来的对象给到req.body req.body = str next() })}module.exports = bodyParse
const bodyParse = require('./自定义中间件模块化')const express = require('express')const app = express()app.use(bodyParse)app.post('/', (req, res) => { // res.send('收到get申请') console.log(req.body);})app.listen(80, () => console.log('express server running at http://127.0.0.1'))
3.
咱们持续看到用express来写接口
分为了三个步骤
创立根本服务器、创立 api路由模块、编写get接口
这是路由模块
// 2.写api路由模块 就是将路由模块化 因为那边引入进来须要用use来注册同时挂载api前缀const express = require('express')const router = express.Router()// 3.编写get接口router.get('/get', (req, res) => { // 3.1首先拿到用户传过来的数据 let data = req.query // 3.2把数据发送给客户端 res.send({ status : 0, // 0示意胜利 1示意失败 msg : 'get申请胜利', data : data //把数据返回给客户端 })})// 4.编写post接口router.post('/post', (req, res) => { // 4.1客户端发过来的数据 let data = req.body res.send({ status : 0, msg : 'post申请胜利', data : data })})module.exports = router
其实次要就是通过req的那几个属性拿到数据后,再通过send办法发给客户端,上面是入口文件次要就是开启服务器,而后解析下数据
// 1.创立根本web服务器const express = require('express')const app = express()// 2.1导入路由模块 并挂载前缀const router = require('./router')// 4.2注册内置中间件 不然req.body解析不进去 app.use(express.urlencoded({extended : false}))// 5.cors解决跨域const cors = require('cors')app.use(cors())app.use('/api', router)app.listen(80, ()=> { console.log('http://127.0.0.1');})
有些货色要把前面看了才晓得哈我只是先拿上来了。
4.
cors和jsonp
咱们方才这个案例其实是有bug的,就是有跨域的问题,咱们创立一个html文件通过button来获取数据这个时候就会因为协定不同而被同源策略组织。
咱们后面也说过解决跨域一个是cors一个是jsonp,这里必定不能用jsonp因为他只反对get,那么怎么来用cors呢?
间接三部曲装置导入加注册就解决了跨域问题了,就这么简略。
4.1
什么是cors
就是由一系列http响应头组成,同源策略碰到这个头就会解除限制。
cors个别是在服务器进行配置,客户端不须要。
上面是一些理解性内容
响应头部:
第一个res.setHeader(‘Access-Control-Allow-Orign’,‘http:wwwssss。聪慧、’)
这是示意只容许前面这个网站的域来拜访,如果为*那就示意容许任何域来拜访了
第二个是后面的根底上为Allow-Headers
咱们的cors默认值只有9个申请头如果超出了这个九个头就必然失败申请,在这个九个之外的能够通过这个代码来增加上来
第三个后面的根底上-Methods
cors默认只反对get post head 除此之外的须要用这个来设置。
4.2
当初不是理解内容了。
cors申请分类
大体上分为简略申请和预检申请。
什么叫做简略申请
满足两个条件:
一个是申请形式在默认的三个之内,一个是http申请头不能超过默认的九个
什么是预检申请
三个条件达到其中一种都是
一个是申请头在九个之外,一个是申请形式在三个之外,还有一个就是发送过去的数据是json数据
那么他们的区别是什么呢
很简略,简略申请只会发送一次申请,而预检申请会发送两次申请,为什么?
因为预检申请会在服务器与客户端正是连贯之前,提前发一个option的申请作为预检,看服务器是否跟这个格局的申请相连接,只有申请胜利了才会开始正式申请,携带实在数据。
5.
明天最初一个内容jsonp接口
首先要留神一下,如果说曾经配置了cors那么必须在配置cors之前去申明jsonp接口,不然会错乱的。
做这个接口之前咱们先来回应一下jsonp的一个常识,首先它是来解决跨域的,咱们通过script标签把函数传进来再去调用接口这种形式就叫jsonp
// 1.创立根本web服务器const express = require('express')const app = express()// 2.1导入路由模块 并挂载前缀const router = require('./router')// 4.2注册内置中间件 不然req.body解析不进去 app.use(express.urlencoded({extended : false}))// 6.jsonp接口必须写在coes之前app.get('/api/jsonp', (req, res) => { // 6.1获取回调函数的名字 let fn = req.query.callback // 6.2定义你要发送回去的数据对象 let data = {name : '张三', age : 15} // 6.3模仿函数调用 let fnDiao = `${fn}(${JSON.stringify(data)})` // 6.4数据返回回去 res.send(fnDiao)})// 5.cors解决跨域const cors = require('cors')const { json } = require('body-parser')app.use(cors())app.use('/api', router)app.listen(80, ()=> { console.log('http://127.0.0.1');})