1. 程式人生 > 實用技巧 >UML 各種圖總結精華

UML 各種圖總結精華

1. 初識Express

1.1 Expres簡介

  1. 什麼是 Express

    • 概念:Express 是基於 Node.js 平臺,快速、開放、極簡的 Web 開發框架。
    • 本質:第三方包,提供了快速建立 Web 伺服器的便捷方法。
  2. Express 的作用
    對於前端來說,最常見的兩種伺服器,分別是:

    • Web 網站伺服器:專門對外提供web網專資源的伺服器。
    • API介面伺服器:專門對外提供API介面的伺服器。

    使用 Express,可以方便、快速建立Web網站的伺服器或API介面的伺服器。

1.2 Express的基本使用

  1. 執行 npm i [email protected] 命令安裝 express

  2. 建立基本的Web伺服器

    // 1. 匯入 express  
    const express = require('express');
    // 2. 建立 Web 伺服器例項物件  
    const app = express();
    // 3. 定義埠號  
    const port = 3000;
    
    // 4. 呼叫app.listen(埠號,啟動成功後的回撥函式) 方法,啟動伺服器
    app.listen(port, () => {
        console.log('Express server running at http://127.0.0.1:3000');
    })
    
  3. 監聽GET請求語法格式

    /*
     * @alias app.get(url, callback)
     * @param {string} 客戶端請求的URL地址
     * @param {callback} 響應客戶端請求的處理函式
     */
    app.get('url', (req, res) => {
        // req: 請求物件(包含了與請求相關的屬性與方法)
        // res: 相應物件(包含了與響應相關的屬性與方法)
        // 處理函式體
    })
    
  4. 監聽POST請求語法格式

    /*
     * @alias app.post(url, callback)
     * @param {string} 客戶端請求的URL地址
     * @param {callback} 響應客戶端請求的處理函式
     */
    app.post('url', (req, res) => {
        // req: 請求物件(包含了與請求相關的屬性與方法)
        // res: 相應物件(包含了與響應相關的屬性與方法)
        // 處理函式體
    })
    
  5. 獲取URL中攜帶的查詢引數
    通過 req.query 物件,可以訪問到客戶端通過查詢字串的形式傳送到伺服器的引數:

    app.get('/search', (req, res) => {
       // req.query 預設是一個空物件
       // 當客戶端的請求URL為:/search?q=taobao
       console.log(req.query); // 輸出: { q: 'taobao' }
       console.log(req.query.q); // 輸出: taobao
    })
    
  6. 獲取表單中的資料
    通過 req.body 物件,可以獲取表單提交過來的資料:

    // 如果需要使用 req.body , 需要在使用前使用解析表單的中介軟體(下面會詳細說)
    app.use(express.urlencoded({ extended: true }));
    // 如果使用上述程式碼,req.body 的值為 undefined  
    app.post('/reg', (req, res) => {
       console.log(req.body);
    })
    
  7. 獲取URL中的動態引數
    通過 req.params 物件,可以訪問到URL中通過 : 匹配到的動態引數:

    // :id 表示 id 這個引數是動態引數  
    app.get('/user/:id', (req, res) => {
       // req.params 預設是一個空物件
       // 客戶端請求URL為: /user/34
       console.log(req.params); // 輸出: { id: '34' }
    })
    
  8. 響應客戶端請求
    通過 res.send() 方法,可以把資料和資訊傳送給客戶端。

    app.get('/', (req, res) => {
       // 向客戶端傳送 JSON 物件
       res.send({
          name: 'xao',
          age: 18,
          sex: '男',
       });
    })
    
    app.post('/user', (req, res) => {
       // 向客戶端傳送文字內容
       res.send('POST請求成功');
    })
    

