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)隅忿。