Nodejs入门实战一篇精通

  • Post author:
  • Post category:其他




Nodejs



初始Node.js


Node

.

js

® 是一个基于 Chrome V8 引擎 的JavaScript 运行时环境。

Node.js介绍



Node.js中的JavaScript环境

image-20220831161656095

Node.js可以做什么

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



NodeJs学习路径

JavaScript

基础語法+Nodejs内置APl模块(s、path,http等)+第三方API模块(express.mysql 等)



NodeJs环境安装

区分LTS版本和Current 版本的不同


LTS

为长期确定版,对于追求稳定性的企业级项目来说,推荐安装LTS版本的Node.j5.


Current

为新特性类鲜版,对热表于装试新将性的用户来说,推荐安装Current 版本的Node js,但是,Current 版本中可

能存在隐副的Bug 呢安全性测同,因此不推荐在企业级项日中使用Current 版本的Node js。



fs文件系统模块



什么是fs文件系统模块


ts模诀

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

例如:


  • fs.readFile()

    方法,用来读取指定文件中的内容


  • fs.witefile()

    方法,用来向指定的文件中写入内容

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

    const fs = require('fs')
    



读取文件内容


fs.witefile()

示例代码

参数1:文件路径

参数2:编码格式

参数3:回调函数

function readFile(path, options, callback)

const fs = require('fs');
fs.readFile('input.txt', 'utf-8', function (err, data) {
    if (err) {
        return console.log("读取文件失败:" + err.message);
    }
    console.log("读取文件成功:" + data);
})



文件写入内容


fs.witefile()

示例代码

参数1:文件路径

参数2:写入内容

参数3:编码格式

参数4:回调函数

function writeFile(path, data, options, callback)

const fs = require('fs');
fs.writeFile('input.txt', "测试1", function (err) {
    if (err) {
        return console.log("文件写入内容失败!" + err.message)
    }
    console.log("文件写入成功");
})



模块-路径动态拼接问题


__dirname

获取当前文件所属目录

在使用横块操作文件时,如果提供的操作路径是以

./



../

开头的

相对路径

时,很容易出现路径动拼接错误的问题。

原因:代码在运行的时候,

会以执行node命令时所处的目录

,动态拼接出被操作文件的完彪路径。

如果在input.txt上层目录执行node xxx/xxx.js 的话,如果出现错误读取不到文件,直接将./input.txt相对路径改为绝对路径读取。

const fs = require('fs');
fs.readFile('./input.txt', 'utf8', function (err, data) {
    if (err) {
        return console.log("读取文件失败" + err.message)
    }
    console.log("读取文件成功" + data);
})

//__dirname获取文件所处目录
const fs = require('fs');
fs.readFile(__dirname + '/input.txt', 'utf8', function (err, data) {
    if (err) {
        return console.log("读取文件失败" + err.message)
    }
    console.log("读取文件成功" + data);
    console.log(__dirname)
})



Path路径模块



什么是Path路径模块

path模块是Nodejs官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理

例如:


path.join()

方法,用来将多个路径片段拼接成一个完整的路径字符串


path.basename()

方法,用来从路径字符申中,将文件名解析出来

如果要在JavaScript代码中,使用path模块来处理路径,则需要使用如下的方式先导入它:

const path = require('path')



路径拼接

使用

path.join0

方法,可以把多个路径片段拼接为完格的路径字符串:

const pathStr = path.join('/a', '/b/c', '../', './d', 'e')
console.log(pathStr)//指出\a\b\d\e

const pathStr2 = path.join(__dirname, '/files/1.txt')

console.log(pathStr2)//物出 当前文件所处目录\files\1.txt



获取路径文件名


path.basename()

的代码示例

使用

path.basenam()

方法,可以从一个文件路径中,获取到文件的名称部分


basename(path: string, ext?: string)

const path = require("path");

const fpath = '/a/b/c/index.html';
let filename = path.basename(fpath);
//分割指定内容
let newFileName = path.basename(filename,".html");

console.log(filename);//index.html
console.log(newFileName)//index


获取路径中扩展名

使用 path.extname0方法,可以获取路径中的扩展名部分,语法格式如下:

path.extname(path)

参数解读:

  • path必选参数,表示一个路径的字符串
  • 返回:返回得到的扩展名字符串
const path = require("path");

const pathStr = "/a/b/c/index.html";
let extname = path.extname(pathStr);
console.log(extname)//.html



