express 入門

基礎(chǔ)的 express 實(shí)現(xiàn)靜態(tài)文件訪問

index.js 開啟 http 服務(wù)

const express = require('express'); // 引入 express 模塊
const globalConfig = require('./config');  // 導(dǎo)入全局配置
const app = new express();  // 實(shí)例化一個(gè) express

app.use(express.static(globalConfig['page_path'])); // 告訴 express 示例, 靜態(tài)文件的位置

app.listen(globalConfig['port']); // 監(jiān)聽配置文件中的端口

server.conf是服務(wù)的配置文件

port=8081
page_path=page

config.js 用來處理 server.conf 物赶,將配置文件轉(zhuǎn)換為配置對象

/*
將配置文件格式化成對象鍵值對的形式
 */

const fs = require('fs');  // 引入 fs 模塊

let globalConfig = {}; // 定義全局配置對象

let conf = fs.readFileSync('./server.conf'); // 同步讀取 server.conf 文件

let confArr = conf.toString().split("\n"); // 通過回車符拆分

for (let i = 0, len = confArr.length; i < len; i++) {
  globalConfig[confArr[i].split('=')[0]] = confArr[i].split('=')[1]
}

module.exports = globalConfig; // 將配置對象導(dǎo)出

page 文件夾中存放頁面文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <h1>Hello, world!</h1>
</body>
</html>

然后運(yùn)行 index.js白指,瀏覽器訪問127.0.0.1:8081

基于 express 搭建 web 服務(wù)

這個(gè)不同于上面簡單的web服務(wù),這是一個(gè)完整的簡易 web 服務(wù)酵紫。
首先目錄是這樣的:


server.conf

盡管它不在一個(gè)文件夾中告嘲, 也是很重要的一環(huán)
這個(gè)文件定義了整個(gè)服務(wù)的基本信息。

port=8081
page_path=page
web_path=web

盡管只有簡單的三行奖地, 但是業(yè)務(wù)邏輯復(fù)雜之后橄唬, 這個(gè)文件也會逐漸豐滿的。如果不定義此文件参歹,在需要這些字段的時(shí)候仰楚,就會變得很麻煩。例如改端口號犬庇, 可能很多地方都需要改僧界, 但是有這個(gè)文件, 只需要修改文件中的端口就好了臭挽。

config.js

有了配置文件捂襟, 肯定需要一段代碼去解析配置文件。

/*
將配置文件格式化成對象鍵值對的形式
 */
const fs = require('fs');  // 引入 fs 模塊
let globalConfig = {}; // 定義全局配置對象
let conf = fs.readFileSync('./server.conf'); // 同步讀取 server.conf 文件
let confArr = conf.toString().split("\n"); // 通過回車符拆分
for (let i = 0, len = confArr.length; i < len; i++) {
  globalConfig[confArr[i].split('=')[0]] = confArr[i].split('=')[1]
}
module.exports = globalConfig; // 將配置對象導(dǎo)出

這個(gè)文件的目的是將上面的配置文件格式化為對象的形式:

{ 
  port: '8081',
  page_path: 'page',
  web_path: 'web',
  '': undefined
}

然后在需要配置項(xiàng)的地方使用globalConfig.xxx的形式即可欢峰。

index.js

此文件用于創(chuàng)建服務(wù)葬荷。

const express = require('express'); // 引入 express 模塊
const globalConfig = require('./config');  // 導(dǎo)入全局配置
const app = new express();  // 實(shí)例化一個(gè) express
const loader = require('./loader')
app.use(express.static(globalConfig['page_path'])); // 告訴 express , 靜態(tài)文件的位置
app.post("/dosomething", loader.get("/dosomething")) // 請求數(shù)據(jù)的方法
app.listen(globalConfig['port']); // 監(jiān)聽配置文件中的端口

app.post("/dosomething", loader.get("/dosomething")):
假設(shè)點(diǎn)擊了一個(gè)按鈕纽帖, 這個(gè)按鈕要獲取數(shù)據(jù)宠漩。這個(gè)請求可能是www.example.com/dosomething?name=xx&age=yy, 然后服務(wù)監(jiān)聽到這個(gè)請求, 然后就會去loader.js中尋找對應(yīng)的處理函數(shù)抛计, 對這個(gè)請求進(jìn)行處理哄孤。至于參數(shù)在哪里照筑, 這個(gè)請求是怎么處理的吹截, 在下面會介紹。

這個(gè)時(shí)候服務(wù)已經(jīng)搭好凝危, 已經(jīng)可以訪問靜態(tài)文件了波俄。

page

page 文件夾之下都是靜態(tài)資源信息。如果請求為靜態(tài)資源蛾默, 會直接去express.static參數(shù)的文件夾下尋找懦铺。

web

如果說 page 文件夾存放靜態(tài)資源, 那么 web 的作用就是存儲獲取動態(tài)數(shù)據(jù)的方法支鸡。
在這里冬念, 有許多的 controller趁窃,是用來處理邏輯的。這里有一個(gè)dosomething的例子:

const timeUtil = require('../Utils/timeUtil')
const writeRes = require('../Utils/resultUtil')
let path = new Map()
let dosomething = require('../dao/somethingDao');
function something(request, response) {
  request.on('data', function (data) {
    dosomething.dosomething(data, timeUtil.getNow(), function (res) {
      response.writeHead(200)
      response.write(writeRes.writeResult("success OK", timeUtil.getNow(), res))
      response.end()
    })
  })
}
path.set("/dosomething", something)
module.exports = path

