Node.js

目录

Node.js是什么

入门案例

fs文件系统模块

案例

http模块

创建最简单的web服务器

网页跳转案例

模块化

模块化概念

模块化规范

Node.js 中模块的分类

加载模块

模块作用域

module对象

Node.js中的模块化规范

第三方模块 (包)

安装包的命令

卸载包的命令

devDependencies节点

解决下包速度慢的问题 

导入moment包案例

包的分类

项目包

全局包

全局包安装路径设置

模块的加载机制

优先从缓存中加载

内置模块的加载机制

自定义模块的加载机制

第三方模块的加载机制 

目录作为模块 

 Express

 Express简介

安装

创建基本的Web服务器

托管静态资源

以上述案例为基础访问静态资源的路径为:http://127.0.0.1:8080/xxx.html

托管多个静态资源目录

路由的概念

路由的匹配过程

模块化路由 

模块化路由案例

中间件的概念

 定义中间件函数例

全局生效的中间件

中间件的作用

定义多个全局中间件

局部生效的中间件

定义多个局部中间件

 了解中间件的5个使用注意事项

中间件的分类

应用级别的中间件

路由级别的中间件

错误级别的中间件

Express内置的中间件 

第三方的中间件

跨域问题

使用cors中间件解决跨域问题

什么是CORS

CORS响应头部– Access-Control-Allow-Origin

 CORS响应头部– Access-Control-Allow-Headers

CORS 响应头部– Access-Control-Allow-Methods 

 Mysql

安装mysql模块

导入mysql模块

配置mysql

mysql中增删改查案例


Node.js是什么

Node.js是一个基于Chrome V8引擎的[JavaScript运行环境]。 Node.js使用了一个事件驱动、非阻塞式I/O 的模型。

Node.js 可以做什么

Nodejs作为一个JavaScript的运行环境,仅仅提供了基础的功能和API。然而,基于Node.js 提供的这些基础能,很多强大的工具和框架层出不穷,所以学会了Node.js,可以让前端程序员胜任更多的工作和岗位:

Node.js 的学习路径:

JavaScript 基础语法+Node.js 内置API模块(fs、path、http等)+第三方API模块(express、mysql 等)

下载安装

http://t.csdn.cn/pg0Sa

入门案例

创建一个js文件如下:
在这里插入图片描述
在当前目录下打开终端执行 node 文件名
在这里插入图片描述
如上所示便成功使用Node.js执行JavaScript代码了

fs文件系统模块

fs模块是Node,js官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。

如果要在JavaScript 代码中,使用fs模块来操作文件,则需要使用如下的方式先导入它

 fs中部分api:

方法作用
readFile()用来读取指定文件中的内容
writeFile()用来向指定的文件中写入内容

appendFile()

用来向指定的文件中追加内容

案例

前提准备:在同级目录中新建一个file文件夹并新建一个file01.txt文件

读取文件

// 导入fs模块,操作文件
const fs = require('fs')
const path = require('path')
// 调用fs.readFile()来读取文件
// 参数1:读取文件的存放路径
// 参数2:读取文件时候采用的编码格式,一般默认指定utf8
// 参数3:回调函数,拿到读取失败和成功的结果err dataStr

// path模块下的__dirname表示当前文件所处的目录。join()拼接路径并能够识别 ../ ./
const url = path.join(__dirname,'./file/file01.txt')
fs.readFile(url, 'utf8', function (err, dataStr) {
    if (err == null) {
        // 打印成功的结果
        console.log(dataStr)
        return
    }
    // 打印失败的结果
    console.log(err)
})

写入文件

// 导入fs模块,操作文件
const fs = require('fs')
const path = require('path')
// 参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径。
// 参数2:必选参数,表示要写入的内容。
// 参数3:可选参数,表示以什么格式写入文件内容,默认值是utf8。
// 参数4:必选参数,文件写入完成后的回调函数。

const url = path.join(__dirname,'./file/file01.txt')
fs.writeFile(url,'hello node.js','utf-8',(err) => {
    if(err == null) {
        console.log('文件写入成功')
        return
    }
    console.log('文件写入失败')
})

追加文件

// 导入fs模块,操作文件
const fs = require('fs')
const path = require('path')

