Node.js第二天

156 阅读9分钟

Node.js 内置模块-Http开启web服务器:

一.服务器相关概念

1.服务器:

  • 提供网络服务的一台机器,通过在自己的电脑上安装特殊的软件(或者是运行某段特殊的代码)来提供服务 简单来说:服务器 = 电脑 + 能给其它电脑提供服务的软件

2.客户端与服务器:

  • 提供服务的是服务器,享受服务的是客户端

3.web服务器(重点学习):

  • 安装apache/tomcat/iis或者在nodejs环境写代码来提供:图片/视频/音频浏览/新闻数据浏览等服务的服务器
  • 用户通过浏览器来享受web服务器提供的图片,视频,音频等网页内容浏览的服务
  • 用户用url地址来访问某个web服务器上的资源
  • 浏览器端发起请求,web服务器收到请求后,响应这个请求,并将处理结果返回给浏览器
  • 浏览器端与web服务器是通过http(或者是https)协议来进行请求和响应的

4.ftp服务器:

  • 安装serv-U软件,为其它电脑提供文件下载,共享服务

5.数据库服务器:

  • 安装mysql软件,为其它电脑提供数据库服务

6.IP地址:

  • 全称: Internet Protocol Address
  • 作用: 标识一个网络设备(计算机、手机、电视)某一个具体的网络当中的地址,要访问某个电脑上的资源,先要找到它的ip
  • 同一个网络中,计算机的IP是不允许相同的,都是唯一的
  • IP分类:IPV4(互联网协议第6版)、 IPV6(互联网协议第6版)
  • IPV4格式: [0-255].[0-255].[0-255].[0-255] 即为四个 0-255 的数字组成
  • 127.0.0.1(本机访问) 或 192.168.106.2(局域网访问) 或 220.181.38.149(外网访问)
  • IPV6格式:X:X:X:X:X:X:X:X,每个X 以十六进制表示(了解)
  • FF01:0:0:0:0:0:0:1101 → FF01::1101,可以把连续的一段0压缩为“::”

7.域名: ip地址的别名

  • 127.0.0.1 的别名为 localhost 系统自动解析的,不需要做额外的配置
  • 220.181.38.149的别名为 www.baidu.com 需要域名解析系统把域名翻译成IP地址,需要额外购买和配置

8.端口:

  • 理解:如果理解IP地址(一台服务器)是一栋大商场,端口就是商场中的商铺的编号

  • 一个网络设备可以有65536个端口,范围是从[0,65535])

  • 不同的端口被不同的软件占用,以提供不同的服务

  • 服务器要提供服务必须通过指定的端口

  • 客户端与服务器都需要通过特定端口要进行通信http://157.122.54.189:9092

  • 端口是可以编程分配

  • 有一些端口号是被预定了的

    • http: 80
    • https:443
    • mysql:3306

9.HTTP协议:

  • 协议:制定客户端与服务器之间的通讯规则,不同的协议的作用也不同,我们主要了解HTTP协议

  • http协议

    • 定义:HTTP(HyperText Transfer Protocol) 超文本传输协议,浏览器与web服务器都要遵守的协议
    • HTTP 协议中明确规定请求数据响应数据格式(报文)
  • 浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)

  • 服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)

二.核心模块Http实现一个Web服务器

1.用http 模块写一个简单的web服务器:

//1.创建一个web服务器 导入http模块
const http = require("http")
//2.创建一个服务
const server = http.createServer((req, res) => {
    console.log('接受到了客户端的请求');
    res.end('OK')
})
//3.监听8000端口并启动web服务器等待客户端请求
server.listen(8000, () => {
    console.log('服务器准备就绪');
})
复制代码

工作原理:使用http模块在本机上创建一个Web服务器,它来接收浏览器的请求,并给出响应。

Http模块创建Web服务器代码解析:

2.req.url:

  • 通过 req.url来获取当前请求的url路径
  • 不同的请求url通过req.url获取的结果

代码:

//1.创建一个web服务器 导入http模块
const http = require("http")
//2.创建一个服务
const server = http.createServer((req, res) => {
    //获取到url的结果
    console.log(req.url);
    res.end('OK')
})
//3.监听8000端口并启动web服务器等待客户端请求
server.listen(8000, () => {
    console.log('服务器准备就绪');
})
复制代码

