天天看點

node.js總結(express篇)

文章目錄

    • 前言
    • 1 Express
      • 1.1 什麼是express
      • 1.2 為什麼需要express
      • 1.3 手動安裝手動配置
    • 2 Express基本使用
      • 2.1 主要代碼及注釋
    • 3 處理網頁
      • 3.1 處理靜态資源
      • 3.2 什麼是ejs(模闆引擎)
        • 3.2.1 ejs的特點
        • 3.2.2 ejs的成員函數
        • 3.3.3 ejs的常用标簽
      • 3.3 處理動态資源
      • 在模闆中使用資料
    • 4 處理路由
      • 4.1 應用級别中路由
      • 4.2 處理路由第二種方式
    • 5 會話技術
      • 5.1 什麼是會話?
      • 5.2 會話技術
      • 5.3 cookie作用
      • 5.4 cookie記錄上一次通路的時間
      • 5.5 session的使用
    • 6 Express中間件
      • 6.1 next介紹
      • 6.2 next使用
      • 6.3 next正确使用方式
      • 6.4 express中間件
    • 7 Express腳手架
      • 7.1 通過express搭建項目
      • 7.2 生成的app.js

前言

這部分主要是node使用express架構之後的簡寫版本。

1 Express

express:表達;快速(這裡取快速的翻譯)

1.1 什麼是express

Express是一個基于NodeJS的Web Server開發架構, 能夠幫助我們快速的搭建Web伺服器。

1.2 為什麼需要express

  1. 利用原生的NodeJS開發Web伺服器,

    我們需要處理很多繁瑣且沒有技術含量的内容。

    例如: 擷取路由->解析路由->配置設定路由->處理路由等。

    但是有了Express之後, 就能幫助我們省去大量繁瑣的環節, 讓我們隻用關注核心業務邏輯。

  2. 利用原生的NodeJS開發Web伺服器,

    我們需要自己手動去實作靜态/動态資源處理, get/post參數的解析, cookie的解析, 日志處理等。

    但是有了Express之後, 已經有現成的插件幫我們實作了上述功能。

  3. 是以作為單身的程式猿(媛), 如果你還想留一些時間去約會, 那麼Express是你的最佳選擇。

1.3 手動安裝手動配置

  傳送門

  安裝:

npm i express -S

2 Express基本使用

2.1 主要代碼及注釋

// 導入express
const express = require("express");
// express執行(調用express方法),建立服務端執行個體對象
const app  = express();
// req,res 并不是原生node中的req,res
// 它是在原生node的基本上進行增強
// 雖然此處req,res進行了增強,但是也可以使用原生node中的api
app.get("/",(req,res)=>{//路由  預設是/  一個位址,對應了一個響應
    // res.writeHead(200,{'Content-type':'text/plain;charset=utf-8'})//解決字元亂碼問題
    // res.end("www.badu.com")//響應資料
    //之前的原生方法也能使用
    res.send("hello express")

})

app.get("/login",(req,res)=>{ // 一個位址,對應了一個響應
    res.send("<h1>登入頁面</h1>")
})
//監聽端口
app.listen(3000,()=>{//告訴服務端需要監聽哪一個端口
    console.log("server is running on 3000");
})
           

res.send([body|status], [body])

既可以直接發送内容,也可以第一個參數狀态,第二個參數内容。

如果直接發送内容的話,狀态會被自動補全;

詳細介紹:傳送門

我們向伺服器發一個請求,核心有兩種請求方式:

1)get請求 偏向于向伺服器要資料 當然也可以把資料給伺服器

A)浏覽器的位址欄就可以發起get請求

B)a标簽的href也可以發起get請求

C)link标簽的href也可以發起get請求

D)script 标簽的 src也可以發起get請求

E)img标簽的src也可以發起get請求

F)form表示也可以發起Get表示

特點:

1)會資料放到位址欄中 不太安全

2)post請求 偏向于把資料扔給伺服器

利用form表示發起get請求:

1)action表示此請求位址

2)method請求的方式

3)表單中的input必須要有一個name屬性

<form action="http://localhost:3333/doreg" method="get">
    <ul>
        <li>使用者名:<input type="text" name="username"></li>
        <li>密碼:<input type="password" name="pwd"></li>
        <li><input type="submit" value="注冊"></li>
    </ul>
</form>
           

3 處理網頁

3.1 處理靜态資源

const express = require("express");
const path = require("path")
const app  = express();
//可以配置多個靜态資源目錄
app.use(express.static('public'))
// app.use(express.static('files'))
// app.use('/static', express.static('files'))
========================express托管靜态資源
// use 表示使用中間件 express内部自帶一個中間件 express.static()
// express.static 此中間件就可以托管靜态資源 是一個内置的中間件
// console.log(path.join(__dirname,"public"));
app.use(express.static(path.join(__dirname, 'public')));
           