fs.appendFile(path.join(__dirname,'./file/file01.txt'),'\nhello node.js',(err) => {
    if(err == null) {
        console.log('文件追加成功')
        return
    }
    console.log('文件追加失败')
})

http模块

 http模块是Nodejs官方提供的、用来创建web服务器的模块。通过 http模块提供的 http.createServer()方法,就能方便的把一台普通的电脑,变成一台Web服冬哭从而对从担HWeh次活肥女心

解决正文乱码

res.setHeader('Content-Type','text/html; charset=UTF-8')

创建最简单的web服务器

// 导入http模块
const http = require('http')
// 创建web服务器实例
const sever = http.createServer()
// 为服务器实例绑定request事件,监听客户端的请求
sever.on('request',function(req,res) {
    // req.url是客户端请求的URL地址
    const url = req.url
    // req.method是客户端请求的method类型
    const method = req.method
    const str = `<h1>你请求的路径是: ${url},你请求的方式是: ${method}</h1>`
    // 调用res.setHeader()方法,设置Content-Type 响应头,解决中文乱码的问题
    res.setHeader('Content-Type','text/html; charset=UTF-8')
    // 返回数据给客户端
    res.end(str)
})
// 启动服务器
sever.listen(8080,() => {
    console.log('server running at http://127.0.0.1:8080')
})

 启动效果

网页跳转案例

创建一个time.html网页

<!DOCTYPE html>
<html>

<head>
    <title>当前时间</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        #time {
            font-size: 40px;
            color: red;
        }
    </style>
</head>

<body>
    <h1>当前时间</h1>
    <p id="time"></p>
</body>
<script>
    function updateTime() {
        var now = new Date();
        var hours = now.getHours();
        var minutes = now.getMinutes();
        var seconds = now.getSeconds();
        var timeString = hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
        document.getElementById('time').innerHTML = timeString;
    }
    setInterval(updateTime, 1000);
</script>
</html>

在同级目录下创建一个<网页请求转到time网页.js>

// 导入模块
const http = require('http')
const fs = require('fs')
const path = require('path')
// 创建web服务器实例
const sever = http.createServer()
// 为服务器实例绑定request事件,监听客户端的请求
sever.on('request',function(req,res) {
    // req.url是客户端请求的URL地址
    const url = req.url
    // 调用res.setHeader()方法,设置Content-Type 响应头,解决中文乱码的问题
    res.setHeader('Content-Type','text/html; charset=UTF-8')
    // 读取文件
    fs.readFile(path.join(__dirname,url), 'utf8', (err, dataStr) => {
        // 读取文件失败后,向客户端喻应固定的"错误消息”
        if (err) {
            // 返回数据给客户端
            return res.end('404 Not fount')
        }
        // 读取文件成功后,将"读取成功的内容"响应给客户端
        res.end(dataStr)
    })
})
// 启动服务器
sever.listen(8080,function() {
    console.log('server running at http://127.0.0.1:8080')
})

模块化

模块化概念

模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
把代码进行模块化拆分的好处:

  • 提高了代码的复用性
  • 提高了代码的可维护性
  • 可以实现按需加载

模块化规范

模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
模块化规范的好处:
大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。

Node.js 中模块的分类

Node.js 中根据模块来源的不同,将模块分为了3大类,分别是:

  • 内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)
  • 自定义模块(用户创建的每个.js文件,都是自定义模块)
  • 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

加载模块

使用require()方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如;

注意:使用require()方法加载其它模块时,会执行被加载模块中的代码。

模块作用域

防止了全局变量污染的问题

module对象

在每个.js 自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息,打印信息如下:
在这里插入图片描述

module.exports 对象

在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。
外界用require(方法导入自定义模块时,得到的就是module.exports所指向的对象。
例:
创建一个modedemo01.js

const age = 20 
module.exports.name = 'zs'
module.exports.address = 'cq'
module.exports.helloexports = function() {
    console.log('helloexports')
}

创建一个modetest.js

const modetest = require('./modedemo01')
console.log(modetest.name)
console.log(modetest.address)
console.log(modetest.helloexports)

使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准。

exports 对象

由于module.exports单词写起来比较复杂,为了简化向外共享成员的代码,Node提供了exports对象。默认情况下,exports和module.exports指向同一个对象。最终共享的结果,还是以 module.exports 指向的对象为准

console.log(module.exports == exports)

打印结果为true

Node.js中的模块化规范

Node.js遵循了CommonJS模块化规范,CommonJS规定了模块的特性和各模块之间如何相互依赖。
CommonJS规定:

  • 每个模块内部,module变量代表当前模块。
  • module变量是一个对象,它的exports属性(即module.exports)是对外的接口。
  • 加载某个模块,其实是加载该模块的module.exports属性。require)方法用于加载模块。

