Node.js

学习目标

能够知道什么是node.js

能够知道node.js可以做什么

能够说出node.js中javascript的组成部分

能够使用path模块处理模块路径

能够使用http模块写一个基本的web服务器

01初始node.js是基于chrome v8引擎的javascript运行环境

什么是终端 

专门为程序员开发而设计的  用于实现人机交互的一种方式

使用命令来交互

1.4在node.js环境中执行javascript代码

1打开终端

2输入node 要执行的文件路径 就可以执行.js文件

C:\Users\强天尊>node 1.js

hello word

C:\Users\强天尊>


终端快捷键

cd +文件路径可以切换到其他文件的所处路径

便捷快速进入文件所处的目录

在文件空白按住shift 鼠标右键 找到Windows PowerShell 就可以打开直接输入node 加文件名就可以运行js文件 这个属于新的终端 功能强大 比cmd更好

 终端快捷键

1方向建里面的向上【   可以快速定位到上一次执行吗,命令

2使用tab 可以快速补全 .\自己加上的不影响

PS C:\Users\强天尊> node .\1.js

hello word

3使用esc按键可以快速清空

4输入cls可以清空终端的所有内容

.help: 显示点命令的帮助。

.editor: 启用编辑器模式,可以轻松地编写多行 JavaScript 代码。当处于此模式时,按下 ctrl-D 可以运行编写的代码。

.break: 当输入多行的表达式时,输入 .break 命令可以中止进一步的输入。相当于按下 ctrl-C。

.clear: 将 REPL 上下文重置为空对象,并清除当前正在输入的任何多行的表达式。

.load: 加载 JavaScript 文件(相对于当前工作目录)。

.save: 将在 REPL 会话中输入的所有内容保存到文件(需指定文件名)。

.exit: 退出 REPL(相当于按下两次 ctrl-C)。


FS文件系统模块

Fs模块是node.js官方提供来满足用户对文件的操作

fs.read File()方法用来指读取定文件的内容

fs.writeFile()写入

导入模块

const fs=require(‘fs’)

2.2 读取指定文件内容

使用 fs.readFile()

语法格试 fs.readFile(path[,options],callback)

参数1 必选字符串表示文件的路径

参数2 可选 表示以什么拜尼马格式来读取文件

参数3 必选参数 文件读取完后 通过回调函数 拿去读取的结果

以utf8的编码格式 读取文件的内容

 Const fs=require(‘fs’)

fs.readFile(‘./file/11.text’ ,   ’utf8’,    function(err,dataStr){

Console.log(err)  失败

Consloe.log(‘-----’)

Console.log(dataStr)  成功

})

安装最新的 PowerShell,了解新功能和改进!https://aka.ms/PSWindows

请求失败

PS C:\Users\强天尊\text> node .\使用readFile读取文件内容.js

[Error: ENOENT: no such file or directory, open 'C:\Users\强天尊\text\File\1.text'] {

  errno: -4058,

  code: 'ENOENT',

  syscall: 'open',

  path: 'C:\\Users\\强天尊\\text\\File\\1.text'

}

---

Undefined

请求成功

PS C:\Users\强天尊\text> node .\使用readFile读取文件内容.js

null

---

1234213

PS C:\Users\强天尊\text>


3判断文件是否读取成功

判断err对象是否为null  如果是其他的就失败

const fs = require('fs')

fs.readFile('./File/1.txt', 'utf8', function(err, dataStr) {

    if (err) {

        return console.log("读取文件失败" + RegExp.massage)

    }

    console.log('读取文件成功' + dataStr)

})

PS C:\Users\强天尊\text> node .\02判断文件是否读取成功.js

读取文件成功1234213

PS C:\Users\强天尊\text>

PS C:\Users\强天尊\text> node .\02判断文件是否读取成功.js

读取文件失败undefined

PS C:\Users\强天尊\text>


2.3向指定文件写入内容

1使用fs.writeFile()

语法格试 fs.readFile(file,data [,options],callback)

参数1 必选字符串表示文件的路径

参数2 必选表示写入内容

参数3 必选参数 内容格式

参数4 必选参数 文件读取完后 通过回调函数 拿去读取的结果

以utf8的编码格式 读取文件的内容

// 导入文件系统模块

const fs = require('fs')

// 调用fs.writeFile()

fs.writeFile('./File/2.txt', 'abcd', 'utf-8', function(err) {

    console.log(err)

})


成功

PS C:\Users\强天尊\text> node .\03写入内容.js

null

PS C:\Users\强天尊\text>

判断文件是否写入成功

// 导入文件系统模块

const fs = require('fs')

// 调用fs.writeFile()

fs.writeFile('./File/2.txt', 'abcd', 'utf-8', function(err) {

    if (err) {

        return console.log("文件写入失败" + err.message)

    }

    console.log('写入成功')

})

练习 考试成绩整理

使用 fs文件系统模块,将素材目录下的成绩txt文件中考试数据整理到成绩 ok.txt文件中

整理数据 小红=99 小白=33 小李=45 小赵=78

整理后的数据

小红=99

小白=33

小李=45

小赵=78

核心实现步骤

1导入需要的fs文件系统模块

2使用fs.readFile()方法,读取素材目录下的文件

