1. 程式人生 > >通過express快速搭建一個node服務

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

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、在瀏覽器中訪問http://localhost:8082/ 或http://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服務。瀏覽器直接訪問http://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只是示例 

如果有需要,點選此處連結獲取文章例項原始碼(點我!點我!),或者關注公眾號可更早獲取文章~