通過express快速搭建一個node服務

  • 2020 年 10 月 26 日
  • 筆記

Node.js 是一個基於Chrome JavaScript 運行時建立的一個平台。可以理解為是運行在服務端的 JavaScript。如果你是一個前端程序員,不太擅長像PHP、Python或Ruby等動態編程語言,想創建自己的服務,那麼Node.js是一個非常好的選擇。本文將通過幾個簡要步驟,運用express框架,搭建一個node服務。

一、安裝、搭建環境

1、新建一個文件夾,這裡暫時叫做「node-service」。

2、進入文件夾,cmd執行npm init,可根據自己需要填寫一些信息,不需要定製的話,前面一路回車即可,只需要在最後,即下圖中紅色圈起部分輸入yes或者y。此時在文件夾內會生成一個package.json文件。紅色劃線部分是我示例填寫,不是必需。

3、安裝express

命令:cnpm install express –save

此時文件夾中會生成node-modules文件夾,以上命令會將express框架安裝在node-modules目錄中。以下幾個重要模塊,是可以與express一起安裝的,大家根據自己需要進行安裝即可。

body-parser - node.js 中間件,用於處理 JSON, Raw, Text 和 URL 編碼的數據。
cookie
-parser - 一個解析Cookie的工具。通過req.cookies可以取到傳過來的cookie,並把它們轉成對象。
multer
- node.js 中間件,用於處理 enctype="multipart/form-data"(設置表單的MIME編碼)的表單數據。

二、創建一個簡單實例

在我們創建 Node.js 第一個 “Hello, World!” 應用前,讓我們先了解下 Node.js 應用是由哪幾部分組成的:

引入 required 模塊:我們可以使用 require 指令來載入 Node.js 模塊。

創建服務器:服務器可以監聽客戶端的請求,類似於 Apache 、Nginx 等 HTTP 服務器。

接收請求與響應請求 服務器很容易創建,客戶端可以使用瀏覽器或終端發送 HTTP 請求,服務器接收請求後返迴響應數據。

此時我們求創建一個服務:在客戶端發起請求時,響應”hello world”字符串。

2.1、創建app.js文件,示例代碼如下:

var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

let port = 8082;
app.listen(port, () => {
    console.log(`Server listening on http://localhost::${port}, Ctrl+C to stop`) 
});

2.2、啟動服務:根目錄下執行命令 node app.js

2.3、在瀏覽器中訪問//localhost:8082/ 或//127.0.0.1:8082/,效果如下:

此時有文本輸出,說明服務搭建成功。

三、路由匹配

上文我們是在客戶端發起請求時,直接響應一段指定文本。但有時需要根據不同請求路徑或請求方式,返回不同數據。所以我們新建一個文件app1.js,代碼如下:

var express = require('express');
var app = express();

// 默認請求,輸出 "Hello World"
app.get('/', function (req, res) {
   res.send('Hello GET');
})
// 用戶刪除接口
app.get('/user_del', function (req, res) {
   res.send('用戶刪除接口');
})
// 用戶信息查詢接口 GET 請求
app.get('/user_list_query', function (req, res) {
   res.send('用戶列表數據');
})

let port = 8082;
app.listen(port, () => {
    console.log(`Server listening on http://localhost::${port}, Ctrl+C to stop`) 
});

文件中通過三個不同路徑暴露了三個接口,接下來我們可以訪問不同路徑,看驗證是否返回不同信息。

可以看到,我們已經拿到了不同返回體。但也許有人會問,如果此時我有很多請求,難道都堆在app1.js里嘛,能不能把請求歸類一下,讓app1.js整潔一些,只作為入口呢?當然可以。

假定現有兩類接口,每類各有三個接口
一、用戶管理
1、用戶列表查詢:user/user_list_query
2、用戶信息刪除:user/user_del
3、用戶信息修改:user/user_update
二、部門管理    
1、部門列表查詢:dept/dept_list_query
2、部門刪除:dept/dept_del
3、部門修改:dept/dept_update 

此時我們在app1.js同級建立api文件夾,文件夾下新建文件user.js和dept.js。

// dept.js
let express = require('express');
let router = express.Router();

//  部門修改接口
router.get('/dept_update', function (req, res) {
  res.send('部門修改接口');
});

// 部門刪除接口
router.get('/dept_del', function (req, res) {
  res.send('部門刪除接口');
});

// 部門信息查詢接口
router.get('/dept_list_query', function (req, res) {
  res.send('部門列表數據');
});

module.exports = router;

user.js 與此類似,不再贅述。文件中通過使用express.Router()註冊接口,通過module.exports拋出整個模塊,然後在app1.js中引入並使用該模塊:

//app1.js
var express = require('express');
var app = express();
let dept = require('./api/dept');

//  匹配請求,以dept開頭的映射到dept文件中去
app.use('/dept', dept);

let port = 8082;
app.listen(port, () => {
  console.log(`Server listening on http://localhost::${port}, Ctrl+C to stop`)
});

