概念:用来创建 web
服务器的模块。通过 http
模块提供的 http.createServer()
方法,就能方便的把一台普通的电脑,变成一台 Web
服务器,从而对外提供 Web
资源服务
使用 http
模块创建 Web
服务器,则需要先导入它:
const http = require('http')
http
模块的作用:
1、服务器和普通电脑的区别在于,服务器上安装了 web
服务器软件
2、我可可以基于 Node.js
提供的 http
模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web
服务
服务器相关的概念
ip
地址
-
IP 地址
就是互联网上每台计算机的唯一地址,因此IP 地址
具有唯一性 -
IP 地址
的格式:通常用“点分十进制”表示成(a.b.c.d)
的形式,其中,a,b,c,d
都是 0~255 之间的十进制整数
-
例如:用点分十进表示的
IP
地址(192.168.1.1)
域名和域名服务器
-
尽管
IP 地址
能够唯一地标记网络上的计算机,但IP地址
是一长串数字,不直观,而且不便于记忆,于是人们又发明了另一套字符型的地址方案,即所谓的域名地址(Domain Name) -
IP地址
和域名
是一一对应的关系,这份对应关系存放在一种叫做域名服务器(DNS,Domain name server)
的电脑中。使用者只需通过好记的域名访问对应的服务器即可,对应的转换工作由域名服务器实现。因此,域名服务器就是提供IP 地址
和域名之间的转换服务的服务器
注意事项:
1. 单纯使用 `IP 地址`,互联网中的电脑也能够正常工作。但是有了域名的加持,能让互联网的世界变得更加方便
2.在开发测试期间, 127.0.0.1
对应的域名是 localhost
,它们都代表我们自己的这台电脑,在使用效果上没有任何区别
端口号
-
在一台电脑中,可以运行成百上千个
web 服务
-
每个
web 服务
都对应一个唯一的端口号 -
客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的
web 服务
进行处理
创建web服务器
实现步骤和核心代码
1 // 1. 导入 http 模块 2 const http = require('http') 3 // 2. 创建 web 服务器实例 4 // 调用 http.createServer() 方法,即可快速创建一个 web 服务器实例 5 const server = http.createServer() 6 // 3. 为服务器实例绑定 request 事件 7 // 为服务器实例绑定 request 事件,即可监听客户端发送过来的网络请求 8 // 使用服务器实例的 .on() 方法,为服务器绑定一个 request 事件 9 server.on('request', function (req, res) { 10 console.log('Someone visit our web server.') 11 }) 12 // 4.调用服务器实例的 .listen() 方法,即可启动当前的 web 服务器实例 13 server.listen(8080, function () { 14 console.log('server running at http://127.0.0.1:8080') 15 })
req
请求对象
1 const http = require('http') 2 const server = http.createServer() 3 // req 是请求对象,包含了与客户端相关的数据和属性 4 server.on('request', (req, res) => { 5 // req.url 是客户端请求的 URL 地址 6 const url = req.url 7 // req.method 是客户端请求的 method 类型 8 const method = req.method 9 const str = `Your request url is ${url}, and request method is ${method}` 10 console.log(str) 11 // 调用 res.end() 方法,向客户端响应一些内容 12 res.end(str) 13 }) 14 server.listen(80, () => { 15 console.log('server running at http://127.0.0.1') 16 })
res
响应对象
在服务器的 request 事件处理程序中,如果想访问与服务器相关的数据和属性,可以使用如下方式
1 server.on('request', function (req, res) { 2 // res 是响应对象,它包含了与服务器相关的数据和属性 3 // 例如:将字符串发送到客户端 4 5 const str = `${req.url} -- ${req.method}` 6 7 // res.end() 方法的作用 8 // 向客户端发送指定的内容,并结束这次请求的处理过程 9 res.end(str) 10 })
解决中文乱码问题
当调用 res.end()
方法,向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式
1 const http = require('http') 2 const server = http.createServer() 3 4 server.on('request', (req, res) => { 5 // 定义一个字符串,包含中文的内容 6 const str = `您请求的 URL 地址是 ${req.url},请求的 method 类型为 ${req.method}` 7 // 调用 res.setHeader() 方法,设置 Content-Type 响应头,解决中文乱码的问题 8 res.setHeader('Content-Type', 'text/html; charset=utf-8') 9 // res.end() 将内容响应给客户端 10 res.end(str) 11 }) 12 13 server.listen(80, () => { 14 console.log('server running at http://127.0.0.1') 15 })
根据不同的 url
响应不同的内容
核心实现步骤
-
获取请求的
url
地址 -
设置默认的响应内容为
404 Not found
-
判断用户请求的是否为
/
或/index.html
首页 -
判断用户请求的是否为
/about.html
关于页面 -
设置
Content-Type
响应头,防止中文乱码 -
使用
res.end()
把内容响应给客户端
1 const http = require('http') 2 const server = http.createServer() 3 4 server.on('request', (req, res) => { 5 // 1. 获取请求的 url 地址 6 const url = req.url 7 // 2. 设置默认的响应内容为 404 Not found 8 let content = '<h1>404 Not found!</h1>' 9 // 3. 判断用户请求的是否为 / 或 /index.html 首页 10 // 4. 判断用户请求的是否为 /about.html 关于页面 11 if (url === '/' || url === '/index.html') { 12 content = '<h1>首页</h1>' 13 } else if (url === '/about.html') { 14 content = '<h1>关于页面</h1>' 15 } 16 // 5. 设置 Content-Type 响应头,防止中文乱码 17 res.setHeader('Content-Type', 'text/html; charset=utf-8') 18 // 6. 使用 res.end() 把内容响应给客户端 19 res.end(content) 20 }) 21 22 server.listen(80, () => { 23 console.log('server running at http://127.0.0.1') 24 })
模块化概念:
-
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元
-
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块
-
把代码进行模块化拆分的好处
-
提高了代码的复用性
-
提高了代码的可维护性
-
可以实现按需加载
Node
中的模块化
-
内置模块(内置模块是由
Node.js
官方提供的,例如fs
、path
、http
等) -
自定义模块(用户创建的每个
.js
文件,都是自定 义模块) -
第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
使用 require
方法加载模块
1 // 1. 加载内置的 fs 模块 2 const fs = require('fs') 3 4 // 2. 加载用户的自定义模块 5 const custom = require('./custom.js') 6 7 // 3. 加载第三方模块,(使用第三方模块,下面会进行讲解) 8 const moment = require('moment')
注意事项 1: 使用 require() 方法加载其他模块时,会执行被加载模块中的代码**
注意事项2: 在使用 require
加载用户自定义模块期间,可以省略 .js
后缀名**
模块作用域
概念:和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,外部文件是访问不到的,这种模块级别的访问限制,叫做模块作用域
1 // 被加载的模块.js 2 3 const username = '张三' 4 5 function sayHello () { 6 console.log('说话') 7 }
1 // 加载模块.js 2 3 const custom = require('./被加载的模块')
模块作用域的好处:防止了全局变量污染、文件依赖等问题的产生
模块化最基础认识(*重点*)
module
对象
module.exports
对象的作用
-
在自定义模块中,可以使用
module.exports
对象,将模块内的成员共享出去,供外界使用 -
外界用
require()
方法导入自定义模块时,得到的就是module.exports
所指向的对象
1 // 记载模块.js
2 const mo = require('./被加载的模块')
4 console.log(mo) // {}
1 // 被加载的模块.js 2 3 // 当外界使用 require 导入一个自定义模块的时候,得到的成员,就是模块中,通过 module.exports 指向的那个对象 4 // console.log('我会被加载')
使用 module.exports
向外共享成员
sum.js
1 const username = 'ifer'; 2 const sum = (a, b) => a + b; 3 4 // 最佳实践,推荐写法 5 module.exports = { 6 username, 7 sum 8 }; 9 10 /* // 往 module.exports 对象上挂载了一个属性是一个字符串 11 module.exports.username = username; 12 13 // 往 module.exports 对象上挂载了一个属性是一个方法 14 module.exports.sum = (a, b) => a + b; */
index.js
1 // require 得到的结果就是这个 sum.js 文件中 module.exports 所指向的对象 2 // ./ 一定不能省略,因为 sum.js 是一个自定义模块 3 const modSum = require('./sum'); 4 5 const res = modSum.sum(1, 3); 6 console.log(res); // 4 7 8 // 这个 username 和引入的 sum.js 中的 username 没有任何关系 9 const username = 'elser'; 10 11 console.log(username); // elser 12 console.log(modSum.username); // ifer
终端命令
node index.js
共享成员时的注意点:使用 require()
方法导入模块时,导入的结果,永远以 module.exports
指向的对象为准
1 // 加载模块.js 2 const mo = require('./被加载的模块.js') 3 4 console.log(mo) // { username: '小黑', sayHi: [Function: sayHi] }
1 // 被加载模块.js 2 3 // 当外界使用 require 导入一个自定义模块的时候,得到的成员,就是模块中,通过 module.exports 指向的那个对象 4 // console.log(module) 5 6 // 向 module.exports 对象上挂载 username 属性 7 module.exports.username = 'zs' 8 9 // 向 module.exports 对象上挂载 sayHello 方法 10 module.exports.sayHello = function () { 11 console.log('Hellp') 12 } 13 14 // 使用 module.exports 指向一个全新的对象 15 module.exports = { 16 username: '小黑', 17 sayHi() { 18 console.log('小黑') 19 } 20 }
exports
对象
exports
和 module.exports
指向同一个对象。最终共享的结果,还是以 module.exports
指向的对象为准
1 console.log(exports) 2 3 console.log(module.exports) 4 5 // 默认情况下,`exports` 和 `module.exports` 指向同一个对象 6 console.log(exports === module.exports) // true
1 // 将私有成员共享出去 2 exports.username = 'zs' 3 4 // 直接挂载方法 5 exports.sayHello = function () { 6 console.log('Hellp') 7 }
exports
和 module.exports
的使用误区
-
时刻谨记,==
require()
模块时,得到的永远是module.exports
指向的对象 -
注意:为了防止混乱,建议大家不要在同一个模块中同时使用
exports
和module.exports
1 exports.username = 'Tom' // 不会被打印 2 3 module.exports = { 4 gender: '男', 5 age: 22 6 } 7 8 module.exports.username = 'Tom' 9 10 // 不会被执行 11 exports = { 12 gender: '男', 13 age: 22 14 } 15 16 17 // 两个都会执行 18 module.exports.username = 'Tom' 19 20 exports.gender = '男' 21 22 // 三个都会打印 23 exports = { 24 gender: '男', 25 age: 22 26 } 27 28 module.exports = exports 29 module.exports.username = 'Tom'
CommonJS
模块化规范
-
Node.js
遵循了CommonJS
模块化规范,CommonJS
规定了模块的特性和各模块之间如何相互依赖 -
CommonJS
规定:
-
每个模块内部,
module
变量代表当前模块 -
module
变量是一个对象,它的exports
属性(即module.exports
)是对外的接口 -
加载某个模块,其实是加载该模块的
module.exports
属性。require() 方法用于加载模块