第三方模块 (包)

 包是由第三方个人或团队开发出来的,Node.js 中的包都是免费且开源的,不需要付费即可免费下载使用。

为什么需要包

  • 由于Node.js的内置模块仅提供了一些底层的API,导致在基于内置模块进行项目开发的时,效率很低。
  • 包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率。

搜索包:npm

下载包: https://registry.npmjs.org/

安装包的命令

npm install 包名[@版本号]  简写为  npm i 包名[@版本号]

注:版本号省略则下载最新版

卸载包的命令

npm uninstall 包名

devDependencies节点

如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到devDependencies 节点中。

与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到dependencies节点中。

您可以使用如下的命令,将包记录到devDependencies节点中:

解决下包速度慢的问题 

在使用npm下包的时候,默认从国外的 https://registry.npmjs.org/服务器进行下载,此时,网络数据的传输需要经过漫长的海底光缆,因此下包速度会很慢。

查看npm下载地址:npm config get registry

切换npm的下包镜像源

导入moment包案例

执行如下命名:

 此时项目中就会出现如下两个文件:

 package-lock.json文件中就存放了下了那些包以及下载的版本和下载的地址等待信息

注意:程序员不要手动修改node modules 或 package-lockjson文件中的任何代码,npm包管理工具会自动维护它们.

const moment = require('moment') // 导入moment
const nowtime = moment().format('YYYY MM DD : HH mm ss') // 使用moment中的api获取当前时间
console.log(nowtime)

包的分类

项目包

那些被安装到项目的node modules目录中的包,都是项目包。

项目包又分为两类,分别是:

  • 开发依赖包(被记录到devDependencies节点中的包,只在开发期间会用到)
  • 核心依赖包(被记录到dependencies节点中的包,在开发期间和项目上线之后都会用到)

全局包

在执行npm install命令时,如果提供了-g参数,则会把包安装为全局包。

全局包会被安装到C:\Users\用户目录\AppData\Roaming\npm\node modules目录下。

全局包安装路径设置
# 查看全局包路径
npm config get prefix
# 设置全局包路径
npm config set prefix "路径"

查看全局包路径

模块的加载机制

优先从缓存中加载

模块在第一次加载后会被缓存。这也意味着多次调用require()不会导致模块的代码被执行多次。

注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。

内置模块的加载机制

内置模块是由Node.js 官方提供的模块,内置模块的加载优先级最高。

