Express


title: Express

date: 2019-09-06 14:30:24

tags: 后端

categories:  # 这里写的分类会自动汇集到 categories 页面上,分类可以多级

  • 后端 # 一级分类
  • Node.js # 二级分类

介绍

Express 是基于 Node.js 平台的 web 开发框架.

快速创建

使用以下命令安装 express

1
2
//express脚手架
npm install express-generator -g

使用-h选项显示命令选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
express -h
Usage: express [options][dir]
//用法

Options:

-h, --help output usage information
--version output the version number
-e, --ejs add ejs engine support
--hbs add handlebars engine support
--pug add pug engine support
-H, --hogan add hogan.js engine support
--no-view generate without view engine
-v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
--git add .gitignore
-f, --force force on non-empty directory

例如,以下语句在当前工作目录中创建名为 myapp 的 Express 应用程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ express --view=pug myapp

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

然后安装依赖项:

1
2
cd myapp
npm install

在 Mac 或 Linux 下采用以下命令运行此程序

1
DEBUG=myapp:* npm start

在 windows 上

1
set DEBUG=myapp:* & npm start

然后在浏览器输入`http://localhost:3000 访问

基本路由

中间件: 处理请求的函数.

模板引擎: <%= 写入的变量名 %>,其中变量名可以在其他地方赋值,这样就可以批量改变变量了.

后台

基本页面: 创建,列表,展示

静态文件

提供图像,css 和 js 之类的静态文件,请使用 express.static 内置中间件函数.

使用以下代码在名为 public 的目录中提供图像,css 和 js 之类的静态文件

1
app.use(express.static("public"));

现在,可以访问位于 public 目录中的文件:

1
2
3
4
5
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html

要使用多个静态资源目录,请多次调用 express.static 中间件函数:

1
2
app.use(express.static("public"));
app.use(express.static("files"));

Express 以您使用 express.static 中间件函数设置静态目录的顺序来查找文件。

要为 express.static 函数提供的文件创建虚拟路径前缀(路径并不实际存在于文件系统中),请为静态目录指定安装路径,如下所示:

1
app.use("/static", express.static("public"));

向 express.static 函数提供的路径相对于您在其中启动 node 进程的目录。如果从另一个目录运行 Express 应用程序,那么对于提供资源的目录使用绝对路径会更安全:

1
app.use("/static", express.static(__dirname + "/public"));

路由

基本路由示例:

1
2
3
4
5
6
var express = require("express");
var app = express(); //在`myapp/bin/www`里创建了app的服务器

app.get("/", function (req, res) {
red.send("hello world"); //给浏览器发一个hello world
});

路由方法

GET 和 POST 的示例

1
2
3
4
5
6
7
8
9
//GET
app.get("/", function (req, res) {
res.send("GET request to the homepage");
});

//POST
app.post("/", function (req, res) {
res.send("POST request to the homepage");
});

有一种特殊路由方法:app.all(),它并非派生自 HTTP 方法。该方法用于在所有请求方法的路径中装入中间件函数。

在以下示例中,无论您使用 GET、POST、PUT、DELETE 还是在 http 模块中支持的其他任何 HTTP 请求方法,都将为针对“/secret”的请求执行处理程序。

1
2
3
4
app.all("/secret", function (req, res, next) {
console.log("Accessing the secret section ...");
next(); // pass control to the next handler
});

路由路径

‘/‘表示根路径

1
2
3
app.get("/", function (req, res) {
res.send("root");
});

和’/about’路径匹配

1
2
3
app.get("/about", function (req, res) {
res.send("random.txt");
});

基于字符串模式的匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//此路由路径将匹配 abcd、abbcd、abbbcd 等。

app.get("/ab+cd", function (req, res) {
res.send("ab+cd");
});
//此路由路径将匹配 abcd、abbcd、abbbcd 等。

app.get("/ab+cd", function (req, res) {
res.send("ab+cd");
});

//此路由路径将匹配 abcd、abxcd、abRABDOMcd、ab123cd 等。

app.get("/ab*cd", function (req, res) {
res.send("ab*cd");
});

//此路由路径将匹配 /abe 和 /abcde。

app.get("/ab(cd)?e", function (req, res) {
res.send("ab(cd)?e");
});

字符 ?、+、* 和 () 是其正则表达式同应项的子集。基于字符串的路径按字面理解连字符 (-) 和点 (.)。

路由处理程序

可以提供多个回调函数,以类似于中间件的行为方式来处理请求。

唯一例外是这些回调函数可能调用 next(‘route’) 来绕过剩余的路由回调。

可以使用此机制对路由施加先决条件,在没有理由继续执行当前路由的情况下,可将控制权传递给后续路由。

路由处理程序的形式可以是一个函数、一组函数或者两者的结合,如以下示例中所示。

单个回调函数可以处理一个路由。例如:

1
2
3
app.get("/example/a", function (req, res) {
res.send("Hello from A!");
});

多个回调函数可以处理一个路由(确保您指定 next 对象)。例如:

1
2
3
4
5
6
7
8
9
10
app.get(
"/example/b",
function (req, res, next) {
console.log("the response will be sent by the next function ...");
next();
},
function (req, res) {
res.send("Hello from B!");
}
);

一组回调函数可以处理一个路由。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var cb0 = function (req, res, next) {
console.log("CB0");
next();
};

var cb1 = function (req, res, next) {
console.log("CB1");
next();
};

var cb2 = function (req, res) {
res.send("Hello from C!");
};

app.get("/example/c", [cb0, cb1, cb2]);

独立函数与一组函数的组合可以处理一个路由。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var cb0 = function (req, res, next) {
console.log("CB0");
next();
};

var cb1 = function (req, res, next) {
console.log("CB1");
next();
};

app.get(
"/example/d",
[cb0, cb1],
function (req, res, next) {
console.log("the response will be sent by the next function ...");
next();
},
function (req, res) {
res.send("Hello from D!");
}
);

响应方法

响应对象 (res) 的方法可以向客户端发送响应,并终止请求/响应循环。如果没有从路由处理程序调用其中任何方法,客户端请求将保持挂起状态。

方法 描述
res.download() 提示将要下载文件。
res.end() 结束响应进程。
res.json() 发送 JSON 响应。
res.jsonp() 在 JSONP 的支持下发送 JSON 响应。
res.redirect() 重定向请求。
res.render() 呈现视图模板。
res.send() 发送各种类型的响应。
res.sendFile 以八位元流形式发送文件。
res.sendStatus() 设置响应状态码并以响应主体形式发送其字符串表示。

app.route()

可以使用app.route()为路由路径创建可连接的路由处理程序

因为在单一位置指定路径,可以减少冗杂和输入错误.

1
2
3
4
5
6
7
8
9
10
11
app
.route("/book")
.get(function (req, res) {
res.send("get a book");
})
.post(function (req, res) {
res.send("add a book");
})
.put(function (req, res) {
res.send("update a book");
});

express.Router

使用 express.Router 类来创建可安装的模块化路由处理程序。Router 实例是完整的中间件和路由系统;因此,常常将其称为“微型应用程序”。

以下示例将路由器创建为模块,在其中装入中间件,定义一些路由,然后安装在主应用程序的路径中。

在应用程序目录中创建名为 birds.js 的路由器文件,其中包含以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var express = require("express");
var router = express.Router();

// middleware that is specific to this router
//use是不管get还是post都可以匹配
router.use(function timeLog(req, res, next) {
console.log("Time: ", Date.now());
next();
});
// define the home page route
router.get("/", function (req, res) {
res.send("Birds home page");
});
// define the about route
router.get("/about", function (req, res) {
res.send("About birds");
});

module.exports = router;

接着,在应用程序中装入路由器模块:

1
2
3
var birds = require('./birds');
...
app.use('/birds', birds);

此应用程序现在可处理针对 /birds 和 /birds/about 的请求,调用特定于此路由的 timeLog 中间件函数。