21、Node.js Express 框架

Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用

使用Express 可以快速地搭建一个完整功能的网站

Express 框架核心特性:

1、 可以设置中间件来响应HTTP请求;
2、 定义了路由表用于执行不同的HTTP请求动作;
3、 可以通过向模板传递参数来动态渲染HTML页面;

安装 Express

$ npm install express --save

以上命令会将 Express 框架安装在当前目录的 node_modules 目录中

node_modules 目录下会自动创建 express 目录

其它依赖模块

Express 框架只能开发简单的网站,如果要开发一个功能齐全的网站还需要安装一下模块

1、 body-parser

Node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据

2、 cookie-parser

解析 Cookie 的工具。通过 req.cookies 可以取到传过来的 cookie,并把它们转成对象

3、 multer

Node.js 中间件,用于处理 enctype="multipart/form-data"(设置表单的MIME编码)的表单数据

$ npm install body-parser --save
$ npm install cookie-parser --save
$ npm install multer --save

安装完后,可以使用以下命令查看 express 的版本号

$ npm list express
~/curl_main/node
└── express@4.16.2 

第一个 Express 框架应用

我们使用 Express 框架开发一个 WEB 服务输出 “Hello World”

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/
var express = require('express');
var app = express();

app.get('/', function (req, res) {

    res.write('<h1>Hello World</h1>');
    res.write('DDKK.COM 弟弟快看,程序员编程资料站,教程 </p>');
    res.end();
})

var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js 
应用范例,访问地址为 http://:::8080

在浏览器中访问 http://127.0.0.1:8080,显示如下

 

请求和响应

Express 路由回调函数的参数: requestresponse 对象封装了请求和响应的数据

app.get('/', function (req, res) {
   // ...
})

requestresponse 对象包含很多属性和方法

Request 对象

request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性

属性 描述
req.app 当 callback 为外部文件时,用 req.app 访问 express 的实例
req.baseUrl 获取路由当前安装的URL路径
req.body
req.cookies
获得「请求主体」/ Cookies
req.fresh
req.stale
判断请求是否还「新鲜」
req.hostname
req.ip
获取主机名和IP地址
req.originalUrl 获取原始请求URL
req.params 获取路由的parameters
req.path 获取请求路径
req.protocol 获取协议类型
req.query 获取URL的查询参数串
req.route 获取当前匹配的路由
req.subdomains 获取子域名
req.accepts() 检查可接受的请求的文档类型
req.acceptsCharsets
req.acceptsEncodings
req.acceptsLanguages
返回指定字符集的第一个可接受字符编码
req.get() 获取指定的HTTP请求头
req.is() 判断请求头Content-Type的MIME类型

Response 对象

response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据

属性 描述
res.app 同 req.app 一样
res.append() 追加指定 HTTP 头
res.set() 在 res.append() 后将重置之前设置的头
res.cookie(name,value [,option]) 设置 Cookie
res.clearCookie() 清除 Cookie
res.download() 传送指定路径的文件
res.get() 返回指定的HTTP头
res.json() 传送JSON响应
res.jsonp() 传送JSONP响应
res.location() 只设置响应的 Location HTTP 头,不设置状态码或者返回信息
res.redirect() 设置响应的Location HTTP头,并且设置状态码302
res.send() 传送HTTP响应
res.sendFile(path [,options] [,fn]) 传送指定路径的文件,会自动根据文件 extension 设定 Content-Type
res.set() 设置 HTTP 头,传入 object 可以一次设置多个头
res.status() 设置 HTTP 状态码
res.type() 设置 Content-Type 的 MIME 类型

Express 路由

前面我们已经学习开发了 HTTP 请求的基本应用,而路由决定了由哪个脚本去响应客户端请求

在HTTP 请求中,我们可以通过路由提取出请求的 URL 以及 GET/POST 参数

现在我们在 Hello World 基础上添加一些功能来处理更多类型的 HTTP 请求

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var app = express();

//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js
应用实例,访问地址为 http://:::8080

我们可以尝试访问 http://127.0.0.1:8080 不同的地址查看效果

1、 访问首页http://127.0.0.1:8080

![img\_2.png][img_2.png]

2、 访问http://127.0.0.1:8080/user/list

![img\_3.png][img_3.png]

3、 访问http://127.0.0.1:8080/abcd

![img\_4.png][img_4.png]

4、 访问http://127.0.0.1:8080/abcdefg

![img\_5.png][img_5.png]

静态文件

Express 内置的中间件 express.static 可以设置静态文件 ( 如:图片, CSS, JavaScript 等)

我们可以将静态文件 ( 图片, CSS, JavaScript ) 等放到 static 目录下,然后使用 express.static 中间件来设置静态文件路径

app.use(express.static('static'));

我们可以放一些图片到 static/img 目录下,如下所示

$ tree static 
static
└── static
    ├── css
    ├── img
    │   ├── nodejs_express_1.jpeg
    │   ├── nodejs_express_2.jpeg
    │   ├── nodejs_express_3.jpeg
    │   ├── nodejs_express_4.jpeg
    │   └── nodejs_express_5.jpeg
    ├── js
    └── media

5 directories, 5 files

然后修改我们的 main.js 添加静态文件处理功能

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var app = express();

app.use(express.static('static'));
//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js                                              
Node.js Express 应用范例,访问地址为 http://:::8080

在浏览器中访问 http://127.0.0.1:8080/static/img/nodejs_express_1.jpeg 显示如下

 

Express 路由 GET 方法

现在我们使用 Express 开发一个表单,然后接收和处理表单传过来的数据

form_get.html

