node.js - 路由、中间件、mysql
这几天天天搞到这么晚,我看今天的内容看起不多啊,不知道为什么学着学着就到了这么晚。今天的内容还是有点多哈,有点自我矛盾了,再次一一道来。
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.导入express
const 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');
})
node.js - 路由、中间件、mysql的更多相关文章
- KoaHub.JS基于Node.js开发的mysql的node.js驱动程序代码
mysql A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 10 ...
- Node.js:连接 MySQL
ylbtech-Node.js:连接 MySQL 1.返回顶部 1. Node.js 连接 MySQL 本章节我们将为大家介绍如何使用 Node.js 来连接 MySQL,并对数据库进行操作. 如果你 ...
- Node.js Express连接mysql完整的登陆注册系统(windows)
windows学习环境: node 版本: v0.10.35 express版本:4.10.0 mysql版本:5.6.21-log 第一部分:安装node .Express(win8系统 需要&qu ...
- Node.js + Express中间件详解
使用中间件 Express是一种路由和中间件Web框架,它具有自己的最小功能:Express应用程序本质上是一系列中间件函数调用. 中间件函数是可以访问请求对象 (req),响应对象(res)以及应用 ...
- Node.js 路由
我们要为路由提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码. 因此,我们需要查看HTTP请求,从中提取出请求的URL以及GET/POST参数.这一功能应当属 ...
- node.js中对 mysql 进行增删改查等操作和async,await处理
要对mysql进行操作,我们需要安装一个mysql的库. 一.安装mysql库 npm install mysql --save 二.对mysql进行简单查询操作 const mysql = requ ...
- 前端使用node.js+express+mockjs+mysql实现简单服务端,2种方式模拟数据返回
今天,我教大家来搭建一个简单服务端 参考文章: https://www.jianshu.com/p/cb89d9ac635e https://www.cnblogs.com/jj-notes/p/66 ...
- React++ node.js ++SQL Sever ++MySQL++ python ++ php ++ java ++ c++ c#++ java ++ android ++ ios ++Linux+
"C语言在它诞生的那个年代,是非常不错的语言,可惜没有OOP.当项目臃肿到一定程度,人类就不可控了. 为了弥补这个缺陷,C++诞生了.而为了应对各种情况,C++设计的大而全,太多复杂的特性, ...
- Node.js中测试mysql的代码var client = mysql.createClient运行出错:TypeError: Object # has no method ‘createClient’
今天在WebStorm下熟悉一个node.js的项目,配置环境时,手一抖,将mysql包从0.8升级到了2.1.1,结果再运行时就出错了. [Fri Mar 14 2014 17:05:49] 连接数 ...
- node.js如何读取MySQL数据
先安装mysql模块. node.js默认安装时,模块文件放在 /usr/local/lib/node_modules 这个目录下,为了便宜管理,模块还是统一安装到这里好. $ cd /usr/loc ...
随机推荐
- prometheus虚拟化安装脚本
在线安装下载链接:https://files.cnblogs.com/files/blogs/705493/online_prometheus.sh 离线安装下载链接:https://files.cn ...
- WebGPU 计算管线、计算着色器(通用计算)入门案例:2D 物理模拟
目录 1. WebGL 2. WebGPU 2.1. 适配器(Adapter)和设备(Device) 2.2. 着色器(Shaders) 2.3. 管线(Pipeline) 2.4. 并行(Paral ...
- SpringMVC前后端分离交互传参详细教程
温故而知新,本文为一时兴起写出,如有错误还请指正 本文后台基于SpringBoot2.5.6编写,前端基于Vue2 + axios和微信小程序JS版分别编写进行联调测试,用于理解前后端分离式开发的交互 ...
- burp token爆破(DVWA high暴力破解)
一.选择Pitchfork模式.选择要爆破的参数 二.options设置 找到optiops(设置)把线程设为1 配置Grep=Extract,点添加 点击Refetch response 获取返回 ...
- 二叉树:前序遍历、中序遍历、后序遍历,BFS,DFS
1.定义 一棵二叉树由根结点.左子树和右子树三部分组成,若规定 D.L.R 分别代表遍历根结点.遍历左子树.遍历右子树,则二叉树的遍历方式有 6 种:DLR.DRL.LDR.LRD.RDL.RLD.由 ...
- 对redis数据库的初步认识
由于之前接触的都是关系型数据库,对于非关系型数据库总是不了解,趁着外出做项目的机会,正好初步认识了redis数据库 redis分为存储分为几个存储的数据类型 string类型,hash类型,list链 ...
- 🍛 餐厅吃饭版理解 IO 模型:阻塞 / 非阻塞 / IO 复用 / 信号驱动 / 异步
IO 概念 一个基本的 IO,它会涉及到两个系统对象,一个是调用这个 IO 的进程对象,另一个就是系统内核 (kernel).当一个 read 操作发生时,它会经历两个阶段: 通过 read 系统调用 ...
- switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
答:在Java 5以前,switch(expr)中,expr只能是byte.short.char.int.从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始 ...
- jdk_8接口的内部内容
目标: 如何创建已定义好的接口类型的对象呢? 步骤: 实现的概述 抽象方法的使用 默认方法的使用 静态方法的使用 接口的常量使用 讲解: 实现的概述 类与接口的关系为实现关系,即类实现接口,该类可以称 ...
- Java根路径设置(在获取本地路径时会获取到这个文件夹,,这样就可以专门放配置文件了)
在获取本地路径时会获取到这个文件夹,,这样就可以专门放配置文件了