http模块



什么是http模块

回顾:什么是客户端、什么是服务器?

在网络节点中,负责消费资源的电脑,叫做客户端;

负责对外提供网络资源

的电脑,叫做服务器。


http模块

是Node.js官方提供的、用来创

建 web 服务器的模块

。通过http模块提供的

http.createServer()

方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供Web资源服务。

如果要希望使用http模块创建Web服务器,则需要先导入它:

const http = require('http')



http模块作用

服务器和普通电脑的

区别

在于,服务器上安装了

web服务器软件

,例如:IIS、Apache等。通过安装这些服务器软件,就能把一台普通的电脑变成一台web服务器。



Node.js

中,我们不需要使用IIS、Apache等这些第三方web服务器款件。因为我们可以基于Node.js提供的


http模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供web服务。



创建web服务器

①导入http模块

②创建 web 服务器实例

③为服务器实例绑定request事件,监听客户端的请求

④启动服务器

//导出http模块
const http = require('http');
//创建web服务器
const server = http.createServer();
//为服务器示例绑定request事件,监听客户端的请求
server.on('request', function (req, res) {
    console.log("调用了request方法")
})
//启动服务器
server.listen(8080, function () {
        console.log("访问http://127.0.0.1:8080 获取结果")
    }
)


request请求

获取request里面的数据和属性参数

//导出http模块
const http = require('http');
let server = http.createServer();
// req是请求对象,包含了与客户端的数据和属性
server.on('request', (req, res) => {
    const url = req.url;
    const method = req.method;
    const str = `url地址${url}, 方法是${method}`;
    console.log(req);
    console.log(str);
})

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


response响应

响应结束


res.end();

解决中文乱码,设置Header


res.setHeader('Content-Type', 'application/json');


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

//response响应对象
const http = require('http');
let server = http.createServer();
// req是请求对象,包含了与客户端的数据和属性
server.on('request', (req, res) => {
    const url = req.url;
    const method = req.method;
    const str = `url地址${url}, 方法是${method}`;
    res.setHeader('Content-Type', 'text/html;charset=utf-8');
    // res.setHeader('Content-Type', 'application/json');
    res.end(str)
})

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


根据不同URL相应不同内容
const http = require('http');
let server = http.createServer();

server.on('request', function (req, res) {
    //获取请求URL
    let url = req.url;
    let content = "<h1>404 Not found!</h1>";
    if (url === '/' || url === '/index.html') {
        content = '<h1>首页</h1>'
    } else if (url === '/about.html') {
        content = '<h1>关于页面</h1>'
    }
    res.setHeader('Content-Type', 'text/html; charset=UTF-8');
    res.end(content);
})

server.listen(8080, () => {
    console.log("启动成功访问http://127.0.0.1:8080")
})



模块化

能够说出模块化的好处

能够知道CommonJS规定了哪些内容

能够说出Node.js中模块的三大分类各自是什么

能够使用npm管理包

能够了解什么是规范的包结构

能够了解模块的加载机制



模块化概念

编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。

把代码进行模块化拆分的好处:

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

模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。

例如:

  • 使用什么样的语法格式来引用模块
  • 在模块中使用什么样的语法格式向外剔需成员

  • 模块化规范的好处

    :大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。



模块的分类

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


  • 内置模块

    (内置模块是由 Node.js官方提供的,例如fs、path、http等)

  • 自定义横块

    (用户创建的每个js文件,都是自定义横块)

  • 第三方模块

    (由第三方开发出来的横块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下或)



加载模块

使用强大的require0方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如:

//1.加载内置的fs模块
const fs = require('fs')
//2.加载用户的自定义模块
const custom = require('./custom.js')
//3.加载箱三方模块(关于第三方模块的下载和使用,会在后面的课程中进行专门的讲解)
const moment = require('moment')


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

//使用 require0方法加载其它模块时,会执行被加载模块中的代码,在使用require0加载自定义模块可以省略.js后缀名`
const test = require('E:\\work2\\node-learning\\node基础\\01.使用readFile读取文件.js');
console.log(test)

//{}
//读取文件成功:测试1



模块作用域

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。


防止了全局变量污染的问题,在模块内定义的成员不能被外部访问

image-20220902101110268



向外共享模块作用域中的成员

在每个,js自定义横块中都有一个module 对象,它里面存储了和当前横块有关的信息,打印如下:

