服务器基础概念

学习NodeJS的意义

  • 了解客户端浏览器与服务端后台的交互过程,可以在以后的前端开发工作中与后台人员之间的沟通更加容易理解
  • 虽然以后工作中不一定用的上nodejs,但是通过对服务端开发的了解,能够让你在日常工作中与公司后台人员之间的沟通变得更加轻松
  • 了解服务端开发的一些特性,可以在以后的工作中,当我们前端与后台交互出现bug问题时,能够更快速的定位bug是出现在自己的客户端还是别人的服务端。
  • 作为一名前端人员,如果对后台不了解,那么以后在与后台交互的开发中有可能明明是后台的问题,但是由于自身对后台的不了解再加上前期的经验不足,导致解决问题的时间增加。
  • 了解服务端开发的过程,可以为以后的职业发展打下一定的基础(全栈工程师)

什么是Nodejs

  • Node 是一个构建于 Chrome V8引擎之上的一个Javascript 运行环境
  • Node是一个运行环境,作用是让js拥有开发服务端的功能
  • Node使用事件驱动、非阻塞IO模型(异步读写)使得它非常的轻量级和高效
  • Node中绝大多数API都是异步(类似于ajax),目的是提高性能
  • Node中的NPM是世界上最大的开源库生态系统(类似于github)

服务端js与客户端js区别

  • 客户端JavaScript由三部分组成
    • ECMAScript:确定js的语法规范
    • DOM:js操作网页内容
    • BOM:js操作浏览器窗口
  • node中的JavaScript
    • 组成
    • ECMAScript
    • 核心模块
    • 第三方模块
  • 基本的语法和写法和之前的js没有本质的区别
  • 在nodejs中使用dom与bom的api程序会报错
  • 服务器端没有界面
  • 压根不需要操作浏览器和页面元素

在学习创建服务器前需要了解基本的核心模块:

nodejs核心模块

  • readFile读取文件
    1.导入文件模块
    const fs = require('fs');

2.异步读取文件

  • 第一个参数:文件路径

  • 第二个参数:编码格式 (可选参数,默认为buffer二进制)

  • 第三个参数:读取回调操作(异步操作)

  • err:如果读取成功,err为null, 否则读取失败(一般文件路径错误或者找不到文件)

  • data:读取到的数据

    fs.readFile('./data/aaa.txt','utf-8',(err,data)=>{
        if(err){
            console.log(err);
            //抛出异常,throw的作用就是让node程序终止运行,方便调试
            throw err;
        }else{
            console.log(data);
        };
    });```
    
    
    

fs 模块是node提供的核心模块--装好了node就能直接使用这个核心模块
fs核心模块可以进行文件(目录)的相关操作
require方法可以引入模块,并返回一个对象,通过返回的对象可以调用模块中提供的api
语法: const myfs = require('fs')

  • writeFile写入文件

1.导入文件模块
const fs = require('fs');

2.异步写文件

  • 第一个参数:文件路径

  • 第二个参数:要写入的数据

  • 第三个参数:文件编码 默认utf-8

  • 第四个参数: 异步回调函数

  • err: 如果成功,err为null.否则读取失败

    fs.writeFile('./data/bbb.txt','黑马程序员','utf-8',(err)=>{
        if(err){
            throw err;
        }else{
            console.log('写入成功');
        };
    });```
    
    
    
  • appendFile追加内容 :
    1.可以往指定的文件中追加内容--不会覆盖原文件的内容

  • path路径模块
    1.在服务端开发中,一般不要使用相对路径,而使用绝对路径
    2.在nodejs中,每一个js文件都有两个全局属性,它可以帮助我们获取到文件的绝对路径

  • __filename:当前js文件 所在目录 的绝对路径,当前文件的全路径:目录+文件名称

  • __dirmame:当前js文件的绝对路径,当前文件所在的目录
    示例:
    1.导入文件模块
    const fs = require('fs');

2.如果想要获取当前文件夹下其他文件绝对路径,可以使用 __dirname属性来拼接
let path = __dirname + '/文件名';

(注意:通过path.join可以生成规范化的路径:path.join(__dirname, '/views/login.html') 会自动拼接成规范地址)

什么是服务器

一个管理资源并为用户提供服务的计算机,通常分为文件服务器(能使用户在其它计算机访问文件,我们平时访问的网页也一个一个的文件),数据库服务器和应用程序服务器;能够提供以上服务的计算机,我们也称其为网络主机(Host)
基本访问流程

  • 输入主机地址
  • 指定端口(如果没有指定,则默认为80)
  • 指定需要访问的资源路径(要参照服务器的设定)
  • 发起请求
  • 获取服务器返回的结果并处理