請求的urlrequest里面急前⌒崖剑可以使用url模塊解析這個(gè)url獲取對應(yīng)的參數(shù)信息。data就是post請求發(fā)送過來的參數(shù)裆针。這里忽略了對 data 的解析刨摩。

loader.js

const fs = require('fs')
const globalConfig = require('./config')
let controllerSet = []
let pathMap = new Map()
let files = fs.readdirSync(globalConfig['web_path']) // 讀取文件夾
for (let i = 0, len = files.length; i < len; i++){ // 讀取 files 中所有的文件
  let temp = require('./' + globalConfig['web_path'] + '/' + files[i]) // 引入 web 里面的文件
  if(temp.path){
    for (let [key, value] of temp.path){ // 讀取 每一個(gè)文件的 path
      if(pathMap.get(key) == null){ // 如果在 pathMap 中沒有, 就添加進(jìn)去
        pathMap.set(key, value)
      }else {                       // 如果進(jìn)入 else 世吨, 說明 url 重了澡刹。 這當(dāng)然不允許
        throw new Error("url error, url: " + key);
      }
      controllerSet.push(temp)
    }
  }
}
module.exports = pathMap // 將 pathMap 導(dǎo)出

讀取上面的web文件夾, 引入所有的js文件耘婚, 引入一個(gè)解析一個(gè)罢浇, 獲取到所有的處理動態(tài)數(shù)據(jù)的方法, 將這些方法全部放入一個(gè)叫做pathMapMap中 边篮,然后將之導(dǎo)出己莺, 在index.js里面引入pathMap。然后根據(jù)不同請求戈轿, getloader里面對應(yīng)的方法凌受。

dao(Data Access Object)

此文件夾下有兩類文件,第一類只有一個(gè)思杯, 叫做DBUtil.js胜蛉,它用于創(chuàng)建一個(gè)與數(shù)據(jù)庫的鏈接。

let mysql = require('mysql')
function createConnection() {
  return mysql.createConnection({
    host: "127.0.0.1",
    port: "3306",
    user: "root",
    password: "123546",
    database: "test"
  })
}
module.exports.createConnection = createConnection

第二類可能有很多個(gè)色乾, 它們用于響應(yīng)用戶請求對數(shù)據(jù)庫的增刪改查操作誊册。
這里是上面dosomething的例子:

const DBUtil = require('./DBUtil')  // 引入創(chuàng)建數(shù)據(jù)庫的工具方法
function dosomething(content, ctime, success) {
  let sql = "insert into table (`content`, `ctime`) values (?, ?)" // 編寫數(shù)據(jù)庫查詢語句
  let params = [content, ctime]                   // 定義參數(shù)列表
  let connection = DBUtil.createConnection()      // 創(chuàng)建一個(gè)數(shù)據(jù)庫的鏈接
  connection.connect()                            // 連接
  connection.query(sql, params, function (err, result) {  // 進(jìn)行查詢
    if (!err){      // 如果過程沒有出錯(cuò)
      success(result)   
    } else {
      console.log(err)
    }
  })
  connection.end() // 查詢完畢一定要關(guān)閉數(shù)據(jù)庫的連接
}
module.exports.dosomething = dosomething // 將此方法導(dǎo)出,供 web 層使用

至此暖璧, 文件夾說明完畢案怯。

回顧整個(gè)流程。
使用 express 開啟一個(gè)服務(wù)澎办。
使用 app.get, app.post 等待對應(yīng)的請求進(jìn)來嘲碱。
請求進(jìn)來之后, 使用loader.get()拿到對應(yīng)的處理方法局蚀。這個(gè)方法去查詢數(shù)據(jù)庫麦锯, 邏輯復(fù)雜的還要經(jīng)過邏輯處理流程, 查詢完畢之后執(zhí)行loader預(yù)先設(shè)置到的回調(diào)函數(shù)琅绅, 這個(gè)回調(diào)函數(shù)返回給客戶端需要的數(shù)據(jù)眶明。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝗羊,一起剝皮案震驚了整個(gè)濱河市饿自,隨后出現(xiàn)的幾起案子刑枝,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡凑懂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門梧宫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來接谨,“玉大人,你說我怎么就攤上這事塘匣∨Ш溃” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵忌卤,是天一觀的道長扫夜。 經(jīng)常有香客問我,道長驰徊,這世上最難降的妖魔是什么笤闯? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮棍厂,結(jié)果婚禮上颗味,老公的妹妹穿的比我還像新娘。我一直安慰自己牺弹,他們只是感情好浦马,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著张漂,像睡著了一般晶默。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上航攒,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天磺陡,我揣著相機(jī)與錄音,去河邊找鬼漠畜。 笑死币他,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盆驹。 我是一名探鬼主播圆丹,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滩愁,長吁一口氣:“原來是場噩夢啊……” “哼躯喇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤廉丽,失蹤者是張志新(化名)和其女友劉穎倦微,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體正压,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欣福,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焦履。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拓劝。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嘉裤,靈堂內(nèi)的尸體忽然破棺而出郑临,到底是詐尸還是另有隱情,我是刑警寧澤屑宠,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布厢洞,位于F島的核電站,受9級特大地震影響典奉,放射性物質(zhì)發(fā)生泄漏躺翻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一卫玖、第九天 我趴在偏房一處隱蔽的房頂上張望公你。 院中可真熱鬧,春花似錦假瞬、人聲如沸省店。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懦傍。三九已至,卻和暖如春芦劣,著一層夾襖步出監(jiān)牢的瞬間粗俱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工虚吟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寸认,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓串慰,卻偏偏與公主長得像偏塞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子邦鲫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354