7.express

Express框架

首先我們先安裝Node.js

基于express框架愉烙,創(chuàng)建項(xiàng)目檐涝。

創(chuàng)建工程目錄

mkdir myNodeExpress01  
#創(chuàng)建項(xiàng)目
cd myNodeExpress01
#進(jìn)入目錄

通過npm init命令給你的應(yīng)用創(chuàng)建一個(gè)package.json 文件。(包含工程的基本信息忍抽,以及工程模塊的依賴列表)

npm init
#具體請看2_node NPM的使用因妇。

在項(xiàng)目的根目錄下安裝Express并將其保存在依賴列表中。

npm install express --save

在項(xiàng)目的根目錄下創(chuàng)建index.js文件找蜜,并在其中調(diào)用express 框架提供的方法饼暑,搭建web服務(wù)器。

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

const webApp=express();
const port=2222;

// 根據(jù)不同的請求處理業(yè)務(wù)
webApp.get('/',(req,res)=>{
    res.send('這是我的第一個(gè)express 應(yīng)用');
})
webApp.get('/login',(req,res)=>{
    res.send('這是我的的登錄');
})

webApp.listen(port,()=>{
    console.log(`server is running at http://127.0.0.1:${port}`);
});

以上是使用express 搭建一個(gè)基本的Web服務(wù)器的代碼示例.

1.快速入門

npm提供了大量的第三方模塊,其中不乏有許多web框架弓叛,之所以選擇使用Express作為開發(fā)框架彰居,因?yàn)樗悄壳白罘€(wěn)定,使用最廣泛撰筷,而且Node.js官方推薦的唯一一個(gè)WEB開發(fā)框架陈惰。
??Express除了為http模塊提供了更高層的接口外,還實(shí)現(xiàn)了許多功能闭专,其中包括:

  • 路由控制
  • 模板解析
  • 動(dòng)態(tài)視圖
  • 用戶會話
  • CSRF保護(hù)
  • 靜態(tài)文件服務(wù)
  • 錯(cuò)誤控制器
  • 訪問日志
  • 緩存
  • 插件支持
    ??Express 不是一個(gè)無所不能的全能框架,他只是一個(gè)輕量級的web框架旧烧,多數(shù)功能只是對HTTP協(xié)議中常用的操作的封裝影钉,更多的功能需要插件或者整合其他模塊來完成。

1.1 安裝express

$ npm install -g express //全局安裝

等待安裝完成后掘剪,我們可以在命令行下通過express 命令快速創(chuàng)建一個(gè)項(xiàng)目平委。
在使用以下命令安裝express-generator(應(yīng)用構(gòu)造器)

應(yīng)用程序生成器:
我們可以通過npx 命令來安裝express 應(yīng)用程序生成器。

mkdir myNodeExpress02
cd myNodeExpress02
npx  express-generator

也可以使用npm 命令安裝Express應(yīng)用程序生成器

npm install -g express-generator

$ npm install express-generator -g 

1.2 建立工程&啟動(dòng)工程(使用express-generator應(yīng)用構(gòu)造器創(chuàng)建項(xiàng)目)

通過以下命令建立網(wǎng)站的基本解構(gòu)

$ express projectName
// projectName 要?jiǎng)?chuàng)建的項(xiàng)目名稱

當(dāng)前目錄下會出現(xiàn)一個(gè)projectName的子目錄夺谁,并且創(chuàng)建一些文件:

   create : projectName/
   create : projectName/public/
   create : projectName/public/javascripts/
   create : projectName/public/images/
   create : projectName/public/stylesheets/
   create : projectName/public/stylesheets/style.css
   create : projectName/routes/
   create : projectName/routes/index.js
   create : projectName/routes/users.js
   create : projectName/views/
   create : projectName/views/error.jade
   create : projectName/views/index.jade
   create : projectName/views/layout.jade
   create : projectName/app.js
   create : projectName/package.json
   create : projectName/bin/
   create : projectName/bin/www

    // 執(zhí)行如下操作
   change directory:
     $ cd projectName   //進(jìn)入項(xiàng)目的根目錄

   install dependencies:
     $ npm install    //安裝項(xiàng)目需要的依賴

   run the app:
     $ DEBUG=projectname:* npm start  //啟動(dòng)項(xiàng)目

項(xiàng)目啟動(dòng)后廉赔,在瀏覽器輸入http://localhost:3000,訪問項(xiàng)目匾鸥。

1.3 工程結(jié)構(gòu)

1.3.1 app.js 和入口文件

app.js 是工程的配置文件蜡塌,