例如,require("fs')始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs。

自定义模块的加载机制

使用require()加载自定义模块时,必须指定以』或../开头的路径标识符。在加载自定义模块时,如果没有指定/或../这样的路径标识符,则 node会把它当作内置模块或第三方模块进行加载。

同时,在使用require()导入自定义模块时,如果省略了文件的扩展名,则Nodejs 会按顺序分别尝试加载以下的文件:

  1. 按照确切的文件名进行加载
  2. 补全.js扩展名进行加载
  3. 补全.json扩展名进行加载
  4. 补全.node扩展名进行加载
  5. 加载失败,终端报错

第三方模块的加载机制 

如果传递给require()的模块标识符不是一个内置模块,也没有以‘”或‘./”开头,则Node,js 会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块。

如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。

例如,假设在'C:\Users\itheimalproject\foojs'文件里调用了require('tools'),则 Node.js 会按以下顺序查找:

  1. C:\Users\itheimaproject\node_modules\tools
  2. C:\Users\itheima\node_modules\tools
  3. C\Users\node_modules\tools
  4. C:\node_modules\tools

目录作为模块 

当把目录作为模块标识符,传递给require()进行加载的时候,有三种加载方式:

  • 在被加载的目录下查找一个叫做 package.json的文件,并寻找main属性,作为require()加载的入口
  • 如果目录里没有package.json文件,或者main入口不存在或无法解析,则 Node.js将会试图加载目录下的 indexjs文件。
  • 如果以上两步都失败了,则Node.js 会在终端打印错误消息,报告模块的缺失:Error: Cannot find module 'xo'

 Express

 Express简介

官方给出的概念:Express是基于Node.js 平台,快速、开放、极简的Web开发框架。

通俗的理解: Express的作用和Node.,js内置的 http模块类似,是专门用来创建Web服务器的。

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

Express的中文官网:Express - 基于 Node.js 平台的 web 应用开发框架 - Express 中文文档 | Express 中文网

对于前端程序员来说,最常见的两种服务器,分别是:

  • Web 网站服务器:专门对外提供Web 网页资源的服务器。
  • API接口服务器:专门对外提供API接口的服务器。

使用Express,我们可以方便、快速的创建Web 网站的服务器或API接口的服务器。 

安装

在项目所处的目录中,运行如下的终端命令,即可将express安装到项目中使用:

npm i express@4.17.1

创建基本的Web服务器

// 导入express
const express = require('express')
// 创建web服务器
const app = express()

// 挂载两个路由分别监听客户端的GET和 POST请求
// URL地址中,可以通过参数名的形式匹配路径变量
app.get('/:id',(req,res) => {
    // 获取请求中的参数
    console.log(req.query)
    // 获取路径变量
    console.log(req.params)
    // 返回数据给客户端
    res.send(req.params)
})
app.post('/',(req,res) => {
    // 获取请求中的参数
    console.log(req.query)
    // 返回数据给客户端
    res.send(req.query)
})
// 调用app.listen(端口号,启动成功后的回调函数),启动服务器
app.listen(8080,() => {
    console.log('server running at http://127.0.0.1:8080')
})

托管静态资源

express提供了一个非常好用的函数,叫做 express.static([前缀],路径),通过它,我们可以非常方便地创建一个静态资源服务器

例如,通过如下代码就可以将 static目录下的图片、CSS文件、JavaScript文件对外开放访问了:

// express.static(前缀名,静态资源路径)函数会根据目录的添加顺序查找所需的文件。
app.use(express.static('./static'))

以上述案例为基础访问静态资源的路径为:http://127.0.0.1:8080/xxx.html

托管多个静态资源目录

如果要托管多个静态资源目录,请多次调用express.static)函数

访问静态资源文件时,express.static()函数会根据目录的添加顺序查找所需的文件。

路由的概念

在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。

Express 中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数,格式如下:

app.METHOD(PATH,HANDLER)

Express中的路由的例子

app.get('/',(req,res) => {
    res.send('hello get')
})
app.post('/',(req,res) => {
    res.send('hello post')
})

路由的匹配过程

每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数。
在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的URL同时匹配成功,则Express 会将这次请求转交给对应的function函数进行处理。

模块化路由 