如何创建服务器:

  ```
  1. 服务器一定要遵守http协议,所以首先要引入http协议 
  const http = require('http')

  2.根据http协议创建一个服务器  
  const server = http.createServer()

  3.添加指定端口的监听(127.0.0.1:本机圆环地址,如果以本机做为服务器,默认的地址就是127.0.0.1)  
  server.listen(3003, () => {console.log('http://127.0.0.1:3003')})

  4. 监听用户的请求 
  // 当用户向这个服务器发起指定端口的请求时,就会自动的触发request事件
  // 在事件处理函数中,有两个参数:
                    req:就是客户端传递给服务器的请求数据(请求报文)-- request,      
                    res:就是服务器响应给客户端的数据 --response
  // 如果监听到用户的请求,通过设置的资源url用于响应用户特定的请求---路由
  server.on('request', (req, res) => {
        // 服务器响应回客户端的内容永远都是字符串
        // 但是你需要注意的是,字符串是带格式的
          res.end('为什么写个中文我看不懂aabbcc')
  });
  ```

服务器如何响应用户不同的请求

响应客户端请求

// 1.引入http模块
const http = require('http')

// 2.创建服务器
// createServer方法可以创建一个node服务器
const server = http.createServer()

// 3.添加服务器的端口监听
// 第一个参数:监听的端口,以后只有这个端口的请求,当前服务器才会响应
// 第二个参数:回调函数,当服务器启动的时候会调用这个回调函数
server.listen(3000,function(){
    console.log('服务器开好了: http://127.0.0.1:3000')
})

// 4.添加用户请求的监听,只要用户发起了针对当前服务器3000端口的请求,就会调用回调函数进行处理
// 这个回调函数的参数和之前createServer中回调函数的参数一样
server.on('request',function(req,res){
    res.end('hello world')
})

响应客户端页面

// 1.引入http模块
const http = require('http')

// 读取文件需要fs模块
const fs = require('fs')

// 2.创建服务器
const server = http.createServer()

// 3.添加服务器的端口监听
server.listen(3000,function(){
    console.log('服务器开好了: http://127.0.0.1:3000')
})

// 4.添加用户请求的监听,只要用户发起了针对当前服务器3000端口的请求,就会调用回调函数进行处理
// 这个回调函数的参数和之前createServer中回调函数的参数一样
server.on('request',function(req,res){
    // 读取首页并返回,这里就需要使用到fs核心模块了
    // 细节:这里不需要设置编码,因为html页面已经有默认的编码了
    fs.readFile(__dirname+"/views/index.html",function(err,data){
        if(err){
            res.end('404')
        }else{
            res.end(data)
        }
    })
})

监听客户端请求并响应不同页面

// 1.引入http模块
const http = require('http')

// 读取文件需要fs模块
const fs = require('fs')

// 2.创建服务器
const server = http.createServer()

// 3.添加服务器的端口监听
server.listen(3000, function () {
    console.log('服务器开好了: http://127.0.0.1:3000')
})

// 4.添加用户请求的监听,只要用户发起了针对当前服务器3000端口的请求,就会调用回调函数进行处理
// 这个回调函数的参数和之前createServer中回调函数的参数一样
server.on('request', function (req, res) {
    // 想要根据用户请求返回不同的页面,关键是需要知道用户到底发了什么请求
    // req.url:可以获取当前用户请求的url,如果客户端没有指定url,那么它默认为/
    let url = req.url
    // 这里需要注意的是,在node服务器中使用console,会在服务器端中进行打印,而不是在浏览器端打印输出呢
    console.log(url)
    // 我们可以看到,用户的不同请求,url是不一样的,所以我们需要判断当前的url以决定返回什么样的页面
    // 对于url的判断,我们在开发的时候一般是在后台进行约定,前端需要遵守
    // 这里我们约定    /或/index   就是要请求首页,   /login   就是要请求登陆页
    if (url == '/' || url == '/index') {
        fs.readFile(__dirname + "/views/index.html", function (err, data) {
            if (err) {
                res.end('404')
            } else {
                res.end(data)
            }
        })
    }else if(url == '/login'){
        fs.readFile(__dirname + "/views/login.html", function (err, data) {
            if (err) {
                res.end('404')
            } else {
                res.end(data)
            }
        })
    }else{
        res.end('404')
    }
})

响应数据回客户端

// 1.引入http模块
const http = require('http')

// 读取文件需要fs模块
const fs = require('fs')

