1. 程式人生 > >【重點突破】——使用Express創建一個web服務器

【重點突破】——使用Express創建一個web服務器

otto name 其余 保存 就會 輸入 能夠 分享 循環

一、引言

在自學node.js的過程中有一個非常重要的框架,那就是Express。它是一個基於NodeJs http模塊而編寫的高層模塊,彌補http模塊的繁瑣和不方便,能夠快速開發http服務器。這裏,就要用Express創建一個Web服務器,用來深入的理解這個框架,並熟悉創建Web服務器的過程。

二、核心概念——中間件

Express 是一個自身功能極簡,完全是由路由和中間件構成一個的 web 開發框架:從本質上來說,一個 Express 應用就是在調用各種中間件。

中間件(Middleware) 是一個函數,它可以訪問請求對象(request object (req)), 響應對象(response object (res)), 和 web 應用中處於請求-響應循環流程中的中間件,一般被命名為 next 的變量。

中間件的功能包括:

  • 執行任何代碼。
  • 修改請求和響應對象。

終結請求-響應循環。調用堆棧中的下一個中間件。

如果當前中間件沒有終結請求-響應循環,則必須調用 next() 方法將控制權交給下一個中間件,否則請求就會掛起。

Express 應用可使用如下幾種中間件:

  • 應用級中間件
  • 路由級中間件
  • 錯誤處理中間件
  • 內置中間件
  • 第三方中間件

使用可選則掛載路徑,可在應用級別或路由級別裝載中間件。另外,你還可以同時裝在一系列中間件函數,從而在一個掛載點上創建一個子中間件棧。

技術分享