3.res.end()设置响应体:

  • 语法:res.end(响应的数据) end()只能传入buffer或者是String类型的数据
  • 作用:设置响应体并结束本次请求
  • 用法:在createServer的回调函数中使用
  • 注意:一次请求只能有一个res.end()响应,多个以第一个响应的数据为准,同时服务器报错终止

4.res.setHeader()设置响应头解决中文乱码:

  • 作用:设置响应头信息,控制浏览器的一些行为

  • 语法:res.setHeader(响应头,响应值) ,两个参数的具体值都是http协议规定的

  • 用法:在createServer的回调函数中使用

  • 注意:

    • res.setHeader()在res.end()之前才有效
    • res.setHeader()可以设置多次
  • 解决响应中文字符在浏览器显示成乱码问题

    • res.setHeader(“Content-Type”, ”text/html;charset=utf8”):
    • res.setHeader("Content-Type", 'application/javascript;charset=utf8' );
//1.创建一个web服务器 导入http模块
const http = require("http")
//2.创建一个服务
const server = http.createServer((req, res) => {
    //防止中文乱码
    res.setHeader("Content-Type", 'application/javascript;charset=utf8');
    res.end('OK')
})
//3.监听8000端口并启动web服务器等待客户端请求
server.listen(8000, () => {
    console.log('服务器准备就绪');
})
复制代码

5.res.statusCode设置状态码:

  • 场景:浏览器输入了一个不存在的url,则服务器返回404状态码

  • 语法:res.statusCode = 状态码,状态码是http协议规定的

    • 状态码: 500 (服务器异常) 404(资源找不到)
  • 注意:res.statusCode只有在res.end()前执行才有效

6.修改了服务器的代码要重启:

  • 场景:更改res.end()的内容,重启后,再次观察是否有更新

    • 停止服务: 在小黑窗中按下ctrl+c 停止服务
    • 重启服务:就是重新运行程序(按下向上的箭头,再回车)

7.content-type作用:

在http协议中,content-type用来告诉对方本次传输的数据的类型是什么

  • 在请求头中设置content-type来告诉服务器,本次请求携带的数据是什么类型的

  • 在响应头中设置content-type来告诉浏览器,本次返回的数据是什么类型的

  • res.setHeader方法可以设置content-type这个响应头,浏览器根据不同类型做出不同解析

  • ※ 请求头和响应头都可以设置content-type

  • 常见的几种文件类型及content-type

    • .html:res.setHeader('content-type', 'text/html;charset=utf8')
    • .css:res.setHeader('content-type', 'text/css;charset=utf8')
    • .js:res.setHeader('content-type', 'application/javascript')
    • .png:res.setHeader('content-type', 'image/png')
    • json数据:res.setHeader('content-type', 'application/json;charset=utf-8')

三.Web服务器处理接口响应

1.接口请求方式:

  • 发送接口请求的类型: get post delete put ...
  • web服务器通过req.method获取当前请求的类型

2.接口请求的各种表现形式:

3.不带参数的接口:

  • 场景:在server.js中写代码,提供一个名为getHero的Get接口(http://127.0.0.1:8003/getHero)它以json字符串格式返回db/data.json的内容

    //导入http模块
    const http = require("http")
    //创建服务
    const server = http.createServer((req, res) => {
        const { method, url } = req
        //防止中文乱码
        res.setHeader("Content-Type", 'application/javascript;charset=utf8');
    ​
        if (method === "GET" && url === '/member/cart') {
            res.end("获取购物车商品")
        } else if (method === "POST" && url === '/member/cart') {
            res.end("加入购物车")
        } else if (method === "DELETE" && url === '/member/cart') {
            res.end("删除购物车")
        } else {
            res.end("OK")
        }
    })
    server.listen(8001, () => {
        // 启动服务(监听)
        console.log('请求成功');
    })
    复制代码
    

4.带参数的Get接口:

场景:在server.js中写代码,提供一个名为getHero的Get接口(http://127.0.0.1:8003/getHero?name=xxx)它以json字符串格式返回db/data.json的name为xxx的内容

前置知识:

  • get请求的参数是附加在url后面

  • URLSearchParams 解析参数

    • URLSearchParams可以将查询字符串解析成一个对象,通过get方法获取到指定参数值

          <script>
              const query = 'name=后裔'
              //通过URLSearchParams解析参数值
              const usp = new URLSearchParams(query)
              //通过get方法获取到查询字符串name参数的值
              const nameValue = usp.get('name')
              console.log(nameValue);
          </script>
      复制代码
      

5.postman工具测试api接口:

  • postman是一款api接口的测试工具,可以模拟get,post,文件上传等请求
  • 下载地址+汉化

四.代码片段:导包express

//1.导包
const express = require('express')
const fs = require('fs')
​
//2.创建服务
const server = express()
​
const stuPath = "./db/student.json"//获取请求数据需要主动开启,不开启功能req.body的值为undefined
server.use(express.urlencoded())
​
server.get("/", (req, res) => {
​
    res.send("主页")
})
//======业务开始========//查询所有学员
server.get("/student", (req, res) => {
    //读取文件
    fs.readFile(stuPath, (err, data) => {
        //读取失败,就响应失败的提示
        if (err) return res.send({
            code: 1,
            message: "获取失败",
        })
        //成功响应
        res.send({
            code: 0,
            message: "获取成功",
            data: JSON.parse(data)
        })
    })
})
​
//增加学员
server.post("/student", (req, res) => {
    // console.log('请求体数据', req.body);
    //读取文件
    fs.readFile(stuPath, (err, data) => {
        //读取文件失败提醒
        if (err) return res.send({
            code: 1,
            message: "获取失败",
        })
        //处理学生格式
        const stu = {
            id: Date.now(),
            name: req.body.name,
            age: Number(req.body.age),
            sex: req.body.sex
        }
        //把读取的文件解析成数组
        const arr = JSON.parse(data)
        //追加数据
        arr.push(stu)
        //把新数据写入目标文件中 注意参数二要转JSON字符串
        fs.writeFile(stuPath, JSON.stringify(arr, null, 2), err => {
            //写入文件失败提醒
            if (err) return res.send({
                code: 1,
                message: "增加失败",
            })
            //写入成功
            res.send({
                code: 0,
                message: "增加成功",
            })
        })
    })
​
})
​
//删除学员
server.delete("/student", (req, res) => {
    // console.log('query查询参数', req.query)
    //读取文件
    fs.readFile(stuPath, (err, data) => {
        //失败提示
        if (err) return res.send({
            code: 1,
            message: "获取失败",
        })
        //根据id删除一条数据
        const arr = JSON.parse(data)
        // 通过过滤实现删除
        const newArr = arr.filter(item => item.id !== Number(req.query.id))
        // 写入新数组
        fs.writeFile(stuPath, JSON.stringify(newArr, null, 2), (err, data) => {
            //失败提示
            if (err) return res.send({
                code: 1,
                message: "删除失败",
            })
            //删除成功提示
            res.send({
                code: 0,
                message: "删除成功",
            })
        })
    })
})
​
//修改学员
server.put("/student", (req, res) => {
    // console.log(req.body)
    // 读取文件
    fs.readFile(stuPath, (err, data) => {
        //失败提示
        if (err) return res.send({
            code: 1,
            message: "获取失败",
        })
        //转换成数组
        const arr = JSON.parse(data)
        //从数组中查找要修改的数组项
        const stu = arr.find(item => item.id === Number(req.body.id))
        // 修改信息
        stu.name = req.body.name
        stu.age = Number(req.body.age)
        stu.sex = req.body.sex
        // 重新写入
        fs.writeFile(stuPath, JSON.stringify(arr, null, 2), err => {
            //失败提示
            if (err) return res.send({
                code: 1,
                message: "修改失败",
            })
            //成功提示
            res.send({
                code: 0,
                message: "更新学员成功",
            })
        })
    })
})
​
//3.// 启动服务(监听)
server.listen(8000, () => {
    console.log('服务器启动完成');
})
复制代码