重新啟動8082服務。瀏覽器直接訪問//localhost:8082/dept/dept_update,可以成功拿到返回體。

上面通過2種方式,實現了匹配接口路徑,給出不同返回體。做的更全一點,就可以模擬接口增刪改查邏輯了。提到邏輯處理,就會和請求參數掛鈎,所以我們向下看。

四、請求和響應處理

function中的req和res,分別是 request 和 response 對象。

request 對象 – 表示 HTTP 請求,包含了請求查詢字符串,參數,內容,HTTP 頭部等屬性。

response 對象 – 表示 HTTP 響應,即在接收到請求時向客戶端發送的 HTTP 響應數據。

這兩個對象的常見屬性簡單列舉如下,可根據自己需要進行調用。

req.app:當callback為外部文件時,用req.app訪問express的實例
req.baseUrl:獲取路由當前安裝的URL路徑
req.body / req.cookies:獲得「請求主體」/ Cookies
req.fresh / req.stale:判斷請求是否還「新鮮」
req.hostname / req.ip:獲取主機名和IP地址
req.originalUrl:獲取原始請求URL
req.params:獲取路由的parameters
req.path:獲取請求路徑
req.protocol:獲取協議類型
req.query:獲取URL的查詢參數串
req.route:獲取當前匹配的路由
req.subdomains:獲取子域名
req.accepts():檢查可接受的請求的文檔類型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一個可接受字符編碼
req.get():獲取指定的HTTP請求頭
req.is():判斷請求頭Content-Type的MIME類型
res.app:同req.app一樣
res.append():追加指定HTTP頭
res.set()在res.append()後將重置之前設置的頭
res.cookie(name,value [,option]):設置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():傳送指定路徑的文件
res.get():返回指定的HTTP頭
res.json():傳送JSON響應
res.jsonp():傳送JSONP響應
res.location():只設置響應的Location HTTP頭,不設置狀態碼或者close response
res.redirect():設置響應的Location HTTP頭,並且設置狀態碼302
res.render(view,[locals],callback):渲染一個view,同時向callback傳遞渲染後的字符串,如果在渲染過程中有錯誤發生next(err)將會被自動調用。callback將會被傳入一個可能發生的錯誤以及渲染後的頁面,這樣就不會自動輸出了。
res.send():傳送HTTP響應
res.sendFile(path [,options] [,fn]):傳送指定路徑的文件 -會自動根據文件extension設定Content-Type
res.set():設置HTTP頭,傳入object可以一次設置多個頭
res.status():設置HTTP狀態碼
res.type():設置Content-Type的MIME類型

五、靜態文件服務器

有時,我們的一些靜態文件,例如圖片、CSS文件、js文件等,想放在一個服務器上,此時node可以作為靜態文件服務器。

express 提供了內置的中間件 express.static 來設置靜態文件路徑。

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

我們在app.js同級,新建一個public目錄,存放靜態文件。向裏面放一個css文件和一張圖片。

5.1、按路徑讀取文件:

新建app2.js文件:

var express = require('express');
var app = express();

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

app.get('/', function(req, res){
  res.send('hello world');
});
let port = 8082;
app.listen(port, () => {
    console.log(`Server listening on http://localhost::${port}, Ctrl+C to stop`) 
});

將之前佔用8082端口的服務停掉,通過node app2.js 啟動服務。可以看到默認輸出”hello world”。此時我們嘗試輸入文件路徑去讀靜態文件。

5.2、接口返回靜態文件

上面示例是需要自己輸入文件路徑拿到文件,有人說輸路徑太麻煩了,能不能通過一個接口返回指定靜態文件呢?res.sendFile來了,新建app3.js :

var express = require('express');
var app = express();
  
app.use('/public', express.static('public'));

app.get('/', function(req, res){
   console.log(__dirname);  // 打印結果:/node-service
   res.sendFile(__dirname+'/public/avatar.jpg');
});

let port = 8082;
app.listen(port, () => {
    console.log(`Server listening on http://localhost::${port}, Ctrl+C to stop`)
});

此時執行node app3.js 啟動服務,不用輸入文件路徑,直接就可以看到圖片。

此時代碼與5.1基本相同,差異是用了res.sendFile。

__dirname 是當前模塊的目錄名。 相當於 __filename 的 path.dirname()

console.log(__dirname);
// 打印: /node-service
console.log(path.dirname(__filename));
// 打印: /node-service,前提是引入了path模塊,沒有引入的話,打印會報錯

Tips:

    1、app.js文件,每次改動都要重新啟動服務才能生效。 

    2、如果兩個js文件用了同一個端口,同時啟動會報端口佔用,可每次只起一個,或者用兩個端口。

    3、啟動命令是node js 文件名,app.js只是示例 

如果有需要,點擊此處鏈接獲取文章實例源碼(點我!點我!),或者關注公眾號可更早獲取文章~