Module {
  id: '.',
  path: 'E:\\work2\\node-learning\\模块化',
  exports: {},
  parent: null,
  filename: 'E:\\work2\\node-learning\\模块化\\04.module对象.js',
  loaded: false,
  children: [],
  paths: [
    'E:\\work2\\node-learning\\模块化\\node_modules',
    'E:\\work2\\node-learning\\node_modules',
    'E:\\work2\\node_modules',
    'E:\\node_modules'
  ]
}



module.exports 对象

在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。

外界用require0方法导入自定义模块时,得到的就是module.exports所指向的对象。

module.exports.username = ‘张三’ exports.username = ‘张三’指向的是同一个对象,一种简写方式

image-20220902102458404



共享成员注意点

使用requireo方法导入模块时,导入的结果,

永远以module.exports 指向的对象为准

image-20220902104149894

//	{ nikeName: '李四', test: [Function: test], aaa2: 25 }



CommonJS 模块化规范

  • 每个模块内部,

    module

    变量代表当前模块

  • module

    变量是一个对象,

    module.exports

    是对外的接口
  • 加载某个模块即加载该模块的

    module.exports

    属性



模块的加载机制


优先从缓存中加载

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

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



内置模块加载机制


内置模块

是由

Node.js官方

提供的模块,内置模块的加戦优先级最高。

例如,require(‘fs’)始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs.而不是加载第三方的



自定义模块加载机制

使用 require()加载自定义模块时,必须指定以

./



../

开头的路径标识符。在加载自定义模块时,如果没有指定

./



../

这样的路径标识符,则node会把它当作

内置模块



第三方模块

进行加载。

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

①按照确切的文件名进行加载

②补全js扩展名进行加载

③补全json扩展名进行加载

④补全.node扩展名进行加载

⑤加载失效,终端报错



第三方模块的加载机制

如果传递给requir()的模块标识符不是一个内置模块,也没有以

‘./’



‘../’

开头,则Node.js会从当前模块的父目录开始,尝试从/node_modules 文件夹中加载第三方模块。

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

例如,假设在

‘C:AUsersVitheima\project\

foo.js’文件里调用了require(‘tools’),则Node.js会按以下顺序查找:



C:\Users\itheima\project\

node_modules\tools



C:\Users\itheima\

node_modules\tools



C:\Users

\node_modules\tools



C:\

node_modules\tools



express



什么是express

官方给出的概念:

Express

是基于

Node.js

平台,快速、开放、极简的Web开发框架。

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


Express的本质

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



express能做什么

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


  • Web 网站服务器

    :专门对外提供Web 网页资源的服务器。

  • API接口服务器

    :专门对外提供API接口的服务器。

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



express基本使用

安装依赖

node i express@4.17.1
//引入express模块
let express = require('express');
//创建服务器
let app = express();
//监听端口
app.listen(8080, () => {
    console.log('express server running at http://localhost:8080');
})



express GET\POST

//引入express
let express = require('express');
//创建服务器
let app = express();

//测试GET请求,获取参数
app.get('/user/:id/:name', function (req, res) {
    let arrayData = [];
    //获取动态参数,路径参数id,name
    let params = req.params;
    //获取query参数,查询条件
    let query = req.query;

    arrayData.push(params);
    arrayData.push(query)
    res.send(arrayData)
})

//测试POST请求获取参数
app.post('/user', (req, res) => {
    res.send("请求成功")
})

//启动服务
app.listen(8080, () => {
    console.log("测试GET POST请求,http://localhost:8080");
})



托管静态资源

  • 通过

    express.static()

    方法可创建静态资源服务器,向外开放访问静态资源。
  • Express 在指定的静态目录中查找文件,并对外提供资源的访问路径,存放静态文件的目录名不会出现在 URL 中
  • 访问静态资源时,会根据托管顺序查找文件
  • 可为静态资源访问路径添加前缀
  • 托管多个静态文件目录,引入多个按照引入顺序加载
const express = require('express');
const app = express();

//引入多个按照顺序加载,先去public找public没有然后去files文件夹找,http://localhost:8080/index.html
app.use(express.static("../public"))
app.use(express.static("../files"))

//指定访问前缀,指定访问前缀在访问静态文件需要添加上前缀http://localhost:8080/public/index.html
// app.use("/public", express.static("../public"))

app.listen(8080, () => {
    console.log("访问静态文件http://localhost:8080")
})



nodemon