3判断文件是否读取成功

4文件读取成功后处理成绩数据


Path路径模块

1path.join()用来拼接一个完整的路径

2path.basename() 用于从路径中将文件名解析出来

先导入模块

const fs = require('path')

path.join([]) 里面可以传入多个路径

const pt = require('path')

const pathStr = pt.join('a', '/b/c', '../', './c')

console.log(pathStr)

PS C:\Users\强天尊\text> node .\path.js

a\b\c

PS C:\Users\强天尊\text>


三:Node.js的用途

1.Node.js最适合在流媒体应用程序中使用,还有一些聊天应用程序。

2.游戏服务器 - 需要一次处理数千个请求的快速和高性能服务器,这是一个理想的框架。

3.广告服务器 - 再次在这里你可以有数千个请求从中央服务器提取广告,Node.js可以是一个理想的框架来处理这个问题。

4.流服务器 - 使用Node的另一个理想方案是用于多媒体流服务器,其中客户端有请求从该服务器提取不同的多媒体内容。

以上就是对nodejs是做什么的?有哪些功能的全部介绍,如果你想了解更多有关Node.js视频教程,请关注php中文网。

以上就是nodejs是做什么的?有哪些功能的详细内容,更多请关注php中文网其它相关文章!


http模块

是node.js官方提供的用来创建web服务器的模块 通过http模块提供的http.createServer()方法就可以把一台电脑变成web服务器,从而对外开放提供web资源服务

1需要导入模块

Const http=require(‘http’)

就可以调用http

进一步理解http 服务器和普通电脑的区别  ,服务器上安装了web服务器软件例如lls  ,apache等通过安装这些服务器软件就可以一台服务器

服务器相关的概念

Ip地址是互联网上每台计算机的唯一地址

在开发中可以使用127.0.0.1来进行测试 这个地址只限用来测试  不可以用来给哦别人访问

域名和域名服务器

Ip态难记用别名来代替 域名

IP和域名是对应关系 域名需要转换成ip才可以访问

127.0.0.1的域名是locallhost

端口号标识便于准确找到web服务器进行处理  一个端口只能被一个文本服务器占用

实际访问的时候可以省略端口号


创建web服务器

1创建web服务器的基本步骤

    1. 导入http模块
    2. const http = require('http')
    3. 创建web服务器实列

const server = http.createServer((req, res) => {

  res.statusCode = 200  //端口

  res.setHeader('Content-Type', 'text/plain')

  res.end('你好世界\n')

})

    1. 为服务器绑定request事件 监听客服端的请求
    2. 启动服务器 .listen()


server.listen(port, () => {

  console.log(`服务器运行在 http://${hostname}:${port}/`)

})

搭建服务器

// 导入http模块

const http = require('http')

// 创建文本服务器实列

const server = http.createServer()

// 为服务器绑定一个request事件

server.on('request', function(req, res) {

        console.log('someone visit our web server')

    })

    // 启动服务器

server.listen(80, function() {

    console.log("hgedjkghdsgsdjkg")

})


req请求对象

// 导入http模块

const http = require('http')

// 创建文本服务器实列

const server = http.createServer()

// 为服务器绑定一个request事件

// req请求对象 包含了客服端相关的数据和属性

// req.url是客服端请求的url地址

server.on('request', req => {

        const url = req.url

            // req.method客服端请求的类型 get 和post

        const method = req.method

        console.log('url' + url + 'method' + method)

    })

// 启动服务器

//8080端口

server.listen(8080, () => {

    console.log('server runing at http://127.0.0.1:8080')

})

Req对象即为客服请求的对象


Res响应的对象

// 导入http模块

const http = require('http')

// 创建文本服务器实列

const server = http.createServer()

// 为服务器绑定一个request事件

// req请求对象 包含了客服端相关的数据和属性

// req.url是客服端请求的url地址

server.on('request', (req, res) => {

        const url = req.url

            // req.method客服端请求的类型 get 和post

        const method = req.method

        const str = 'url${ url} ${method}'

        console.log('url' + url + 'method' + method)

            // 调用res方法像客服端响应一些内容  客服端可以看到

        res.end(str)

    })

    // 启动服务器

server.listen(8080, () => {

    console.log('server runing at http://127.0.0.1:8080')

})


解决中文乱码问题

当调用res.end()方法时想客服端发送内容时会出现乱码问题此时需要手动设置编码格式

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

// 导入http模块

const http = require('http')

// 创建文本服务器实列

const server = http.createServer()

// 为服务器绑定一个request事件

// req请求对象 包含了客服端相关的数据和属性

// req.url是客服端请求的url地址

server.on('request', (req, res) => {

        const url = req.url

            // req.method客服端请求的类型 get 和post

        const method = req.method

        const str = '哈哈请求成功'

        console.log('url' + url + 'method' + method)

        // 手动设置中文乱码问题

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

            // 调用res方法像客服端响应一些内容

        res.end(str)

    })

    // 启动服务器

server.listen(8080, () => {

    console.log('server runing at http://127.0.0.1:8080')

})


根据不同url地址响应不同的内容

核心步骤

1获取请求的url地址

2设置默认的响应内容为404 农田found