項目位置:

node.js總結(express篇)

3.2 什麼是ejs(模闆引擎)

  

ejs

:一個模闆引擎,預設情況下,你的模闆中寫的資料都是假資料,一般資料都是來自于資料庫的。如果把資料庫中的資料取出來,放到需要

替換資料

的地方,此時就是一個真資料,這個流程叫

服務端渲染

3.2.1 ejs的特點

- 快速編譯和渲染
    - 簡單的模闆标簽
    - 自定義标記分隔符
    - 支援文本包含
    - 支援浏覽器端和伺服器端
    - 模闆靜态緩存
    - 支援express視圖系統
           

3.2.2 ejs的成員函數

Render(str,data,[option]):直接渲染字元串并生成html
     str:需要解析的字元串模闆
     data:資料
     option:配置選項
           

3.3.3 ejs的常用标簽

<% %>流程控制标簽
     <%= %>輸出标簽(原文輸出HTML标簽)
     <%- %>輸出标簽(HTML會被浏覽器解析)
     <%# %>注釋标簽
     % 對标記進行轉義
           

3.3 處理動态資源

  模闆:就是前端程式員寫好的html頁面,html頁面中的資料預設都是假資料,我們需要把它裡面的假資料替換成真實的資料,此時就需要使用模闆。一般情況下,是把模闆放在views下面的,如下:

node.js總結(express篇)

原本是

.html

需要換為

.ejs

,也可以用别的方法代替。

在模闆中使用資料

var ejs = require("ejs");// 導入ejs子產品
==================================路徑寫法一
app.use(express.static(path.join(__dirname,"public")))
// 1)告訴express,你的模闆在什麼地方
app.set("views",path.join(__dirname,"views"));//絕對路徑的寫法
==================================路徑寫法二
// 把./views目錄設定為模闆檔案根,html檔案模闆放在view目錄中
app.set("views", "./views");//告訴express,模闆放在views下面
==============================================================================
// 設定模闆引擎為ejs
// 2)告訴express,你使用的模闆引擎是什麼 ejs 除了ejs模闆引擎之外,還有其它的模闆引擎
app.set('view engine', 'ejs')
app.get("/xxx",(req,res)=>{
// res.send("hello express")
// 把資料渲染到模闆中 通過res.render就可以渲染模闆,同時就可以給模闆上綁定資料
res.render('xxx',{msg:"dadaima"});
})
           
<h1>我是一個模闆</h1>
<h2><%= msg %></h2>
           

4 處理路由

4.1 應用級别中路由

const express = require("express");
// app叫應用
const app = express();
app.get("/reg", (req, res) => {
    res.send("<h1>注冊頁面</h1>")
})
app.get("/login", (req, res) => {
    res.send("<h1>登入頁面</h1>")
})
app.get("/cart", (req, res) => {
    res.send("<h1>購物車頁面</h1>")
})
app.post('/api/user/register', (req, res, next) => {
    res.json({
        name: 'xq',
        age: 18,
        method: 'post'
    });
});

app.listen(3000, () => {
    console.log("server is running on 3000");
})
           

注意:

1.響應對象的json方法是express給響應對象擴充的
    2.這個方法會自動将對象轉換成字元串之後傳回
    3.這個方法還會自動幫助我們設定響應頭
           

4.2 處理路由第二種方式

在項目的根目錄下,建立一個routes檔案夾:

node.js總結(express篇)

  不同的子產品,有不同的路由檔案,這裡的

routes

和controller的意思是一樣的。

user.js

goods.js

裡面的路由,叫

二級路由

user.js代碼如下:

const express = require("express");
// router叫路由對象
const router = express.Router();
// 說白了,就是我們前面講的controller
// 二級路由
router.get("/login", (req, res, next) => {
    res.send("<h1>登入頁面</h1>")
})
router.get("/reg", (req, res, next) => {
    res.send("<h1>注冊頁面</h1>")
})
// 導出路由對象
module.exports = router;
           

goodes.js類似user.js

在入口檔案引入獨立的子產品

// app.js
const express = require("express");
// 引入二級路由檔案
const userRouter = require("./routes/user")
const goodsRouter = require("./routes/goods")
const app = express();
// 一級路由 當通路/api/user時,就把這個路由交給userRouter來處理
app.use("/api/user", userRouter)
app.use("/api/goods", goodsRouter)
app.listen(3000, () => {
    console.log("server is running on 3000");
})

           

5 會話技術

Cookie:浏覽器端的會話技術。

Session:伺服器端的會話技術。

5.1 什麼是會話?

  日常生活中:從撥通電話到挂斷電話之間的一連串你問我答的過程就是一個會話。

  B/S架構中:從浏覽器第一次給伺服器發送請求時,建立會話;直到有一方斷開,會話結束。

一次會話:包含多次請求響應。