在编写调试Node.js项目的时候,如果修改了项目的代码,则需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon(https://www.npmjs.com/package/nodemon)这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon会自动帮我们重启项目,极大方便了开发和调试。

npm i -g nodemon



使用nodemon

当基于Node.js编写了一个网站应用的时候,传统的方式,是运行node app.js命令,来启动项目。这样做的坏处是代码被修改之后,需要手动重启项目。

现在,我们可以将node命令替换为

nodemon

命令,使用

nodemon app.js

来启动项目。这样做的好处是:代码被修改之后,会被

nodemon

监听到,从而实现自动重启项目的效果。

node app.js
# 将上面的终端命令,替换为下血的终满命令,即可实现自动重启项目的效果
nodemon app.js



express路由



引用路由

  • 定义路由模块
//1、导入express
const express = require('express');
//2、创建路由对象
const route = express.Router();

//添加get请求
route.get('/user/list', (req, res) => {
    console.log("GET请求参数", req.query);
    res.send(req.query)
})

//添加post请求
route.post('/user/add', (req, res) => {
    console.log("POST请求参数", req.body);
    res.send(req.body)
})

//导出路由对象
module.exports = route;
  • 调用路由
const express = require('express');
//引入Router自定义模块
const router = require('./04.路由简单用法Router');
//创建服务器
const app = express();
/**
 * app.use()就是来注册全局中间件的
 * 加载router模块,添加固定前缀api
 * GET  http://localhost:8080/api/user/list?aaa=123
 * POST http://localhost:8080/api/user/add
 */
app.use('/api', router);
//启动服务
app.listen(8080, () => {
    console.log("测试引用路由,http://localhost:8080")
})



express中间件

  • 中间件是指流程的中间处理环节
  • 服务器收到请求后,可先调用中间件进行预处理
  • 中间件是一个函数,包含

    req, res, next

    三个参数,

    next()

    参数把流转关系交给下一个中间件或路由

中间件注意事项;

  • 在注册路由之前注册中间件(错误级别中间件除外)
  • 中间件可连续调用多个
  • 别忘记调用

    next()

    函数

  • next()

    函数后别写代码
  • 多个中间件共享

    req



    res

    对象



全局中间件

  • 通过

    app.use()

    定义的中间件为全局中间件
//1、引用express模块
const express = require('express');
//2、创建服务
const app = express();

//3、创建中间件函数
const mw = function (req, res, next) {
    console.log("调用了中间件方法");
    //最后必须要执行的方法,下一步
    next();
}

//4、注册全局中间件
app.use(mw);

//创建中间件函数,并注册简化写法
// app.use(function (req, res, next) {
//     console.log("调用了中间件方法");
//     //最后必须要执行的方法,下一步
//     next();
// });

//5、挂载方法
//挂载GET http://127.0.0.1:8080/
app.get('/', (req, res) => {
    console.log("调用了/ 路由方法");
    res.send("Home Page···")
})
//挂载GET http://127.0.0.1:8080/user
app.get('/user', function (req, res) {
    console.log("调用了user 路由方法");
    res.send('User Page···')
})

//6、启动服务
app.listen(8080, () => {
    console.log("启动服务器http://127.0.0.1:8080");
})

//调用了中间件方法
//调用了/ 路由方法


多个全局中间件

可以使用

app.use()

连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:

const express = require('express');
const app = express();

app.use(function (req, res, next) {
    console.log("第一个中间件函数")
    next()
})

app.use(function (req, res, next) {
    console.log("第二个中间件函数")
    next()
})


app.get('/', (req, res) => {
    console.log("调用get方法")
    res.send("成功!")
})


app.listen(8080, () => {
    console.log("服务启动成功,http://localhost:8080")
})
//http://localhost:8080/
//第一个中间件函数
//第二个中间件函数
//调用get方法



局部中间件


不使用


app.use()

定义的中间件,叫做

局部生效的中间件

,示例代码如下:

const express = require('express');
let app = express();

const mw = function (req, res, next) {
    console.log("局部生效中间件函数1")
    req.startTime = new Date();
    //必须
    next()
}

const mw1 = function (req, res, next) {
    console.log("局部生效中间件函数2")
    req.startTime = new Date();
    //必须
    next()
}

app.get('/user', (req, res) => {
    console.log("调用user方法", req.startTime);
    res.send(req.startTime)
})
//设置局部生效中间件
app.get('/', mw, (req, res) => {
    console.log("调用/方法", req.startTime);
    res.send(req.startTime)
})

//设置多个局部生效中间件
app.get('/user/list1', mw, mw1, (req, res) => {
    console.log("调用/方法", req.startTime);
    res.send(req.startTime)
})
app.get('/user/list2', [mw, mw1], (req, res) => {
    console.log("调用/方法", req.startTime);
    res.send(req.startTime)
})


app.listen(8080, () => {
    console.log("服务启动http://127.0.0.1:8080")
})



中间件分类


  1. 应用级别中间件

    • 通过

      app.use()



      app.get()



      app.post()

      ,绑定到app实例上的中间件,叫做应用级别的中间件,代码示例如下:

    • //应用级别中间件(全局中间件)
      app.use(function (req, res, next) {
          console.log("全局中间件")
          next()
      })
      
      
      //应用级别中间件(局部中间件)
      const mw = function (req, res, next) {
          console.log("局部生效中间件函数")
          req.startTime = new Date();
          //必须
          next()
      }
      app.get('/', mw, (req, res) => {
          console.log("调用/方法", req.startTime);
          res.send(req.startTime)
      })
      

  2. 路由级别中间件

    • 绑定到

      express.Route()

      实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,

      应用级别中间件是绑定到app实例上,路由级别中间件绑定到router实例上

      ,代码示例如下:

    • const express = require('express');
      const router = express.Router();
      
      //设置Router中间件
      router.use(function (req, res, next) {
          console.log("router级别中间件")
          next();
      })
      
      //router绑定方法
      router.get('/user', function (req, res) {
          console.log("调用routerGET方法")
          res.send("调用routerGET方法")
      })
      
      //向外暴露
      module.exports = router
      
      
    • const express = require('express');
      //引入05.router级别中间件自定义模块
      const routerTest = require('./05.router级别中间件');
      //创建服务器
      let app = express();
      
      //设置routerTest中间件
      app.use(routerTest);
      
      //服务启动GET http://localhost:8080/user
      app.listen(8080, () => {
          console.log("服务启动成功,http://localhost:8080")
      })
      
      
      

  3. 错误级别中间件

    • 错误级别中间件的

      作用

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


    • 格式

      :错误级别中间件的function 处理函数中,

      必须有4个形参,形参顺序从前到后,分别是(err,req,res,next)


    • 错误级别的中间件,放到所有路由请求之后

    • const express = require('express')
      const app = express()
      
      app.get('/', (req, res) => {
          throw new Error('服务器内部发生了错误!')
          res.send('Home page.')
      })
      
      // 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
      app.use((err, req, res, next) => {
          console.log('发生了错误!' + err.message)
          res.send('Error:' + err.message)
      })
      
      app.listen(8080, function () {
          console.log('Express server running at http://127.0.0.1:8080')
      })
      

  4. Express 内置中间件

    自Express 4.16.0版本开始,Express内置了

    3个常用

    的中间件,极大的提高了Express项目的开发效率和体验:



    express.static

    快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性)



    express.json

    解析JSON格式的请求体数据(

    有兼容性

    ,仅在

    4.16.0+

    版本中可用)



    express.urlencoded

    解析URL-encoded格式的请求体数据(

    有兼容性

    ,仅在

    4.16.0+

    版本中可用)

    • //添加router.use(express.json()) json解析中间件,post请求req.body JSON参数可以正常取到,否则req.body=undefined
      app.use(express.json())
      //Body参数,x-www-form-urlencoded参数
      app.use(express.urlencoded({ extended: false }))
      
      
      --------------------------------------------------------------------
      
      const express = require('express');
      const app = express();
      //Body参数,json参数
      app.use(express.json())
      //Body参数,x-www-form-urlencoded参数
      app.use(express.urlencoded({ extended: false }))
      
      app.post('/user/add', (req, res) => {
          console.log(req.body);
          res.send(req.body);
      })
      //启动服务
      app.listen(8080, () => {
          console.log("express内置中间件启动成功http://127.0.0.1:8080")
      })
      