3判断用户请求的是否为或者/index.html页面

4判断用户清华求的是否是about.html

5设置Content-Type的响应头防止乱码

5使用res.end()方法把响应给客服内容

// 导入http模块

const http = require('http')

// 创建文本服务器实列

const server = http.createServer()

// 为服务器绑定一个request事件

// req请求对象 包含了客服端相关的数据和属性

// req.url是客服端请求的url地址

server.on('request', (req, res) => {

        const url = req.url //1获取请求的url地址

            // 2设置默认的响应内容为404 not found

        let content = '<h1>404 Not Find!</h1>'

            // 3判断用户请求的是否为或者/index.html页面

        if (url !== '/' || '/index.html') {

            content = '<h1>首页</h1>'

        } else if (url == '/about.html') {

            content = '<h1>about页面</h1>'

        }

        // 有请求的时候返回到终端

        console.log(url + '发起请求')

            // 手动设置中文乱码问题

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

            // 调用res方法像客服端响应一些内容

        res.end(content)

    })

    // 启动服务器

server.listen(8080, () => {

    console.log('server runing at http://127.0.0.1:8080')

})


时钟web服务器案列

把文件的实际路径作为请求的俩路径

浏览器    请求     服务器     磁盘

          响应            拿到    

服务器起到链接 拿数据             

实现步骤

1导入模快

2创建服务器

3将资源的去请求url地址映射为文件的存放位置

4读取文件内容并响应给客服端

5优化资源的请求路径

// 1.1 导入 http 模块

const http = require('http')

    // 1.2 导入 fs 模块

const fs = require('fs')

    // 1.3 导入 path 模块

const path = require('path')

// 2.1 创建 web 服务器

const server = http.createServer()

    // 2.2 监听 web 服务器的 request 事件

server.on('request', (req, res) => {

        // 3.1 获取到客户端请求的 URL 地址

        //     /clock/index.html

        //     /clock/index.css

        //     /clock/index.js

        const url = req.url

            // 3.2 把请求的 URL 地址映射为具体文件的存放路径

            // const fpath = path.join(__dirname, url)

            // 5.1 预定义一个空白的文件存放路径

        let fpath = ''

        if (url === '/') {

            fpath = path.join(__dirname, './clock/index.html')

        } else {

            //     /index.html

            //     /index.css

            //     /index.js

            fpath = path.join(__dirname, '/clock', url)

        }

        // 4.1 根据“映射”过来的文件路径读取文件的内容

        fs.readFile(fpath, 'utf8', (err, dataStr) => {

            // 4.2 读取失败,向客户端响应固定的“错误消息”

            if (err) return res.end('404 Not found.')

                // 4.3 读取成功,将读取成功的内容,响应给客户端

            res.end(dataStr)

        })

    })

    // 2.3 启动服务器

server.listen(80, () => {

    console.log('server running at http://127.0.0.1')

})


模快化

什么是模快化把系统分成若干模快对于整个系统来说模快可以组合分解和更换的单元

把一个大文件拆分成相互依赖的多个小模块

优点

1提高了代码的复用性

2提高了代码的可维护性

3可以实现按需加载

模快化规范 需要遵守  

便于沟通 利人利己

Node.js模块的分类

1内置模快(fs path http模快等)

2自定义模快 (用户创建的.js文件)

3第三方模快(由第三方发出的模快) 使用第三方模快需要下载


2.2加载模快

使用将达的require()方法可以架子啊内置模快

加载内置模块

const http = require('http')

加载自定义模块  写上路径就可以

const contcom = require('./const.js')

加载第三方模块 和加载内置模块差不多

const contcom = require('com')

注意带你当使用require时

完整的路径

加载自定义模块的时候可以不用加.js

const st = require('./用户自定义模块')

console.log(st)

Node中的模块作用域

在自定义模块中定义的白能量  方法等只能在当前模块中访问 其他模块不能访问

模块作用域的好处

防止全局变量污染问题

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

1module对象

每一个自定义模块中都有一个module对象

console.log(module)

<ref *1> Module {

  id: '.',

  path: 'C:\\Users\\强天尊\\text',

  exports: {},

  parent: null,

  filename: 'C:\\Users\\强天尊\\text\\077.js',

  loaded: false,

  children: [

    Module {

      id: 'C:\\Users\\强天尊\\text\\用户自定义模块.js',

      path: 'C:\\Users\\强天尊\\text',

      exports: {},

      parent: [Circular *1],

      filename: 'C:\\Users\\强天尊\\text\\用户自定义模块.js',

      loaded: true,

      children: [],

      paths: [Array]

    }

  ],

  paths: [

    'C:\\Users\\强天尊\\text\\node_modules',

    'C:\\Users\\强天尊\\node_modules',

    'C:\\Users\\node_modules',

    'C:\\node_modules'

  ]}

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

Module.exports对象

//外界导入的模块得到的对象moudle对象

const st = require('./用户自定义模块')

console.log(st)

// 当前这个文件就是一个自定义模块

// module.exports对象上挂uesername属性

module.exports.username = 'zs'

module.exports.sayHello = function() {

    console.log('hellow')

}

向外共享module对象

//外界导入的模块得到的对象moudle对象

const st = require('./用户自定义模块')