1.3 託管靜態資源

  • 靜態資源目錄樹結構
    |--public
    |--|--index.html
    |--|--login.html
    |--|--register.html
    
  1. express.static()
    通過使用 express.static() 方法,可以快速建立一個靜態資源伺服器。

    app.use(express.static('./public'));
    // 通過上述程式碼,客戶端就可以訪問public目錄下的靜態資源
    // htpp://127.0.0.1:3000/index.html
    // htpp://127.0.0.1:3000/login.html
    // htpp://127.0.0.1:3000/register.html
    
  2. 託管多個靜態資源目錄
    如果要託管多個靜態資源目錄,請多次呼叫express.static() 方法

    app.use(express.static('./public'));
    app.use(express.static('./files'));
    

    客戶端訪問靜態資源時,express.static() 函式會根據目錄的新增順序查詢所需的檔案。

  3. 掛載路徑字首
    如果希望在託管的靜態資源訪問路徑之前,掛載路徑字首,則可以使用如下的方式:

    app.use('/public',express.static('./public'));
    // 新增上述程式碼後,客戶端訪問資源時必須要帶有 /public 字首地址來訪問public目錄中的靜態資源
    // htpp://127.0.0.1:3000/public/index.html
    // htpp://127.0.0.1:3000/public/login.html
    // htpp://127.0.0.1:3000/public/register.html
    

2. Express 路由

2.1 路由的概念

  1. 從廣義上來講,路由就是對映關係。

  2. express 中的路由

    • 在 express 中,路由指的是 客戶端的請求伺服器處理函式 之間的對映關係。
    • express 中的路由分 3 部分組成,分別是 請求的型別請求的 URL 地址處理函式
  3. 具體程式碼

    // 匹配GET請求,且請求 URL 地址為 /index.html  
    app.get('/index.html', (req, res) => {
       res.send('hello world !');
    })
    
    // 匹配POST請求,且請求 URL 地址為 /login.html  
    app.post('/login.html', (req, res) => {
       res.send('登入成功');
    })
    
  4. express路由匹配過程

    • 每當一個請求到達伺服器之後,需要先經過路由的匹配,只有匹配成功之後,才會呼叫對應的處理函式。
    • 在匹配時,會按照路由定義的順序進行匹配,如果請求型別和請求的 URL 同時匹配成功,則 Express 會將這次請求,轉交給對應的 function 函式進行處理。

2.2 路由的使用

  1. 簡單使用方法
    將路由掛載到伺服器例項物件上

    // 匯入 express 
    const express = require('express')
    // 建立 web 伺服器例項物件
    const app = express()
    // 定義埠號
    const port = 3000
    
    // 掛載路由
    app.get('/', (req, res) => {
       res.send('GET request to the homepage')
    })
    app.post('/', function (req, res) {
       res.send('POST request to the homepage')
    })
    
    // 啟動伺服器
    app.listen(port, () => {
       console.log(`Express server running at http://127.0.0.1:3000`)
    })
    
  2. 模組化路由
    為了方便對路由進行模組化的管理,Express 不建議將路由直接掛載到 app 上,而是推薦將路由抽離為單獨的模組。

    1. 將路由抽離為單獨模組的步驟如下:

      1. 建立路由模組對應js檔案
      2. 呼叫 express.Router() 函式建立路由物件
      3. 定義路由的具體對映關係
      4. 使用 module.exports 向外共享路由物件
      5. 使用 app.use() 函式註冊路由模組
    2. 程式碼如下

      • 建立路由模組
        // 匯入 express 
        const express = require('express');
        
        //建立路由物件 
        const router = express.Router();
        
        // 定義路由的對映關係
        router.get('/', (req, res) => {
          res.send('GET request to the homepage')
        })
        router.post('/', function (req, res) {
          res.send('POST request to the homepage')
        })
        
        // 向外共享路由物件
        module.exports = router;
        
      • 註冊路由模組
        // 匯入路由模組
        const router = require('./router.js');
        // 使用 app.use() 註冊路由模組  
        app.use(router);
        
      • 為路由模組新增路徑字首
        // 使用 app.use() 註冊路由模組,並統一新增訪問路徑字首  
        app.use('/index', router);
        

3. Express 中介軟體

3.1 中介軟體的概念

  1. 中介軟體(Middleware ),特指業務流程的 中間處理環節

  2. express 中介軟體的呼叫流程

    1. 當一個請求到達伺服器之後,可以連續呼叫多箇中間件,從而對這次請求進行預處理。
    2. 多箇中間件之間共享 req 和 res 物件。
    3. 當處理完畢後,響應客戶端的請求。