中间件的作用

多个中间件之间,共享同一份

req



res

,基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加

自定义



属性



方法

,供

下游

的中间件或路由进行使用。

image-20220905145411180

// 引入express
const express = require('express');
//创建服务器
let app = express();
//定义中间件函数
const mw = function (req, res, next) {
    console.log("进入了中间件函数");
    //req设置自定义参数
    req.startTime = new Date();
    //调用next方法
    next();
}

//注册中间件
app.use(mw)

//挂载方法
app.get('/', (req, res) => {
    console.log("获取中间件设置的自定义参数", req.startTime)
    res.send(req.startTime)
})

//启动服务
app.listen(8080, () => {
    console.log("服务启动,http://127.0.0.1:8080")
})



自定义中间件

  • 暴露中间件模块
//引入express模块
const express = require('express');
const app = express();
//引入querystring模块
const qs = require('querystring');

app.use(function (req, res, next) {
    //定义变量
    let str = '';

    //开始
    req.on('data', (chunk) => {
        str += chunk;
    })

    //结束
    req.on('end', () => {
        //将字符串转对象
        const parsedUrlQuery = qs.parse(str);
        //对象设置body参数
        req.body = parsedUrlQuery

        next();
    })
})

//挂载请求
app.post('/user/add', (req, res) => {
    res.send(req.body);
})