console.log(st)

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

// 当前这个文件就是一个自定义模块

// module.exports对象上挂uesername属性

module.exports.username = 'zs'

module.exports.sayHello = function() {

    console.log('hellow')

}

// 让module只想一个全重新的对象

module.exports = {

    nin: 'xiaohe',

    say() {

        console.log('hufgh')

    }

}

输出的为  远是module.exports指向的对象为准

{ nin: 'xiaohe', say: [Function: say] }

Exports对象

由于module.peports单词写起来不叫复杂为了简化成员代码node提供了exports对象

默认情况下 exports和moudle.exports指向的同一个对象

Exports对象moudle.exports使用的误区

时刻瑾记require模块时得到的永远是module.exports指向的对象

第五章npm+模块加载机制

5-1 包

Node.js的第三方模块又叫做包

包的来源

第三方提供的免费给所有人啊使用

为什么需要包 由于node.js 提供的内置模块一些底层的 效率不高

包基于内置模块封装的  提供了高级更方便  极大的提高了开发效率

包从哪里下载

Npm,inc  https://www.npmjs/,是全球最大的包共享平台

可以从 https://registry.npmjs/服务器  可以下载在iji所需的包

Npm初体验

1格式化是时间传统做法

需要手动封装时间函数

2高级做法不需要自己手动封装函数

在项目中安装包的命令

Npm install 包的完整名称

Npm代表包管理工具   简写模式 npm i 完整的包名称

PS C:\Users\强天尊\text> npm install moment

npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\强天尊\text\package.json'

npm notice created a lockfile as package-lock.json. You should commit this file.

npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\强天尊\text\package.json'

npm WARN text No description

npm WARN text No repository field.

npm WARN text No README data

npm WARN text No license field.

+ moment@2.29.1   //安装成功  包名称  版本号

added 1 package from 6 contributors and audited 1 package in 50.151s

found 0 vulnerabilities

官方的npm包的使用

在终端安装包

Npm install 包的完整名称

Npm代表包管理工具   简写模式 npm i 完整的包名称

// 使用npm 包管理工具 在项目中安装格式化时间的包moment

const moment = require('moment')

    // 参考老moment的官方的API文档对时间格式化

const dt = moment().format('YYYY-MM-DD HH:mm:ss')

console.log(dt)

查询官方的包的文档来使用

初次安装包或多了一个叫做 node_modules的文件夹和package-lock.js的配置文件

node_modules的文件用来存放已安装到项目中的包

package-lock.js 下载信息  

如何安装指定版本的包

Npm i moment@2.22.2  在后面加上@和版本号就可以

包的语义化版本规范

2.24.0

第一位数字:大版本

第二位数字:功能版本

第三个数字:bug修复版本

从2.24.0  升级  3.00.0  升级后其他的归零  

5-3包管理配置文件及解决下包慢的问题

多人协作的问题

遇到问题:第三方包的体积过大不方便团队之间共享项目源代码

共享的时候提出node_modules

如何记录项目中安装了那些包

在项目目录中创建一个叫做package.Json的配置文件,即课用来记录项目中安装了那些包从而方便剔除node-modules目录之后,团队成员之间共享项目源代码

在今后一定把node_modules文件夹  添加到,gitignorwe忽略文件中

如何让快速创建package.json

Npm 包管理工具提供了一个快捷命令 可以在执行命令所处的目录中,快速创建package.json这个包管理

Npm initial-y

只能使用英文不能使用中文

PS C:\Users\强天尊\text> npm init -y

Wrote to C:\Users\强天尊\text\package.json:

{

  "name": "text",

  "version": "1.0.0",

  "description": "",

  "main": "02判断文件是否读取成功.js",

  "dependencies": {

    "moment": "^2.29.1"

  },

  "devDependencies": {},

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC"

}

包管理配置文件  dependencies节点

