[TOC]
# Express
## 概述
  雖然使用 Node.js 中的 http 模塊是可以開發 Web 應用的,處理靜態資源,處理動態資源,請求分發(路由)等等,也可以讓開發者對 HTTP 協議的理解更加清晰,但是使用起來比較復雜,開發效率低。
  npm 提供了大量的第三方模包,其中不乏許多 Web 框架。Express框架是目前最穩定、使用最廣泛,而且 Node.js 官方推薦的唯一一個 Web 開發框架。除了為 http 模塊提供了更高層的接口外,還實現了許多功能,其中包括:
* 靜態文件服務
* 路由控制
* 模板解析支持
* 動態視圖
* 用戶會話
* CSRF保護
* 錯誤控制器
* 訪問日志
* 緩存
* 插件支持
## 安裝使用
1. 首先創建一個名為 myapp(可自定義) 的目錄,在命令行輸入并運行 npm init -y。 使用 npm install express 安裝 Express 包;
2. 其次在 myapp 目錄中,創建一個名為 static.js (可自定義)的文件,并復制下面示例中的代碼。
```
const express=require('express');//引入文件
const app = express();//創建對象
app.get('/',(req,res) =>res.send('Hello?World'));
app.listen(8888,() =>console.log('啟動成功'));
```
使用 node app.js 啟動應用,訪問 [http://localhost:8888/](http://localhost:8888/) 就可以看到效果。
## 靜態資源服務
為了提供訪問諸如圖片、CSS 文件和 JavaScript 文件之類的靜態文件的服務,使用 Express 中的 express.static 函數,格式如下
```
constexpress =require('express');
constpath =require('path');
//?類似昨天我們創建?server
varapp =express();
//?應用靜態資源服務的中間件
//?static?這個方法返回一個函數,中間件
//?簡單靜態資源服務
//?app.use(express.static(path.join(__dirname,'static')));
//?指定虛擬路徑靜態資源服務--從路徑可以讓我們區分訪問的資源是靜態的還是動態的
app.use('/static',express.static(path.join(__dirname,'static')));
//?針對請求路徑/?且請求方式?get,?就會執行我們下面這個匿名函數
app.get('/',function(req,res){
res.send('你好');
});
//?針對請求路徑/?且請求方式?get,?就會執行我們下面這個匿名函數
app.get('/a',function(req,res){
res.send('你好2');
});
//?綁定端口啟動應用
app.listen(8888,() =>{console.log('啟動成功');});
```
## 路由
路由指根據不同請求路徑和請求方式進行路徑分發,導向到不同處理函數,執行不同的業務邏輯。
### 請求方式匹配
HTTP 請求常見的請求方式有 get、post、put、delete 等,Express 支持按請求方式的路由規則。
**app.method**:指定某請求方式的匹配規則;
**app.all**: 指定所有請求方式的匹配規則;
**app.route**: 指定某請求路徑的匹配規則;
**app.use**: 應用多個匹配規則;
```
const express =require('express');
const indexRouter =express.Router();
indexRouter.get('/',(req,res) =>{res.send('get?index');})//?GET/
module.exports =indexRouter;
```
```
const express =require('express');
const userRouter =express.Router();
userRouter.get('/',(req,res) =>{res.send('GET');})//?GET/
.post('/',(req,res) =>{res.send('POST');})//?POST/
.put('/',(req,res) =>{res.send('PUT');})//?PUT/
.delete('',(req,res) =>{res.send('DELETE');});//?DELETE/
module.exports =userRouter;
```
```
const express =require('express');
const productRouter = express.Router();
productRouter.get('/',(req,res) =>{res.send('get?product');})//?GET/
.post('/',(req,res) =>{res.send('post?product');})//?POST/
.put('/',(req,res) =>{res.send('put?product');})//?PUT/
.delete('/',(req,res) =>{res.send('delete??product');})//?DELETE/
.all('/',?(req,?res)? =>?{res.end('all?product');});//?ALL
module.exports =productRouter;
```
```
const express = require('express');
const indexRouter = require('./router/index.js');//導入路由
const userRouter = require('./router/user.js');//導入路由
const productRouter = require('./router/product.js');//導入路由
const app = express();
app.use('/abc/index',?indexRouter);//應用路由?
app.use('/abc/user',?userRouter);//應用路由?
app.use('/abc/product',?productRouter);//應用路由?
app.listen(9979,() =>{console.log('啟動成功');
});
```
## 請求路徑匹配
路由路徑可以是字符串、字符串模式或正則表達式。
```
constexpress\=require('express');
constapp\=express();
?//?GET/
//app.get('/',(req,res)=>{res.send('GET');});
//?POST/
//app.get('/',(req,res)=>{res.send('POST');});
//?PUT/
//app.get('/',(req,res)=>{res.send('PUT');})
//?DELETE/
//app.get('/',(req,res)=>{res.send('DELETE');});?
//?鏈式調用
//?GET/
app.get('/',(req,res)\=>{res.send('GET');})
//?POST/
.post('/',(req,res)\=>{res.send('POST');})
//?PUT/
.put('/',(req,res)\=>{res.send('PUT');})
//?DELETE/
.delete('/',(req,res)\=>{res.send('DELETE');})
//?ALL
.all('/abc',?(req,?res)?\=>?{res.end('ALL');});
app.listen(8886,()\=>{console.log('啟動成功');
});
```
## 模塊化路由處理程序
使用 express.Router 類來創建可安裝的模塊化路由處理程序。Router 實例是一個路由系統。
1. router.method :指定某請求方式的匹配規則;
2. router.all :指定所有請求方式的匹配規則
3. router.route :指定某請求路徑的匹配規則;
4. router.use :應用多個匹配規則。
**index.js文件代碼**
```
// 文件位置:myapp/routes/index.js
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
res.send('home page');
});
router.get('/about', function(req, res) {
res.send('About us');
});
module.exports = router;
```
**users.js文件代碼**
```
// 文件位置:myapp/routes/users.js
const express = require('express');
const router = express.Router();
router.route('/')
.get((req, res) => {
res.send('get user data');
}).post((req, res) => {
res.send('post user data');
}).put((req, res) => {
res.send('put user data');
}).delete((req, res) => {
res.send('delete user data');
});
module.exports = router;
```
**app.js文件代碼**
```
// 文件位置:myapp/app.js
const express = require('express');
const app = express();
const index = require('./routes/index'); // 導入路由
const users = require('./routes/users'); // 導入路由
app.use('/', index); // 應用路由
app.use('/users', users); // 應用路由
app.listen(8888, () => {
console.log('running...');
});
```