//暴露外部模块
module.exports = app

  • 启动服务
const express = require('express');
//引入自定义中间件
const zidingyi = require('./09.自定义中间件01');
//获取服务器
const app = express();
//设置自定义中间件为全局中间件
app.use(zidingyi)
//启动服务
app.listen(8080, () => {
    console.log("自定义模块启动,http://localhost:8080")
})



express写接口例子



api路由接口文件

01.apiRouter.js

const express = require('express');
//1. 创建一个路由容器
const router = express.Router();

//2.编写接口
router.get('/get', function (req, res) {
    //获取req.query查询参数
    const query = req.query;
    res.send(
        {
            code: 200,
            message: 'GET查询成功',
            data: query
        }
    )
})

router.post('/post', function (req, res) {
    //获取body参数
    const body = req.body;
    res.send({
        code: 200,
        message: 'POST提交成功',
        data: body
    })
})


//3.路由外部暴露
module.exports = router



api服务模块

const express = require('express');
//1.创建服务器
const app = express();

//2.导入apiRouter路由模块
const router = require('./01.apiRouter')

//3.导入cors跨域模块
const cors = require('cors');


//4.注册JSON中间件、解析URL-encoded中间件 (内置中间件) \配置跨域中间件app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended: false}))
app.use(cors())

//5.注册router中间件
app.use(router);

//6.启动服务
app.listen(8080, function () {
    console.log("api接口启动成功,http://localhost:8080")
})



CORS跨域资源共享



解决跨域问题

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

使用步骤分为如下3步:

//1.安装cors模块
npm install cors

//2.导入cors模块
const cors = require('cors');

//3.注册cors模块
app.use(cors())



CORS

  • CORS(Cross-Origin Resource Sharing,跨域资源共享)解决跨域,是通过 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源
  • 浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可解除浏览器端的跨域访问限制
  • CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
  • CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。



CORS 常见响应头


  • Access-Control-Allow-Origin

    :制定了允许访问资源的外域 URL
res.setHeader('Access-Control-Allow-Origin', 'http://bruceblog.io')
res.setHeader('Access-Control-Allow-Origin', '*')

  • Access-Control-Allow-Headers
  • 默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头:

    Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
  • 如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 A

    ccess-Control-Allow-Headers

    对额外的请求头进行声明,否则这次请求会失败!
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')

  • Access-Control-Allow-Methods
  • 默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过

    Access-Control-Alow-Methods

    来指明实际请求所允许使用的 HTTP 方法
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')



CORS 请求分类



简单请求
  • 请求方式:GET、POST、HEAD 三者之一
  • HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值 application/x-www-formurlencoded、multipart/form-data、text/plain)


预检请求
  • 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  • 请求头中包含自定义头部字段
  • 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据

、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)`

  • 如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 A

    ccess-Control-Allow-Headers

    对额外的请求头进行声明,否则这次请求会失败!
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')

  • Access-Control-Allow-Methods
  • 默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过

    Access-Control-Alow-Methods

    来指明实际请求所允许使用的 HTTP 方法
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')



CORS 请求分类



简单请求
  • 请求方式:GET、POST、HEAD 三者之一
  • HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值 application/x-www-formurlencoded、multipart/form-data、text/plain)


预检请求
  • 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  • 请求头中包含自定义头部字段
  • 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据



最后

最后准备了一份资料分享给大家,获取链接:

2022年Java开发全套学习资料



版权声明:本文为weixin_43831049原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。