包的信息  记录都安装了 那些包

 "dependencies": {

    "moment": {

      "version": "2.29.1",

      "resolved": "https://registry.npmjs/moment/-/moment-2.29.1.tgz",

      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="

    }

如何安装所有的包

可以运行 npm i 或 npm install  会直接访问package.json 文件中的 dependencies

Dependencies 含有所有包的名称

没有指定包的名字 会直接读取package.json 中的包  全部安装

加上包的名字会指定安装包

卸载包

可以运行npm uninstall 命令来卸载指定的包

PS C:\Users\强天尊\text> npm uninstall moment

npm WARN text@1.0.0 No description

npm WARN text@1.0.0 No repository field.

removed 1 package in 1.399s

found 0 vulnerabilities

删除后会显示没有找到包

PS C:\Users\强天尊\text> npm uninstall moment

npm WARN text@1.0.0 No description

npm WARN text@1.0.0 No repository field.

up to date in 1.391s

found 0 vulnerabilities

devDependencies

如果某些包之子啊开发阶段用到  在项目之后用不到 则建议把这些包记录到devDependencies 节点中去

使用如下命令  将包巨鹿到节点中

Npm i 包名-D

上面这个是简写

Npm install 包名 --save-dev

安装  文档显示这个就需要装到 -Dcls

使用 npm 安装:

npm install --save-dev webpack

用纱线安装:

yarn add webpack --dev

解决包下载慢  npm下载包会很慢

在使用npm下包的时候,默认从国外服务器进行下载下载包会很慢

2使用淘宝的镜像NPM镜像服务器

淘宝在国内搭建了一个服务器 专门把国外的官方的服务器上的包同步到国内服务器上

然后在国内提供下载包的服务 从而提高了下包的速度

每隔一段时间会同步国外服务器的包  对国内用户提供下包的服务

镜像是一种文件存储形式 相当于副本

切换npm的下包镜像源

查看当前的下包镜像源 npm config get registry

官方的

C:\Users\强天尊>npm config get registry

https://registry.npmjs/

切换为淘宝npm config get registry=https://registry.npm.taobao/

使用nrm工具帮助我们快速接换到淘宝镜像

安装nrm这个小工具 安装为全局可用  npm install nrm -g

-g安装为全局可用的包

查看当前所有的镜像源地址  nrm ls

将下包的镜像源切换为taobao镜像  nrm use taobao

包的分类

项目包安装到node_modules目录中

开发依赖包  devDependences -D 中

核心依赖包  devDependences   中

全局包  npm install montent -g中

卸载全局包  npm uninstall montent -g

只有工具包的性质才有必要安装

去包的文档查看是否安全为全局包

I5ting_toc

是一个可以把md文档转化为hml也买你的小工具

hh.md文件路径

i5ting_toc -f hh.md -o  

规范的包的结构

一个规范的包 他的组成结构 必须符合一下三点

1包必须一单独的目录而存在

2包的顶级目录下要必须包含package.json这个包管理配置

3package.json里面必须包含 name version main 这三个元素

开发属于自己的包

1需要实现的功能

1格式化时间

2转义  看到的是html字符转义带有样式

3还原html标签

初始化包的基本结构

1新建itheima-tools文件夹  作为包的根目录

2 itheima-tools文件夹中新建三个文件

Package.json(包管理配置文件)

Index.js(包的入口文件)

READM.md (包的说明文档)

配置文件  package.json

//报的名字

"name":"itheima-tools",

//版本

"version":"1.0.0",

//导入的就是main属性指向的这个文件

"main":"index.js",

//包的简短,描述

"description": "",

"dependencies": {},

    "keywords": [],

"author": "",

//开源许可协议ISC

    "license": "ISC"

}

在index.js中定义格式化时间的方法

// 包的入口文件

//定义格式化时间

function dateFormat(dataStar) {

    // 时间对象

    const dt = new Date(dataStar)

        // 获取年

    const y = dt.getFullYear()

        //  获取yue  从零开始所以要加1

    const m = padZERO(dt.getMonth() + 1)

        // 获取日

    const d = padZERO(dt.getDate())

    // 获取小时

    const hh = padZERO(dt.getHours())

        // 获取分钟

    const mm = padZERO(dt.getMinutes())

        // 获取秒

    const ss = padZERO(dt.getSeconds())

    return `${y}-${m}-${d}  ${hh}:${mm}:${ss}`

}

// 定义一个补零的函数

function padZERO(n) {

    return n > 9 ? n : '0' + n

}

// 向外暴露一个对象

module.exports = {

    dateFormat

}

在090文件测试

// 导入index.js

const itheima = require('./itheima-tools/index')

const str = itheima.dateFormat(new Date())

console.log(str)

2022-03-08  09:36:22

了解package.json中的main属性属性的作用

const itheima = require('./itheima-tools')

只给一个文件夹的路径没有指定那个文件  会去查找package.json  文件中的main属性

拿到文件 index.js

在index 中定义转义html的方法

// 定义html字符的函数

function htmlEscape(htmlstr) {

    return htmlstr.replace(/<|>|"&/g, (match) => {

        switch (match) {

            case '<':

                return '<'

            case '>':

                return '>'

            case '"':

                return '"'

            case "&":

                return '&'

        }

    })

}

// 向外暴露一个对象

module.exports = {

    dateFormat,

    htmlEscape

}

发布自己的包到npm

注册账号

在终端输入  npm login

登录自己的账号

Nrm LS 查看自己在那个镜像

Nrm use npm

把包发到npm上可以供下在和使用  使用 npm pubilsh 命令

包名不能相同

npm unpublish zhaoqiang-timeto --force

Npm账号

账号   zhaoqiangzhao

Password  ZQzq18230786916

  1. MAIL   2762169224@qq

模块的加载机制

优先从缓存机制中加载

这样提高模块加载效率

内置模块的加载机制   内置模块的加载优先级最高  如果和第三方模块的名字相同优先加载内置模块

自定义模块的加载机制  加载自定义模块必须以  ./开头

没有指定./  或者../  会被当作第三方模块或者内置模块  会加载不到

第六章Express

Express的学习目标

能够使用express.static()快速托管静态资源

能够使用express路由精简项目结构

能够使用常见的express中间间

能够使用express创建API接口

能够在express中启用cors跨域资源共享

Express 简介

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

可以设置中间件来响应 HTTP 请求。

定义了路由表用于执行不同的 HTTP 请求动作。

可以通过向模板传递参数来动态渲染 HTML 页面。

Express相当于npm的第三方包  提供了快速创建web服务器的快捷方法