3.2 中介軟體的型別

  1. 應用層中介軟體
    通過 app.use() 和 app.METHOD() 函式,繫結到 express() 例項物件上的中介軟體,叫做應用層中介軟體。

    const app = express();
    // 每次收到請求,都會執行該中介軟體(全域性中介軟體)
    app.use((req, res, next) => {
       console.log('hello express !');
       next();
       // next() 方法必須被呼叫,以便進入下一個中介軟體。否則,請求將被掛起。
       // 呼叫 next() 方法之後,不要再書寫任何程式碼。(一般最後呼叫 next() 方法)
    })
    // 該中介軟體只會在客戶端請求 /api 路徑時,被執行
    app.use('/api', (req, res, next) => {
       console.log('api');
       next();
    })
    // 該中介軟體只會在客戶端發起 GET 請求,且請求 /public 路徑時被執行
    app.get('/public', (req, res, next) => {
       console.log('public');
       next();
    })
    
  2. 路由級中介軟體
    路由器級中介軟體與應用層中介軟體的工作方式相同,只不過它繫結到的例項 express.Router() 上。

    const userRouter = express.Router();
    // 該中介軟體只會在客戶端請求 userRouter 模組時被執行
    userRouter.use((req, res, next) => {
       console.log('success');
       next();
    })
    // 該中介軟體只會在客戶端請求 userRouter 模組,且請求路徑為 /userinfo 時被執行
    userRouter.use('/userinfo', (req, res, next) => {
       console.log('userinfo');
       next();
    })
    // 該中介軟體只會在客戶端請求 userRouter 模組,發起 POST 請求,且路徑為 /userinfo/update 時被執行
    userRouter.post('/userinfo/update', (req, res, next) => {
       console.log('update userinfo');
       next();
    })
    
  3. 錯誤處理中介軟體

    • 錯誤中介軟體必須帶有4個引數,(err, req, res, next)
    • 錯誤中介軟體無需呼叫 next() 方法,但引數必須傳;否則,會被當做其他型別的中介軟體執行。
    • 錯誤中介軟體必須在所有路由之後呼叫
    app.use((err, req, res, next) => {
       if(req.url == '/api/info') {
          return res.status(404).send('404 頁面不存在!');
       }
       res.status(500).send('伺服器內部錯誤');
    })
    
  4. 內建中介軟體

    • express.static 快速託管靜態資源的內建中介軟體,例如: HTML 檔案、圖片、CSS 樣式等(無相容性)。
    • express.json 解析 JSON 格式的請求體資料(有相容性,4.16.0+ 中可用)。
    • express.urlencoded 解析 URL-encoded 格式的請求體資料(有相容性,4.16.0+ 中可用)。
  5. 第三方中介軟體(與包類似)

    • 非express官方內建的中介軟體,而是有第三方開發出來的express中介軟體,叫做第三方中介軟體。
    • 使用第三方中介軟體時,需要使用 npm i 名稱 下載第三方中介軟體,使用 require() 匯入,並呼叫 app.use() 掛載第三方中介軟體。

3.3 自定義中介軟體

// 新建一個js檔案
// 自定義模組可以使用 node.js 內建模組 或 第三方模組  

// 定義中介軟體
const myMiddle = (req, res, next) => {
   // 要執行的程式碼...
   next();
}

// 向外共享myMiddle
module.exports = myMiddle;

4. 使用過 express 搭建API介面伺服器

4.1 使用過 express 搭建API介面

  1. 搭建基本伺服器

    // 匯入 express
    const express = require('express');
    // 建立伺服器例項物件
    const app = express();
    // 定義埠號
    const port = 3000;
    
    // 匯入路由模組
    const apiRouter = require('./apiRouter');
    
    // 將路由模組註冊到伺服器上
    app.use('/api', apiRouter);
    
    app.listen(port, () => console.log(`Example server running at http://127.0.0.1:3000`));
    
  2. apiRouter 模組

    // 匯入 express
    const express = require('express');
    // 建立一個新的路由物件
    const router = express.Router();
    
    // 實現路由的對映
    router.get('/get', (req, res) => {
       const query = req.query;
       res.send({
          status: 200, // 響應狀態碼:200
          msg: 'GET請求成功', // 響應狀態描述
          data: query, // 響應給客戶端的資料
       });
    });
    
    router.post('/post', (req, res) => {
       const query = req.query;
       res.send({
          status: 200, // 響應狀態碼:200
          msg: 'POST請求成功', // 響應狀態描述
          data: query, // 響應給客戶端的資料
       })
    })
    // 向外共享路由模組
    module.exports = router;
    