// 2.创建服务器
const server = http.createServer()

// 3.添加服务器的端口监听
server.listen(3000, function () {
    console.log('服务器开好了: http://127.0.0.1:3000')
})

// 4.添加用户请求的监听,只要用户发起了针对当前服务器3000端口的请求,就会调用回调函数进行处理
// 这个回调函数的参数和之前createServer中回调函数的参数一样
server.on('request', function (req, res) {
    // 想要根据用户请求返回不同的页面,关键是需要知道用户到底发了什么请求
    // req.url:可以获取当前用户请求的url,如果客户端没有指定url,那么它默认为/
    let url = req.url
    // 这里需要注意的是,在node服务器中使用console,会在服务器端中进行打印,而不是在浏览器端打印输出呢
    console.log(url)
    // 我们可以看到,用户的不同请求,url是不一样的,所以我们需要判断当前的url以决定返回什么样的页面
    // 对于url的判断,我们在开发的时候一般是在后台进行约定,前端需要遵守
    if (url == '/getUserList') {
        fs.readFile(__dirname + "/data/users.json",'utf-8', function (err, data) {
            if (err) {
                res.end('404')
            } else {
                res.end(data)
            }
        })
    }else{
        res.end('404')
    }
})

响应客户端不同类型的请求
1.通过req.method可以获取当前客户端的请求方式
2.根据req.method的值的不同,进行相应的处理操作

响应get方式的请求

// 1.引入协议 
var http = require('http')
var fs = require('fs')

// 2.创建服务器
var server = http.createServer()

// 3.添加对端口的监听
server.listen(3000,function(){
    console.log('http://127.0.0.1:3000')
})

// 4.添加用户请求的监听
server.on('request', function (req, res) {
    // 设置允许跨域请求
    res.setHeader('Access-Control-Allow-Origin', '*');
    // req.url:可以获取当前客户端请求的url,如果客户端没有指定url,那么它默认为 /
    let url = req.url
    // req.method:可以获取当前客户端请求方式
    let method = req.method
    console.log(method) // GET  POST
    // 如果是以get方式请求/getUserList,才能匹配从而响应
    if (method == 'GET' && url == '/getUserList') {
        fs.readFile(__dirname + "/data/users.json",'utf-8', function (err, data) {
            if (err) {
                res.end('err')
            } else {
                res.end(data)
            }
        })
    }
    else{
        res.end('404')
    }
})

页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <a href="http://127.0.0.1:3000/getUserList">单击我可以获取到用户列表数据</a>
</body>
</html>

响应post方式的请求

// 1.引入http模块
const http = require('http')

// 解析参数的querystring模块
const querystring = require('querystring')

// 2.创建服务器
const server = http.createServer()

// 3.添加服务器的端口监听
server.listen(3000, function () {
    console.log('服务器开好了: http://127.0.0.1:3000')
})

// 4.添加用户请求的监听
server.on('request', function (req, res) {
    // 设置允许跨域请求
    res.setHeader('Access-Control-Allow-Origin', '*');
    // req.url:可以获取当前客户端请求的url,如果客户端没有指定url,那么它默认为/
    let url = req.url
    // req.method:可以获取当前客户端请求方式
    let method = req.method
    // 如果是以POST方式请求/login,才能匹配从而响应
    if (method == 'POST' && url == '/login') {
        // 接收参数
        var postData = '';
        //给req注册一个data事件,这个事件可以实现post方式请求的参数的接收。post允许客户端发送大容量的参数,如果参数较多,它支持分批进行参数的接收,当客户端每发送一次数据流,都会触发里面的回调函数,我们需要主动将这些数据拼接起来
        req.on('data', function(chuck){
            //具体多少次,取决于客户端带宽
            postData += chuck;
        });

        //2.给req注册一个end事件。当客户端post数据全部发送完毕之后,就会触发这个事件
        req.on('end', () => {
            //3.使用querystring模块解析接收完成的post参数数据
            let postObj = querystring.parse(postData);
            // 登陆验证
            if(postObj.username == 'admin' && postObj.password == '123456'){
                res.end('yes')
            }else{
                res.end('no')
            }
        })
    }
    else {
        res.end('404')
    }
})

html页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form method="post" action='http://127.0.0.1:3000/login'>
        用户名:<input type="text" name='username' placeholder="请输入用户名"><br>
        密码: <input type="password" name='passwrod' placeholder="请输入密码"> <br>
        <input type="submit" value="提交">
    </form>
</body>
</html>
posted @ 2020-11-21 20:18  南城北斋  阅读(142)  评论(0编辑  收藏  举报