不使用express 也可以搭建web服务器  使用node.js原生的http也可以

Express也是基于http  只是express  简单快速

两种服务器

Web网站服务器

API接口服务器

1安装express

 npm install express --save

在终端输入

Npm install express

 npm install express@4.17.1

创建基本的文本服务器

//导入express

const express = require('express')

    // 创建express

const app = express()

    // 启动express

app.listen(80, () => {

    console.log('express serve running at http://127.0.0.1')

})

监听GET请求

听过app.get()方法


app.get(url, function (req, res) {

 res.send('Hello World');

})

Res.send()  发送响应内容

Req请求对象

Res响应内容

监听post请求差不多

app.post(url, function (req, res) {

 res.send('Hello World');

})

//导入express

const express = require('express')

    // 创建express

const app = express()

    // 监听get和post请求  并想起响应内容、

app.get('/use', function(req, res) {

    res.send({

        name: 'zs',

        age: 30

    })

})

app.post('/use', (req, res) => {

    res.send('gdfgjh')

})

// 启动express

app.listen(80, () => {

    console.log('express serve running at http://127.0.0.1')

})

使用postman 工具测试post 和get请求

如何获取url 中携带的查询参数

通过  req.query对象 可以访问到客服端通过查询字符串的形式  发送到服务器的参数、、

app.get('/', function(req, res) {

    console.log(req.query)

    res.send(req.query)

})

获取url地址中的动态参数:后面的值

app.get('./user/:id', (req, res) => {

        // req.params 是动态匹配URL动态参数

        console.log(req.params)

    })

动态参数的两个注意点

app.get('./user/:id'

  Id 不是固定写法

app.get('./user/:id/:name',

匹配两个值

静态资源托管

Express.Static()

1app.use(express.static('publice'))

在外面访问puiblic目录中的所有文件

托管多个静态资源的目录

多次调用就可以

app.use(express.static('./clock'))

会根据先后顺序查找  

挂载路径前缀

如果希望在托管的静态资源访问路径之前 挂载路径前缀

app.use('/public', express.static('./clock'))

在访问的时候必须加上访问的过载前缀

http://127.0.0.1/public/index.html

1.4nodemon

这个小工具可以监听项目文件的变动 当代码被修改后nodemon会自动帮我们重启项目极大的方便了开发和调试

安装  

 Npm install -g nodemon

当你更改代码保存后  nodemon会帮你重启服务器   简便了操作  

使用  nodemon  来启动服务器

路由

我们已经了解了 HTTP 请求的基本应用,而路由决定了由谁(指定脚本)去响应客户端请求。

在HTTP请求中,我们可以通过路由提取出请求的URL以及GET/POST参数。

中间件

Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。

中间件(Middleware) 是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)), 和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。

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

Express中间件的格式

本质是function函数

// 挂载至 /user/:id 的中间件,任何指向 /user/:id 的请求都会执行它

app.use('/user/:id', function (req, res, next) {

console.log('Request Type:', req.method);

next();

});

包含next函数就是中间件

Next函数的作用

实现多个中间件的作用  是将流转关系交给下一个中间件

实现多个中间件的流转

定义中间件函数

const express = require('express')

const app = express()

const mw = function(req, res, next) {

    console.log('这是最简单的中间件')

    next()

}

app.listen(80, () => {

    console.log('http://127.0.0.1')

})

全局身生效的中间件

通过调用app.use(中间件函数)

const mw = function(req, res, next) {

    console.log('这是最简单的中间件')

    next()

}

app.use(mw)

定义全局中间件的简化

app.use(function() {

    console.log('简化的中间件')

    next()

})

中间件的作用

多个中间件可以共享一份 req和res 我们可以在上又的中间件统一为对象天件属性

在后面的中间件调用

const express = require('express')

const app = express()

app.use(function() {

    const time = new Date()

        // 下游的中间件可以使用

    req.startTime = time

    next()

})

app.get('/File', (req, res) => {

    res.send('user name')

})

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

    res.send('user')

})

app.listen(80, () => {

    console.log('http://127.0.0.1')

})

使用express写接口

创建基本服务器

const express = require('express')

const app = express()

app.listen(80, () => {

    console.log('http://127.0.0.1')

})

创建API路由模块

创建

const express = require('express')

const router = express.Router()

module.exports = router

调用

const express = require('express')

const router = require('./111API')

const app = express()

    // 导入路由模块

const router = require('./111API')

    // 吧路由模块注册到app

app.use('/api', router)

app.listen(80, () => {

    console.log('http://127.0.0.1')

})

编写GET接口

第七章Mysql数据库

s接口的跨域问题

1 cors  主流方案

2jsonp  支持GET  不支持post请求

2使用cors中间件解决跨越问题

Cors是express的一个第三方中间件 通过暗转配置cros中间件  可以方便的解决跨域问题

使用步骤如下

1运行  npm install cores

2使用  const cors=require(‘cors’)  导入中间件

3在路由之前调用 app.use(crs())配置中间件

2.1 什么是cors

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

浏览器端:

目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。

服务端:

CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,我们需要以此判断是否运行其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。


 

数据库和身份认证

数据库的概念  存储 和管理的仓库