var createError = require('http-errors');
// http錯(cuò)誤處理模塊
var express = require('express');
// express 模塊
var path = require('path');
var cookieParser = require('cookie-parser');
// cookie 模塊
var logger = require('morgan');
// 日志模塊

// 引入的路由模塊
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// 視圖引擎的設(shè)置
app.set('views', path.join(__dirname, 'views'));
// 設(shè)置視圖目錄
app.set('view engine', 'ejs');
// 設(shè)置模板引擎  官方提供了jade ,ejs;ejs 更接近于HTML語法勿负,推薦使用

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
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;

./bin/www 是工程的入口文件馏艾。


// 以下文件內(nèi)容相較于實(shí)際項(xiàng)目有縮減
/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('projectname:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 * 創(chuàng)建web服務(wù)器
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 * 添加web 服務(wù)器端口監(jiān)聽
 */

server.listen(port,function(){
  console.log('server is running ,port is '+port);
});

1.3.2 public 靜態(tài)資源目錄

public中存放站點(diǎn)所需要的靜態(tài)資源,比如圖片,css,js,font等
配置靜態(tài)資源目錄奴愉,進(jìn)入app.js 文件琅摩,使用以下代碼:

// 靜態(tài)資源目錄的配置 靜態(tài)資源掛載
app.use('/static',express.static(path.join(__dirname, 'public')));//給靜態(tài)資源設(shè)置虛擬目錄
app.use(express.static(path.join(__dirname, 'public')));//默認(rèn)

1.3.3 views 視圖(ejs模板)目錄

此目錄下存放視圖文件。

1.3.4 routes 路由文件目錄

此目錄下存放路由文件锭硼。

2. 路由控制

路由是為了處理不同的請求(url)執(zhí)行的不同的操作房资。
我們要為路由提供請求的URL和其他需要的GET,POST檀头,以及參數(shù)轰异,之后路由需要根據(jù)這些數(shù)據(jù)來執(zhí)行相應(yīng)的代碼。

2.1 工作原理

express 是一個(gè)典型的MVC架構(gòu)暑始,瀏覽器發(fā)起請求溉浙,有路由控制器接受,根據(jù)不同的路徑定向到不同的控制器蒋荚,控制器處理用戶的具體請求(具體業(yè)務(wù))戳稽,可能會訪問數(shù)據(jù)庫中的對象,即模型部分【妫控制器還要訪問模板引擎互躬,生成視圖HTML,最后再由控制器返回給瀏覽器颂郎,完成一次請求吼渡。

2.2創(chuàng)建路由規(guī)則

在routes/index.js 文件中,有個(gè)已有的路由規(guī)則 router.get('/',function(){});

router.get('/',function(req,res){
    res.send('123332132123132123');
})

2.3路徑匹配規(guī)則

//router.get('/a/:parm1/:parm2');
// http://localhost:3000/a/parm1_val/parm2_val
// 取值時(shí)乓序,使用req對象中的params對象取值寺酪。
router.get('/a*/:username',function(req,res){
    res.send('參數(shù):'+req.params.username);
})

路徑規(guī)則/a/:username會被自動(dòng)編譯為正則表達(dá)式.路徑參數(shù)可以在響應(yīng)函數(shù)中通過req.params 的屬性訪問。

2.4 REST風(fēng)格的路由規(guī)則

Express 支持REST風(fēng)格的請求方式替劈,REST(表征狀態(tài)轉(zhuǎn)移Representational State Transfer),它是一種基于HTTP協(xié)議的網(wǎng)絡(luò)應(yīng)用的接口風(fēng)格寄雀,利用HTTP的方法實(shí)現(xiàn)統(tǒng)一風(fēng)格接口的服務(wù)。HTTP協(xié)議定義了以下8中標(biāo)準(zhǔn)的方法:

  • GET:請求獲取指定資源(獲取數(shù)據(jù))陨献;
  • HEAD:請求指定資源響應(yīng)頭 (獲取響應(yīng)頭信息)盒犹;
  • POST:向指定的資源提交數(shù)據(jù)(發(fā)送數(shù)據(jù));
  • PUT:請求服務(wù)器存儲的一個(gè)資源 (存儲數(shù)據(jù))眨业;
  • DELETE:請求服務(wù)器刪除指定資源 (刪除數(shù)據(jù))急膀;
  • TRACE:回顯服務(wù)器收到的請求,主要用于測試或者診斷
  • CONNECT:HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器龄捡。
  • OPTIONS:返回服務(wù)器支持的請求方法卓嫂。
    我們最常用的是GET,POST,PUT 和DELETE 方法。根據(jù)REST設(shè)計(jì)模式聘殖,這4種方法通常分別用于實(shí)現(xiàn)以下功能:
  • GET:獲取
  • POST:新增
  • PUT:更新
  • DELETE: 刪除
    ??Express 對每種HTTP請求方法都設(shè)計(jì)了不同的路由綁定函數(shù)命黔。
請求方式 綁定函數(shù)
GET app.get(path,callback)
POST app.post(path,callback)
PUT app.put(path,callback)
DELETE app.delete(path,callback)
PATCH app.patch(path,callback)
TRACE app.trace(path,callback)
CONNECT app.connect(path,callback)
OPTIONS app.options(path,callback)
所有方法 app.all(path,callback)

需要注意的是app.all函數(shù)煤傍,它支持把所有的請求方式綁定到同一個(gè)響應(yīng)函數(shù)想际。

2.5 控制權(quán)轉(zhuǎn)移

//routes/user.js
var users={ 
    username:'jiaWen',
    password:'123456' 
}
router.all('/:username',function(req,res,next){
  // 檢查用戶是否存在
  if(users['username']==req.params.username){
    // 用戶存在 
    next();
  }else{
    next(new Error(req.params.username+' 找不到數(shù)據(jù)'));
  }
})
router.get('/:username',function(req,res){
  // 用戶存在,直接展示用戶數(shù)據(jù) 
  res.send(JSON.stringify(users['username']+users['password']));
})

router.all定義的這個(gè)路由規(guī)則實(shí)際上起到了中間件作用,把相似的請求的相同部分提取出來常侦,有利于代碼維護(hù)其他next方法如果接受了參數(shù)洋机,也就代表發(fā)生錯(cuò)了坠宴,這種方式可以把錯(cuò)誤檢查分段化,降低代碼的耦合度绷旗。

3. 模板引擎

模板引擎(Template Engine)是一個(gè)從頁面模板根據(jù)一定的規(guī)則生成HTML的工具喜鼓。
??Express 內(nèi)置ejs和jade 兩種模板引擎(建議使用ejs),我們在Express框架中使用時(shí)衔肢,在app.js中通過以下語句設(shè)置了模板引擎和頁面模板的位置:

app.set('views',__dirname+'/views');//設(shè)置頁面模板位置
app.set('views engine','ejs');//設(shè)置使用的模板引擎

渲染頁面時(shí)庄岖,我們在響應(yīng)對象函數(shù)中使用res.render()渲染模板

router.get('/',function(req,res){
    // render(viewName,viewData);
    // *viewName 視圖名稱
    res.render('index',{data:'數(shù)據(jù)'});
})

ejs的標(biāo)簽系統(tǒng),常用三種標(biāo)簽

  • <% code %> JavaScript代碼
  • <%= code %> 顯示替換過HTML特殊字符的內(nèi)容|輸出變量內(nèi)容
  • <%- code %> 顯示原始的HTML內(nèi)容
  • <%- include('common/header',data); %> 在模板頁中引入另外一個(gè)模板頁角骤,并且傳輸data參數(shù)給指定的模板頁面(common/header)隅忿。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末心剥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子背桐,更是在濱河造成了極大的恐慌优烧,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件链峭,死亡現(xiàn)場離奇詭異畦娄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)弊仪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門熙卡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人励饵,你說我怎么就攤上這事驳癌。” “怎么了曲横?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵喂柒,是天一觀的道長不瓶。 經(jīng)常有香客問我禾嫉,道長,這世上最難降的妖魔是什么蚊丐? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任熙参,我火速辦了婚禮,結(jié)果婚禮上麦备,老公的妹妹穿的比我還像新娘孽椰。我一直安慰自己,他們只是感情好凛篙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布黍匾。 她就那樣靜靜地躺著,像睡著了一般呛梆。 火紅的嫁衣襯著肌膚如雪锐涯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天填物,我揣著相機(jī)與錄音纹腌,去河邊找鬼。 笑死滞磺,一個(gè)胖子當(dāng)著我的面吹牛升薯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播击困,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼涎劈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起责语,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤炮障,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坤候,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胁赢,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年白筹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了智末。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡徒河,死狀恐怖系馆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顽照,我是刑警寧澤由蘑,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站代兵,受9級特大地震影響尼酿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜植影,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一裳擎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧思币,春花似錦鹿响、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至博投,卻和暖如春绸贡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贬堵。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工恃轩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人黎做。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓叉跛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蒸殿。 傳聞我的和親對象是個(gè)殘疾皇子筷厘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容