4.2 跨域資源共享

  1. CORS(Cross-Origin Resource Sharing)跨域資源共享

    1. 同源:客戶端請求的URL地址與伺服器的ULR地址的協議域名埠號都相同即為同源,三者有一者不同為跨域。
    2. 由於瀏覽器同源策略的存在,預設阻止跨域獲取資源;但伺服器可以通過設定響應頭,允許跨域請求訪問資源。
    3. 但CORS 在瀏覽器中有相容性,只支援 XMLHttpRequest Level2 的瀏覽器,才能正常開啟 CORS (例如:IE10+、Chrome4+、FireFox3.5+)。
  2. CORS 跨域資源實現方式
    通過指定響應頭 Access-Control-Allow-Origin 欄位對應的值來指定允許訪問資源的外域 URL。

    // 只允許來自 http://127.0.0.1:5500 的跨域訪問資源請求
    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');
    // 值為 '*' : 表示允許來自任何域的請求
    res.setHeader('Access-Control-Allow-Origin', '*');
    
  3. CORS 預設支援9個請求頭

    Accept
    Accept-Language
    Content-Language
    DPR
    Downlink
    Save-Data
    Viewport-Width
    Width 
    Content-Type (值僅限於 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
    

    如果需要支援其他的型別的請求頭,可以通過 Access-Control-Allow-Headers 欄位對額外的請求進行宣告。

    // 允許客戶端額外向伺服器傳送 X-Custom-Header 請求頭
    res.setHeader('Access-Control-Allow-Headers', 'X-Custom-Header');
    // 可以同時設定多個請求頭,多個請求頭之間用英文逗號分隔
    res.setHeader('Access-Control-Allow-Headers','Content-Type,X-Custom-Header');
    
  4. CORS 預設情況下僅支援客戶端發起的簡單請求(GET、POST、HEAD)。
    如果伺服器想要允許客戶端通過非簡單請求(預檢請求)來請求服務端的資源,可以通過 Access-Control-Alow-Methods 欄位來設定客戶端可以使用的請求方式。

    // 允許客戶端使用 GET, POST, HEAD, DELETE 方式請求資源
    res.setHeader('Access-Control-Alow-Methods', 'GET, POST, HEAD, DELETE');
    // 允許客戶端使用所有的HTTP請求方式
    res.setHeader('Access-Control-Alow-Methods', '*');
    
  5. 簡單請求

    • 請求方式為 GET、POST、HEAD 三者之一。
    • 客戶端請求頭部無自定義頭部欄位。
    • 客戶端只會向服務端傳送一次請求。
  6. 預檢請求

    • 請求方式為 GET、POST、HEAD 之外的請求型別。
    • 請求頭部包含自定義頭部欄位。
    • 向伺服器傳送 application/json 格式的資料。
    • 客戶端會向伺服器傳送兩次請求。
      1. 在瀏覽器與伺服器正式通訊之前,瀏覽器會先發送 OPTION 請求進行預檢,以獲知伺服器是否允許該實際請求。
      2. 伺服器成功響應OPTION請求(預檢請求)後,才會傳送真正的請求,並且攜帶真實資料。

4.3 跨域解決方案

  1. CORS(主流方案,只需要在後端配置,推薦使用)
  2. JSONP(相容性好,需要前後端配合,但只支援GET請求)

4.4 使用 cors 中介軟體解決跨域問題

cors 是 express 的一個第三方中介軟體,通過安裝和配置中介軟體,可以方便解決跨域問題。

  • 安裝: npm i cors
  • 匯入: const cors = require('cors')
  • 全域性配置: app.use(cors())

4.5 使用 jsonp 解決跨域問題

  • 伺服器端程式碼
    app.get('/api/jsonp', (req, res) => {
       // 1. 得到函式的名稱
       const funName = req.query.callback
       // 2. 定義要傳送到客戶端的資料物件
       const data = { name: 'zs', age: 22 }
       // 3. 拼接出一個函式的呼叫
       const scriptStr = `${funName}(${JSON.stringify(data)})`
       // 4. 把拼接的字串,響應給客戶端
       res.send(scriptStr)
    })
    
  • 客戶端程式碼
    $.ajax({
       type: 'GET',
       url: 'http://127.0.0.1/api/jsonp',
       dataType: 'jsonp',
       success: function (res) {
          console.log(res);
       }
    })
    

PS: 如果本文對你有所幫助,請點個贊吧!