常见的数据库分类

Mysql数据库  有免费的数据库

Oracle数据库

Sql server

Mysql oracle  sql server  传统数据库   三者都差不多

Mongodb数据库

传统数据库的组织结构

数据库组织结构  指的是数据以什么样的结构进行存储

数据库 数据表 数据行 字段

3.1 使用mysql workbench 管理数据库

1链接数据库

Columns:

id

int PK

username

varchar(45)

password

varchar(45)

status

tinyint(1)

Sql管理数据库

Sql 是结构化查询语言 代码创建  数据库  表  只能在关系型数据库中使用

1可以查询

2删除

3插入数据

4更新

5创建数据库 表

SQL SELECT 语句  查询语句

查询

SELECT * FROM table_name;    * 所有的信息  from  从那个表中查询

插入数据

insert into users (id,username , password) values(3,'tony','1234567')

插入数据要一一对应

值之间用,隔开  值用()括起来

更新密码

update users set password='88888888' where  id =3

删除    一定要加  where id  限定    否则全部删除了

delete from users where id=2

-- select * from users

-- 查询名字 密码

 --  select name ,password from  users

 -- insert into users (id,username , password) values(3,'tony','1234567')

 -- select * from users

 -- 将id=3 的密码改为  88888888

--  update users set password='88888888' where  id =3

-- select *from users where id=3

-- update users set password='admin123',status=1  where id=3

-- select * from users where id=3

-- delete from users where id=2

-- select * from users where id=2

-- select * from users

在项目中如何操作sql

1安装mysql 数据库  的三方模块 mysql

建立链接  才能进行操作

2通过mysql模块来凝结到mysql数据库

3通过 吗mysql 模块执行sql语句

1安装mysql 托管于npm上的sql

Npm install mysql

2配置mysql模块

var mysql = require('mysql');

var connection = mysql.createConnection({ 

host : 'localhost',

user : 'root',

password : '123456',

database : 'test' 

});

// 导入sql 模块

const mysql = require('mysql')

// 建立来链接

const db = mysql.createConnection({

    host: '127.0.0.1', //ip地址

    user: 'root', //账号

    password: 'admin123',

    database: 'zhaoqiang_one' //指定操作那个数据库

})

测试是否能与数据库链接

// 检测数据库是否正常工作

db.query('select 1', (err, results) => {

    // mysql 报错有问题

    if (err) console.log(err.message)

        // 能过成功执行sql语句

    console.log(results)

})

端口3306被占用

在创建数据库的时候更改端口号

链接数据库的时候加上端口号  port

const db = mysql.createConnection({

    host: '127.0.0.1', //ip地址

    port: '3308',

    user: 'root', //账号

    password: 'admin123',

    database: 'zhaoqiang_one' //指定操作那个数据库

})

使用sql语句查询数据

// 导入sql 模块

const mysql = require('mysql')

    // 建立来链接

const db = mysql.createConnection({

    host: '127.0.0.1', //ip地址

    port: '3308',

    user: 'root', //账号

    password: 'admin123',

    database: 'zhaoqiang_one' //指定操作那个数据库

})

// 检测数据库是否正常工作

// db.query('select 1', (err, results) => {

//     // mysql 报错有问题

//     if (err) console.log(err.message)

//         // 能过成功执行sql语句

//     console.log(results)

// })

// 查询users表的说有数据

const sqlStr = 'select * from users'

db.query(sqlStr, (err, results) => {

    if (err) console.log('获取失败')

    console.log(results)

})

执行sql语句查询到的数据是数组

const sqlStr = 'select * from users'

如何使用sql插入数据

// 插入数据

// 插入user表中的数据对象  username password

const user = { id: '1', name: 'sffpp' }

    // 要执行的sql语句 ? ? 占位符  

const sqlStr = 'insert into book (name) value(?)'

db.query(sqlStr, [user.id, user.name], (err, results) => {

    if (err) return console.log(err.message)

    if (results.affectedRows === 1) {

        console.log(results + '成功')

    }

})

如果报错出现

ER_NO_DEFAULT_FOR_FIELD: Field 'id' doesn't have a default value

数据库的表没有将id设置为自增

插入的值意义对应可恶意使用跨界方式插入

const user = { username: 'ghjdfj', password: '35254h' }

const sqlstr = 'insert into users set ?'

db.query(sqlstr, user, (err, result) => {

    if (err) return console.log(err.message)

    if (result.affectedRows === 1) {

        console.log('成功')

    }

})

更新数据库中的数据

// 更新数据

const user = { id: 1, usersname: 'www', password: '12345678' }

const sqll = 'update users set username=?,password=? where id=?'

db.query(sqll, [user.usersname, user.password, user.id], (err, results) => {

    if (err) return console.log(err.message)

    if (results.affectedRows === 1) {

        console.log('成功')

    }

})

不能忘记id  如果id 没有写 所有的数据都会被更新

更新的快捷方式

// 更新数据

const user = { id: 1, username: 'hhh', password: '123345678' }

const sqll = 'update users set ? where id=?'

db.query(sqll, [user, user.id], (err, results) => {

    if (err) return console.log(err.message)

    if (results.affectedRows === 1) {

        console.log('成功')

    }

})