为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到app 上,而是推荐将路由抽离为单独的模块。将路由抽离为单独模块的步骤如下:

  1. 创建路由模块对应的.js文件
  2. 调用express.Router(函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. 使用module.exports向外共享路由对象
  5. 使用app.use()函数注册路由模块

模块化路由案例

创建路由模块router.js

const express = require('express')
const app = express()
// 创建路由对象
const router = express.Router()

// 挂载具体的路由
router.get('/:id', (req, res) => {
    // 获取请求中的参数
    console.log(req.query)
    // 获取路径变量
    console.log(req.params)
    // 返回数据给客户端
    res.send(req.params)
})
router.post('/', (req, res) => {
    // 获取请求中的参数
    console.log(req.query)
    // 返回数据给客户端
    res.send(req.query)
})

// 向外导出路由对象
module.exports = router

注册路由模块

const express = require('express')
const app = express()
// 导入路由模块
const router = require('./router')

// 注册路由模块,并设置前缀为user
app.use('/user',router)
// 注意:pp.use()函数的作用,就是来注册全局中间件

app.listen(8080,() => {
    console.log('server running at http://127.0.0.1:8080/user')
})

中间件的概念

中间件(Middleware ) ,特指业务流程的中间处理环节。

Express中间件的调用流程

当一个请求到达Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。

Express中间件的格式

Express的中间件,本质上就是一个function处理函数,Express 中间件的格式如下

 注意:中间件函数的形参列表中,必须包含next 参数。而路由处理函数中只包含req和res。

next函数的作用

next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。 

 定义中间件函数例

const mw1 = function (req,res,next) {
    console.log('这是最简单的中间件函数01')
    // 添加一个key为name,value为zs请求头
    req.name = 'zs'
    //把流转关系,转交给下一个中间件或路由
    next()
}

全局生效的中间件

客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。

通过调用app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:

const mw1 = function (req,res,next) {
    console.log('这是最简单的中间件函数01')
    // 添加一个key为name,value为zs的属性
    req.name = 'zs'
    //把流转关系,转交给下一个中间件或路由
    next()
}

//将mw1注册为全局生效的中间件
app.use(mw1)

 或者可以简写为

app.use((req,res,next) => {
    console.log('这是最简单的中间件函数01')
    // 添加一个key为name,value为zs的属性
    req.name = 'zs'
    //把流转关系,转交给下一个中间件或路由
    next()
})

中间件的作用

多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用。 

定义多个全局中间件

可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调

局部生效的中间件

不使用app.use()定义的中间件,叫做局部生效的中间件,示例代码如下:

const mw2 = function (req,res,next) {
    console.log('这是最简单的中间件函数02')
    req.age = 18
    next()
}
// mw2这个中间件只在"当前路由中生效",这种用法属于"局部生效的中间件"
// 可以是单个,也可以是多个局部中间件
app.get('/',[mw2],(req,res) => {
    res.send({
        status: 1,
        data: {
            `这是局部中间件的值:${req.age}`,
        },
        msg: '请求成功'
    })
})

定义多个局部中间件

可以在路由中,通过如下两种等价的方式,使用多个局部中间件:[mw1和mw2为中间件函数]

 了解中间件的5个使用注意事项

  1. 一定要在路由之前注册中间件(错误级别的中间件除外)
  2. 客户端发送过来的请求,可以连续调用多个中间件进行处理
  3. 执行完中间件的业务代码之后,不要忘记调用next()函数
  4. 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
  5. 连续调用多个中间件时,多个中间件之间,共享req和res对象

中间件的分类

为了方便大家理解和记忆中间件的使用,Express官方把常见的中间件用法,分成了5大类,分别是:

  1. 应用级别的中间件
  2. 路由级别的中间件
  3. 错误级别的中间件
  4. Express内置的中间件
  5. 第三方的中间件

应用级别的中间件

通过app.use()或app.get()或app.post(),绑定到 app实例上的中间件,叫做应用级别的中间件,也可以理解为是全局中间件和局部中间件的统称

路由级别的中间件

绑定到express.Router)实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到app实例上,路由级别中间件绑定到 router实例上,代码示例如下:

1.创建路由模块router.js,并在模块中添加一个路由中间件

const express = require('express')
const app = express()
// 创建路由对象
const router = express.Router()

// 路由级别的中间件
router.use((req, res, next) => {
    console.log('这是路由中间件函数')
    //把流转关系,转交给下一个中间件或路由
    req.name = 'lis'
    next()
})

// 挂载具体的路由
router.get('/', (req, res) => {
    res.send(`这是路由中间件的值${req.name}`)
})

// 向外导出路由对象
module.exports = router

2.注册路由模块

const express = require('express')
const app = express()
// 导入路由模块
const router = require('./router')

// 注册路由模块,并设置前缀
app.use('/user',router)
// 注意:pp.use()函数的作用,就是来注册全局中间件

app.listen(8080,() => {
    console.log('server running at http://127.0.0.1:8080/user')
})

错误级别的中间件

错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。

格式:错误级别中间件的 function处理函数中,必须有4个形参,形参顺序从前到后,分别是(err, req, res, next)。

错误级别的中间件例:

app.use((err,req,res,next) => {
    console.log('发生了错误:' + err.message)
    res.send('Error!:' + err.message)
})

注意:错误级别的中间件,必须注册在所有路由之后!

Express内置的中间件 

自Express 4.16.0 版本开始,Express 内置了3个常用的中间件,极大的提高了Express项目的开发效率和体验:

  1. express.static快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性)
  2. express.json解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
  3. express.urlencoded解析URL-encoded格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)