app.use(url,  (req, res, next)=>{
//.....中間件要執行的代碼
next( ); //調用下一個中間件或路由

三、模塊下載

因為創建Web服務器要用到第三方模塊的mysql和Express,所以需要在創建新項目之後,在NPM中進行下載,安裝這兩個模塊,具體過程如下:

  1. Webstorm創建新項目project,右鍵點擊project
  2. show in Explorer 進入目標文件夾
  3. 按shift 同時點擊右鍵,在空白面板處
  4. 在此處打開命令窗口
  5. >npm i mysql 等待下載
  6. >npm i express 等待下載

下載完成後,webstorm中新創建的project下會自動更新出一個node_modules目錄,裏面會有需要的mysql和Express。

四、引例說明

使用Express創建一個web服務器,可以向客戶端提供一個 /index響應,內容是一個HTML頁面,其中還使用一個index.css文件/index.js文件

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="index.css"/>
</head>
<body>
   <h1>INDEX.HTML</h1>
   <script src="index.js"></script>
</body>
</html>
css文件和js文件此處省略
//app.js執行文件
const http = require(‘http‘); const express = require(‘express‘); var app = express(); http.createServer(app).listen(8080); app.get(‘/index‘,(req,res)=>{ res.sendFile(__dirname+‘/pulic/index.html‘); }); app.get(‘/index‘,(req,res)=>{ res.sendFile(__dirname+‘/pulic/index.css‘); }); app.get(‘/index‘,(req,res)=>{ res.sendFile(__dirname+‘/pulic/index.js‘); });

小坑:如果index.html室友路由引入的,即使裏面的index.css和index.js引入到了html中,若沒有通過路由引入到app.js文件中,則這兩個css與js文件是存在,但不響應的。所以,必須都通過路由引入到app.js文件中。但是,這同樣會有一個問題,那就是如果要引入的文件太多,又必須要一個不漏的引入,那這樣一個一個引太繁瑣了,工作量太大,這就是中間件的重要性了,使用中間件可以方便快鍵的引入所需的所有文件。

Express 4.x官方還提供了一個中間件函數:app.use(express.static(‘public‘));//若客戶端請求了/public目錄下的某個資源,它可以直接向客戶端返回,不會再調用後續的路由。


五、web服務器創建

要求:使用Express創建Web服務器應用,可以接收如下的請求:

1、編寫SQL:創建數據庫dangdang,書籍信息表book(bid,title,price,pubDate-出版日期,into-內容簡介),並插入4行書籍記錄。

2、至少可以向客戶端提供如下靜態資源:

/public/booklist.html 初始時顯示一個空白的表格,頁面加載完成後向服務器異步請求所有的書籍信息。

/public/jquery-1.11.3.js 在DIV中顯示某一本書的詳情

/public/book_detail.html 在DIV中顯示某一本書的詳情

/public/book_add.html 顯示一個添加書籍的表單,點擊“提交”按鈕,異步提交給服務器

/public/book_update.html 顯示一個修改書籍的表單,輸入域中是當前要修改的書籍信息,點擊“提交”按鈕,異步提交給服務器。

3、以及如下動態資源地址——註意:下述地址都使用Ajax異步請求

GET /book 向客戶端輸出書籍表中的所有記錄,以JSON格式

GET /book/:id 向客戶端輸出指定編號的書籍全部信息,以JSON格式

DELETE /book/:id 刪除指定編號的書籍記錄,向客戶端輸出{code:1,bid:xx}或者{code:2,msg:‘指定書籍編號不存在‘}

POST /book 接收客戶端提交的請求主體數據(title/price/pubDate/intro),執行書籍添加操作保存入數據庫,向客戶端輸出{code:1,bid:xx}

PUT /book 接收客戶端提交的請求主體數據(bid/title/price/pubDate/intro),執行書籍更新操作修改數據庫中對應的書籍,向客戶端輸出{code:1,affectRows:1}

實現:

DROP DATABASE IF EXISTS dangdang;
CREATE DATABASE dangdang CHARSET=UTF8;
USE dangdang;

CREATE TABLE book(
  bid INT PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(64),
  price DECIMAL(8,2),
  pubDate BIGINT,
  intro VARCHAR(2048)
);
INSERT INTO book VALUES
(NULL, 西遊記, 35.5, 1350123456789,描述了一個和尚和三個妖怪的故事),
(NULL, 水滸傳, 45.5, 1360123456789,描述了105個男人和3個女人的故事),
(NULL, 紅樓夢, 55.5, 1370123456789,描述了1個富二代的故事),
(NULL, 三國誌, 65.5, 1380123456789,描述了群雄爭霸的故事);
//book_list.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>書籍列表</h1>
    <hr/>
    <table border="1" width="100%">
        <thead>
            <tr>
                <th>編號</th>
                <th>書名</th>
                <th>價格</th>
                <th>出版日期</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
             <td colspan="5">信息加載中....</td>
        </tbody>
    </table>

    <script src="js/jquery-1.11.3.js"></script>
    <script>
        //待當前頁面加載完成,異步請求所有書籍信息 GET /book
        $.ajax({
            type:GET,
            url:/book,
            success:function(list){
               //遍歷list數組,每個obj拼接為一個TR>TD*5,TBODY
               var html =‘‘;
                for(var book of list){
                    html +=`
                    <tr>
                      <td>${book.bid}</td>
                      <td>${book.title}</td>
                      <td>${book.price}</td>
                      <td>${book.pubDate}</td>
                      <td>
                         <a class="detail" href="#">詳情</a>
                         <a class="delete" href="#">刪除</a>
                         <a class="update" href="#">修改</a>
                      </td>
                    </tr>
                    `;
                }
                $(tbody).html(html);
            }
        });
    </script>
</body>
</html>
//book_detail.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            border-bottom: 1px solid #aaa;
            padding: 1em;
        }
    </style>
</head>
<body>
<h1>書籍詳情</h1>
<hr/>
<div id="bid">
    <b>書籍編號:</b>
    <p>xxx</p>
</div>
<div id="title">
    <b>書籍標題:</b>
    <p>xxx</p>
</div>
<div id="price">
    <b>單價:</b>
    <p>xxx</p>
</div>
<div id="pubDate">
    <b>出版日期:</b>
    <p>xxx</p>
</div>
<div id="intro">
    <b>內容簡介:</b>
    <p>xxx</p>
</div>

<script src="js/jquery-1.11.3.js"></script>
<script>
    //待頁面加載完成,異步請求指定編號的書籍詳情
    //console.log(location);
    //console.log(location.search);
    //console.log(location.search.split(‘=‘));
    var bid = location.search.split(=)[1];
    $.ajax({
        type: GET,
        url: /book/+bid,
        success: function(book){
            console.log(成功接收到服務器返回的書籍信息);
            console.log(book);
            $(#bid p).html(book.bid);
            $(#title p).html(book.title);
            $(#price p).html(+book.price);

            var d = new Date(book.pubDate);
            $(#pubDate p).html(d);

            $(#intro p).html(book.intro);
        }
    });
</script>
</body>
</html>

//其余兩個html內容省略
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>更新書籍內容</h1>
    <hr/>

    <script src="js/jquery-1.11.3.js"></script>
</body>
</html>


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>添加書籍</h1>
    <hr/>

    <script src="js/jquery-1.11.3.js"></script>
</body>
</html>
//執行程序app.js
const http = require(‘http‘);
const express = require(‘express‘);
const book = require(‘./book‘);

var app = express();
http.createServer(app).listen(8080);

//使用中間件向客戶端返回靜態內容
app.use(express.static(‘public‘));

//定義路由,向客戶端返回動態內容
app.get(‘/book‘, book.getAll);//自建一個book模塊,調用getAll方法
//自建模塊book.js
const mysql = require(‘mysql‘);
//數據庫連接池
var pool = mysql.createPool({
    user:‘root‘,
    database:‘dangdang‘,
    connectionLimit:5
});

module.exports = {
    getAll:(req, res)=>{
       pool.getConnection((err,conn)=>{
           conn.query(‘SELECT * FROM book‘,(err,result)=>{
               //把查詢結果集轉換為JSON字符串,輸出給客戶端
               res.json(result);
               conn.release();//釋放連接回連接池
           })
       })
    }
};

效果:

技術分享

【重點突破】——使用Express創建一個web服務器