Sql删除表的数据

需要指定id 当占位符只有一个的时候  不用写数组  直给值就可以

// 删除数据、

const sqlde = 'delete from users where id=?'

db.query(sqlde, 3, (err, results) => {

    if (err) return console.log(err.message)

    if (results.affectedRows === 1) {

        console.log('成功')

    }

})

这样删除是不安全的

使用delete 删除数据使用标记删除来模拟删除状态

状态码来显示数据被删除  更新状态码就行

// 标记删除

const sqlstr = 'update users set status=? where id=?'

db.query(sqlstr, [1, 1], (err, results) => {

    if (err) return console.log(err.message)

    if (results.affectedRows === 1) {

        console.log('成功')

    }

})

第八章身份认证

8-1web开发模式

前后端分离的开发模式

前端分离的开发模式 依赖于Ajax技术的广泛应用后端值负责提供API接口

前端使用ajax调用接口的开发模式

前后端分离的优缺点

1开发体验好 ,前端之哦专注与UI界面的开发,后端专注与api的开发 前端有更多的选择

2用户体验好 ajax提高用户的体验

3减轻服务器的渲染压力

缺点不利于seo,所以爬虫不能爬取有效数据 解决方案有vue ,react等前端框架的ssr技术能解决这个问题

如何选择web开发模式

比如企业级网站 ,主要功能是展示而没有复杂的交互,并且需要良好的SEO,则这时我们就需要使用服务器端渲染

后台管理项目 交互性强不需要考虑SEO,那么就使用前后端分离

身份认证

Web开发登录  扫二维码登录 邮箱登录

不同web开发模式下的身份认证

1服务器端渲染推荐使用 Session认证机制

2前后端分离使用JWT认证

Session认证机制

3. 什么是 Cookei

Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成

不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的 Cookie 一同发送到服务器

Cookie 的几大特性

  • 自动发送
  • 域名独立
  • 过期时限
  • 4KB 限制

4. Cookie 在身份认证中的作用

客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的 Cookie,客户端会自动将 Cookie 保存在浏览器中。

随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的 Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份

5. Cookie 不具有安全性

由于 Cookie 是存储在浏览器中的,而且浏览器也提供了读写 Cookie 的 API,因此 Cookie 很容易被伪造,不具有安全性。因此不建议服务器将重要的隐私数据通过 Cookie 的形式发送给浏览器

注意:千万不要使用 Cookie 存储重要且隐私的数据! 比如用户的身份信息、密码等

安装express—session

安装

 npm install express -session

配置

Aap.use()来注册

// TODO_01:请配置 Session 中间件

const session = require('session')

app.use(session({

    secrt: 'itheima',

    resave: false,

    saveUninitialized: true

}))

// 登录的 API 接口

app.post('/api/login', (req, res) => {

    // 判断用户提交的登录信息是否正确

    if (req.body.username !== 'admin' || req.body.password !== '000000') {

        return res.send({ status: 1, msg: '登录失败' })

    }

    // TODO_02:请将登录成功后的用户信息,保存到 Session 中

    // 注意智友 成功配置来哦express-session 才可以通过req.sue

    req.session.user = req.body //用户信息

    req.session.islogin = true

    res.send({ status: 0, msg: '登录成功' })

})

取数据

// 获取用户姓名的接口

app.get('/api/username', (req, res) => {

    // TODO_03:请从 Session 中获取用户的名称,响应给客户端

    if (req.session.islogin) {

        return res.send({ static: 1, msg: 'fail' })

    }

    res.send({

        static: 0,

        msg: 'sucess',

        username: req.session.user.username

    })

})

清空服务器保存的信息

退出登录的时候需要清空对应的信息

// 退出登录的接口

app.post('/api/logout', (req, res) => {

    // TODO_04:清空 Session 信息

    req.session.destroy()

    res.send({

        static: 0,

        msg: '退出登录'

    })

})

不会清空所有人的

前端有跨域问题哦不建议使用session认证机制

Jwt认证   跨域认证

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

{

  "姓名": "张三",

  "角色": "管理员",

  "到期时间": "2018年7月1日0点0分"}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

三、JWT 的数据结构

实际的 JWT 大概就像下面这样。

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

JWT 的三个部分依次如下。

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

写成一行,就是下面的样子。

Header.Payload.Signature

下面依次介绍这三个部分。

3.1 Header

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

{

  "alg": "HS256",

  "typ": "JWT"}

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。

3.2 Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

{

  "sub": "1234567890",

  "name": "John Doe",

  "admin": true}

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

这个 JSON 对象也要使用 Base64URL 算法转成字符串。

3.3 Signature

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(

  base64UrlEncode(header) + "." +

  base64UrlEncode(payload),

  secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

3.4 Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-/替换成_ 。这就是 Base64URL 算法。

四、JWT 的使用方式

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

Authorization: Bearer <token>

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

五、JWT 的几个特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

定义secret// TODO_02:定义 secret 密钥,建议将密钥命名为 secretKey

在登录成功后生成jwt的字符

    // 登录成功

    // TODO_03:在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端

    jwt.sign({username:userinfo.username},secretKey,{expiresIn:'30s'})

更多推荐

node.js自学基础笔记