5.2 會話技術

  問題:Http是一個無狀态協定,同一個會話的連續兩個請求互相獨立,彼此并不了解。

  會話技術能彌補http協定無狀态帶來的麻煩。

作用:用于存儲浏覽器與伺服器在請求和響應過程中産生的資料

  在一次會話中(多次請求響應), 共享資料

用戶端會話技術:

cookie

伺服器端會話技術:

session

node.js總結(express篇)

5.3 cookie作用

Cookie作用:在一次會話的多次請求之間共享資料,将資料儲存到

用戶端(浏覽器)

伺服器可以給用戶端種植一個cookie:
    cookie: 小甜點 餅幹 cookie本質就是存儲資料的
    伺服器給用戶端種植了一個cookie,那麼這個cookie就存儲在用戶端。
    一旦種植了,後面每一次請求,都會帶上這個cookie。
    
伺服器給用戶端種植了一個cookie,cookie儲存在什麼地方?
答:在開發者工具中,找到application,在左側找到cookie選項,伺服器種植的cookie就存在在這個地方。
           

ookie的特點:

  1. cookie儲存在用戶端(浏覽器), 往往是由伺服器産生發送給浏覽器
  2. cookie隻能儲存字元串, 格式是entry(name : value)
  3. cookie的大小有限制: 4k
  4. 一般, 同一域名下的cookie限制數量50個

使用:(需要子產品:

npm i cookie-parser

const express = require("express")
const path = require("path")
const cookieParser = require('cookie-parser')
let app = express();
app.use(express.static(path.join(__dirname,'public')))
// 配置cookie
app.use(cookieParser())
app.get("/",(req,res)=>{
    // 需要在服務端種植一個cookie,種到了浏覽器的時面
    // 後面,每一次請求,浏覽器都會帶上這個cookie

    // 給用戶端種植一個cookie
    // res.cookie("usrename","wangcai");  // 預設情況下,會話結束,cookie就死了

    // 活7天  設定cookie的生存時間
    // res.cookie("username","wc",{maxAge:60000*60*24*7})

    // 擷取浏覽器帶過來的cookie
    console.log("擷取cookie:",req.cookies);
    res.send("hello 用戶端~")
})

app.listen(3000,()=>{
    console.log("server is running 3000~");
})
           
node.js總結(express篇)

總結:

預設cookie的生存時間:
     種植:res.cookie("username","wangcai");
     當浏覽器關閉後,cookie就沒了,這個過程,叫一次會話。預設情況下,會話結束了,cookie就沒有了。
     
第一次,會種植一個cookie,後面再次去請求伺服器時,它會把cookie攜帶上。
使用cookie的缺點:
     1)除了第1次請求伺服器,後面每一次請求伺服器,都要帶上cookie,浪費帶寬,請求速度會慢一點。
     2)因為cookie是存在浏覽器端的,我們可以銷毀掉,可以篡改它
     3)有的使用者,會在浏覽器端,禁用cookie
     ....
設定cookie的生存周期:
res.cookie("username","wc",{maxAge:60000*60*24*7,httpOnly:true})
除了第1次請求,後面每一次請求,都會帶上cookie,在伺服器端,就可以
           

擷取cookie,需要子產品:

npm i cookie-parser

使用:

let cookieParser = require("cookie-parser")
app.use(cookieParser())
req.cookies // 得到用戶端請求時,傳遞過一過來cookie
           

5.4 cookie記錄上一次通路的時間

app.get("/", (req, res) => {
    // 擷取cookie 第1次擷取不到,值是und
    let last = req.cookies.last;
    // 第1次通路伺服器 需要種植一個cookie
    //在浏覽器種植時間一年。
    res.cookie("last", new Date().toLocaleString(), { maxAge: 60000 * 60 * 24 * 356 });
    if (last) {
        res.send(`你上一次通路的時間是:${last}`)
    } else {
        // 第1次通路
        res.send(`這是你第1次通路本網站`)
    }
})
           

5.5 session的使用

session的作用:在一次會話的多次請求之間共享資料,将資料儲存到伺服器端。

Session基于Cookie技術實作

session是伺服器端的會話技術

從浏覽器第一次向伺服器發起請求建立會話, 直到其中一方斷開為止會話結束。

session的特點:

  1. session存儲資料在伺服器
  2. session存儲任意類型的資料(Object)
  3. session存儲大小和數量沒有限制(在伺服器記憶體)
  4. session存儲相對安全
node.js總結(express篇)
const session = require('express-session')
// 配置session
app.use(session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
    // session是基于cookie的
    cookie: { maxAge:60000*10 }//id存在10分鐘
}))
app.get("/",(req,res)=>{

    // session也是存數資料的,你可以把session了解成一片存儲資料的區域
    // 你不需要種植cookie,内部會自動幫你種植
    req.session.last = "2021-09-08"; // 當請求/時,給session區域儲存一個資料

    // 後面的請求,班長會帶着編号來請求,會根據編号找到他對應的session
    console.log("擷取班長的session中對應的資料:",req.session.last);

    res.send("hello session")

})
           

