服務器基礎概念

學習NodeJS的意義html

  • 瞭解客戶端瀏覽器與服務端後臺的交互過程,能夠在之後的前端開發工做中與後臺人員之間的溝通更加容易理解
  • 雖然之後工做中不必定用的上nodejs,可是經過對服務端開發的瞭解,可以讓你在平常工做中與公司後臺人員之間的溝通變得更加輕鬆
  • 瞭解服務端開發的一些特性,能夠在之後的工做中,當咱們前端與後臺交互出現bug問題時,可以更快速的定位bug是出如今本身的客戶端仍是別人的服務端。
  • 做爲一名前端人員,若是對後臺不瞭解,那麼之後在與後臺交互的開發中有可能明明是後臺的問題,可是因爲自身對後臺的不瞭解再加上前期的經驗不足,致使解決問題的時間增長。
  • 瞭解服務端開發的過程,能夠爲之後的職業發展打下必定的基礎(全棧工程師)

什麼是Nodejs前端

  • Node 是一個構建於 Chrome V8引擎之上的一個Javascript 運行環境
  • Node是一個運行環境,做用是讓js擁有開發服務端的功能
  • Node使用事件驅動、非阻塞IO模型(異步讀寫)使得它很是的輕量級和高效
  • Node中絕大多數API都是異步(相似於ajax),目的是提升性能
  • Node中的NPM是世界上最大的開源庫生態系統(相似於github)

服務端js與客戶端js區別node

  • 客戶端JavaScript由三部分組成
    • ECMAScript:肯定js的語法規範
    • DOM:js操做網頁內容
    • BOM:js操做瀏覽器窗口
  • node中的JavaScript
    • 組成
    • ECMAScript
    • 核心模塊
    • 第三方模塊
  • 基本的語法和寫法和以前的js沒有本質的區別
  • 在nodejs中使用dom與bom的api程序會報錯
  • 服務器端沒有界面
  • 壓根不須要操做瀏覽器和頁面元素

在學習建立服務器前須要瞭解基本的核心模塊:git

nodejs核心模塊程序員

  • readFile讀取文件
    1.導入文件模塊
    const fs = require('fs');

2.異步讀取文件github

  • 第一個參數:文件路徑ajax

  • 第二個參數:編碼格式 (可選參數,默認爲buffer二進制)數據庫

  • 第三個參數:讀取回調操做(異步操做)json

  • err:若是讀取成功,err爲null, 不然讀取失敗(通常文件路徑錯誤或者找不到文件)api

  • 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>
相關文章
相關標籤/搜索