使用方式

// express.static(前缀名,静态资源路径)函数会根据目录的添加顺序查找所需的文件。
app.use(express.static('../static'))
// 通过express.json()这个中间件,解析表单中的JSON格式的数据
app.use(express.json())
// 通过express.urlencoded()这个中间件,解析URL-encoded格式的请求体数据
app.use(express.urlencoded({extended: false}))

第三方的中间件

非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。

跨域问题

解决接口跨域问题的方案主要有两种:

  • CORS(主流的解决方案,推荐使用)
  • JSONP(有缺陷的解决方案:只支持GET请求)

使用cors中间件解决跨域问题

cors 是Express的一个第三方中间件。通过安装和配置cors 中间件,可以很方便地解决跨域问题。

使用步骤分为如下3步:

  1. 运行npm install cors安装中间件
  2. 使用const cors = require('cors')导入中间件
  3. 在路由之前调用app.use(cors())配置中间件 

什么是CORS

CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。

浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了CORS相关的HTTP响应头,就可以解除浏览器端的跨域访问限制。 

CORS响应头部– Access-Control-Allow-Origin

// 只允许来自http://xxx.com的请求
res.setHeader( ' Access-Control-Allow-Origin','htp://xxx.com')
// 如果指定了Access-Control-Allow-Origin字段的值为通配符*,表示允许来自任何域的请求
res.setHeader( ' Access-Control-Allow-Origin','*')

 CORS响应头部– Access-Control-Allow-Headers

默认情况下,CORS仅支持客户端向服务器发送如下的9个请求头:
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、WidthContent-Type(值仅限于text/plain、multipart/form-data、application/x-www-form-urlencoded三者之一)

如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过Access-Control-Allow-Headers 对额外的请求头进行声明,否则这次请求会失败!

CORS 响应头部– Access-Control-Allow-Methods 

默认情况下,CORS仅支持客户端发起GET、POST、HEAD请求。

如果客户端希望通过PUT、DELETE等方式请求服务器的资源,则需要在服务器端,通过Access-Control-Alow-Methods来指明实际请求所允许使用的HTTP方法。

 Mysql

安装mysql模块

命令:npm i mysql@2.18.1

导入mysql模块

const mysql = require('mysql')

配置mysql

在使用mysql模块操作 MySQL数据库之前,必须先对 mysql模块进行必要的配置,主要的配置步骤如下:

// 建立与MySQL数据库的连接关系
const db = mysql.createPool({
    host: '127.0.0.1', //数提库的IP地址
    user: 'root',  //有示录数据库的账号
    password: '123456',//登录数据库的密码
    database: 'test' //指定要操作哪个数据库
})

mysql中增删改查案例

// 查询
const querysql = 'select * from user where accont = ? and password = ?'// sql语句
db.query(querysql, [123456, 123456], (err, result) => {
    // 失败
    if (err) return console.log(err)
    // 成功
    console.log(result)
})

// 插入
const insetsql1 = 'insert into user (name,accont,password,stater) values (?,?,?,?)'// sql语句
db.query(insetsql1, ['lis','654321','654321',1], (err, result) => {
    // 失败
    if (err) return console.log(err)
    // 成功
    if(result.affectedRows === 1) {
        console.log('添加成功')
    }
})

// 插入(简化)
const insertuser = {name: 'lis',accont: '654321',password: '654321',stater: 1}
const insertsql2 = 'insert into user set ?'// sql语句
db.query(insertsql2, [insertuser], (err, result) => {
    // 失败
    if (err) return console.log(err)
    // 成功
    if(result.affectedRows === 1) {
        console.log('添加成功')
    }
})

// 修改
const updatesql = 'update `user` set `name` = ?  where `name` = ?'// sql语句
db.query(updatesql, ['lisi','lis'], (err, result) => {
    // 失败
    if (err) return console.log(err)
    // 成功
    if(result.affectedRows === 1) {
        console.log('修改成功')
    }
})

// 删除
const deletesql = 'delete from `user` where `name` = ?'// sql语句
db.query(deletesql, ['lisi'], (err, result) => {
    // 失败
    if (err) return console.log(err)
    // 成功
    if(result.affectedRows === 1) {
        console.log('删除成功')
    }
})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值