<html>
<body>
<form action="http://127.0.0.1:8080/get">
<p>姓: <input type="text" name="first_name">

名: <input type="text" name="last_name">
<input type="submit" value="提交">
</form>
</body>
</html>

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var app = express();

app.use(express.static('static'));
//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
app.get('/form_get.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.query.first_name,
       "last_name":req.query.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_get.html,如图所示

 

我们可以向表单输入数据,然后提交,演示如下

 

Express 路由 POST 方法

上面我们已经用 GET 方法提交了表单,现在我们在开发一个表单,使用 POST 方法来提交表单

我们需要使用 body-parser 插件来解析 POST 提交的表单

form_post.html

<html>
<body>
<form action="http://127.0.0.1:8080/post" method="POST">
POST 方法提交表单

姓: <input type="text" name="first_name">

名: <input type="text" name="last_name">
<input type="submit" value="提交">
</form>
</body>
</html>

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })

//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
app.get('/form_post.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.body.first_name,
       "last_name":req.body.last_name
   };
   res.end(JSON.stringify(response));
})
app.get('/form_get.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.query.first_name,
       "last_name":req.query.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_post.html,如图所示

 

我们可以向表单输入数据,然后提交,演示如下

 

Express 上传文件范例

我们已经学过了如何用 POST 方法提交表单,现在我们学习如何用 POST 方法开发上传文件范例

上传文件的表单需要设置 form 的 enctype 属性为 “multipart/form-data”

Express 项目中需要设置

var multer  = require('multer');

app.use(multer({ dest: '/tmp/'}).array('image'));

form_upload.html

<html>
<head>
<title>文件上传表单</title>
</head>
<body>
<h3>文件上传:</h3>
选择一个文件上传:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上传文件" />
</form>
</body>
</html>

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var fs = require('fs');
var app = express();
var bodyParser = require('body-parser');
var multer  = require('multer');

app.use(multer({ dest: '/tmp/'}).array('image'));
app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })

//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
app.get('/form_upload.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_upload.html" );
})

app.post('/upload', function (req, res) {

   console.log(req.files[0]);  // 上传的文件信息

   var des_file = __dirname + "/" + req.files[0].originalname;
   fs.readFile( req.files[0].path, function (err, data) {
        fs.writeFile(des_file, data, function (err) {
         if( err ){
              console.log( err );
         }else{
               response = {
                   message:'File uploaded successfully', 
                   filename:req.files[0].originalname
              };
          }
          console.log( response );
          res.end( JSON.stringify( response ) );
       });
   });
})
app.get('/form_post.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.body.first_name,
       "last_name":req.body.last_name
   };
   res.end(JSON.stringify(response));
})
app.get('/form_get.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.query.first_name,
       "last_name":req.query.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_upload.html,如图所示

 

我们可以选择图片,然后点击上传按钮,演示如下

 

Express Cookie 管理

Express 的 response 对象的 res.cookie() 方法和 res.clearCookie 方法可以用来设置和清除 Cookie

当使用cookie-parser 中间件时,还可以设置签名 Cookie 和 获取 Cookie 信息

下面我们就简单的演示下这些方法的使用

main.js

/*
 * filename: main.js
 * author: DDKK.COM 弟弟快看,程序员编程资料站(ddkk.com)
 * Copyright © 2015-2065 ddkk.com. All rights reserved.
*/

var express = require('express');
var fs = require('fs');
var app = express();
var bodyParser = require('body-parser');
var multer  = require('multer');
var cookieParser = require('cookie-parser')

app.use(cookieParser());
app.use(multer({ dest: '/tmp/'}).array('image'));
app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })

//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
app.get('/cookie/set',function(req,res){
    res.cookie('sitename', 'DDKK.COM 弟弟快看,程序员编程资料站', { maxAge: 900000, httpOnly: true })
    res.write('<h1>设置 Cookie </h1>');
    res.write('<p>设置了 Cookie: sitename="DDKK.COM 弟弟快看,程序员编程资料站" </p>')
    res.end('<p><a href="/cookie/get">获取 Cookie</a></p>');
});

app.get('/cookie/get',function(req,res){
    res.write("<h1>获取 Cookie 信息 </h1>");
    res.write("<p>本站的 Cookie 信息如下:" + JSON.stringify(req.cookies) + "</p>");
    res.end();
});

app.get('/form_upload.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_upload.html" );
})

app.post('/upload', function (req, res) {

   console.log(req.files[0]);  // 上传的文件信息

   var des_file = __dirname + "/" + req.files[0].originalname;
   fs.readFile( req.files[0].path, function (err, data) {
        fs.writeFile(des_file, data, function (err) {
         if( err ){
              console.log( err );
         }else{
               response = {
                   message:'File uploaded successfully', 
                   filename:req.files[0].originalname
              };
          }
          console.log( response );
          res.end( JSON.stringify( response ) );
       });
   });
})
app.get('/form_post.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.body.first_name,
       "last_name":req.body.last_name
   };
   res.end(JSON.stringify(response));
})
app.get('/form_get.html', function (req, res) {
   res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

   // 输出 JSON 格式
   var response = {
       "first_name":req.query.first_name,
       "last_name":req.query.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})

//  /user/del 页面响应
app.get('/user/dell', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})

//  /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
   console.log("/user/list GET 请求");
   res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
var server = app.listen(8080, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/cookie/get.html,如图所示

 

我们可以选择图片,然后点击上传按钮,演示如下

 

相关资料

1、 Express官网:http://expressjs.com/
2、 Express4.xAPI:http://www.expressjs.com.cn/4x/api.html