cookie和session的選擇

  1. cookie将資料儲存在浏覽器端,資料相對不安全.

    建議敏感的或大量的資料不要放在cookie中,而且資料大小是有限制的

    成本低,對伺服器要求不高

  2. session将資料儲存在伺服器端記憶體,資料相對安全.

    資料的大小要比cookie中資料靈活很多

    成本較高,對伺服器壓力較大

6 Express中間件

  路由是一個特殊的中間件,如果你要定義一個正經的中間件,必須要加next。next表示放行。

6.1 next介紹

express-next方法:
     1.use既可以處理沒有路由位址的請求, 也可以處理有路由位址請求
     2.use既可以處理get請求, 也可以處理post請求
     3.在處理請求的時候是從上至下的判斷的, 哪一個先滿足就哪一個來處理
     4.如果在處理請求的回調函數中沒有調用next方法, 那麼處理完之後就不會繼續往下判斷了
     5.如果在處理請求的回調函數中調用了next方法,那麼處理完之後還會繼續往下判斷
           

6.2 next使用

// 中間件的書寫順序需要特别注意
// 如果沒有寫路徑,表示所有的請求都要經過此中間件
app.use((req,res,next)=>{
    console.log("所有請求都要經過~");
    // 放行
    next()
})

// 不分是post還是get
// 普通的中間件
app.use("/abc",(req,res,next)=>{
    console.log("我是一個中間件 111 ");
    // 放行
    next()
})

app.use("/abc",(req,res,next)=>{//一樣的名字會繼續執行  直到沒有next或者路徑不一樣
    console.log("我是一個中間件 222");
    // 放行  才能走到下面的路由 注釋掉不行
    next()
})

/// 路由
app.get('/abc',(req, res, next)=>{
    console.log('get1 /api');
    next();
});
           

6.3 next正确使用方式

1)通過next方法, 我們可以将同一個請求的多個業務邏輯拆分到不同的方法中處理。

2)這樣可以提升代碼的可讀性和可維護性, 以及保證代碼的單一性。

6.4 express中間件

1.什麼是中間件?
- 中間件的本質就是一個函數, 這個函數接收3個參數request請求對象、response響應對象、next函數
- 當請求進來,會從第一個中間件開始進行比對。如果比對則進入,如果不比對,則向後依次對比比對
2.中間件的作用?
- 将一個請求的處理過程,分發到多個環節中,目的效率高,便于維護。即每個環節專門幹一件事
3.中間件的分類
     3.1 應用級别中間件
     綁定到app執行個體上的中間件
     例如: app.get / app.post
     3.2 路由級别中間件
     綁定到router執行個體上的中間件
     例如: router.get / router.post
     3.3 錯誤進行中間件
     與其他中間件函數的定義基本相同,
     不同之處在于錯誤處理函數多了一個變量:err,即它有4個變量:err, req, res, next
     3.4 内置中間件
     express.static()、express.json()、express.urlencoded()、...
     3.5 第三方中間件
     cookie-parser、...
           

7 Express腳手架

7.1 通過express搭建項目

安裝腳手架:
    npm install express-generator -g
    
通過腳手架去建立項目:
    express myapp
進入myapp中:
    cd myapp
    
跑環境:
    npm i
運作項目:
    npm start (是npm run start的簡寫)
    
預設建立出來的項目,它使用的模闆引擎是jade模闆引擎,不需要我們不學習。
後面建立項目時,生的項目使用的模闆引擎是ejs的,建立項目是指定模闆引擎,如下:
指令:express -e myapp2
           

7.2 生成的app.js

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');

// http-errors 用來處理錯誤的
var createError = require('http-errors');
// 列印日志
var logger = require('morgan');

// 引入二級路由子產品(路由檔案)
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

// 建立app應用
var app = express();

// 告訴epxress,模闆放在了什麼地方
app.set('views', path.join(__dirname, 'views'));
// 告訴express,使用的模闆引擎是jade
app.set('view engine', 'jade');

// 使用中間件
app.use(logger('dev')); // 日志中間件
// 解析前端傳的json資料
app.use(express.json());
// 解析前端傳的表單資料
app.use(express.urlencoded({ extended: false }));
// 解析cookie
app.use(cookieParser());
// 托管靜态資源
app.use(express.static(path.join(__dirname, 'public')));

// 配置一級路由
app.use('/', indexRouter);
app.use('/users', usersRouter);


// 配置中間件
app.use(function(req, res, next) {
  // 放行
  next(createError(404));
});

// 配置中間件   err
// 叫錯誤進行中間件
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

           

繼續閱讀