1、安装

Express 是一个 基于 Node.js 的简洁灵活的 Web 应用框架,为 Web 应用程序提供一组强大的功能

在阅读这篇文章之前,请确保您已经安装了 Node.js,并对其有一些基本的理解

如果需要了解 Node.js 的内容,可以参考我的另一篇文章 —— 一篇入门Node.js

下面介绍 安装 Express 框架 的步骤,这里介绍的是基于 Node.js 本地安装的方法:

Node.js 本地安装是指在当前文件夹中安装所需模块(Express),而不影响全局配置

可以使用 npm install express --save 命令安装 Express 到根目录中的 node_modules 目录下

2、Hello World

首先创建一个文件夹,该文件夹将作为 Web 项目的根目录

然后在该文件夹中打开命令行,使用 npm init 命令为该文件夹生成一个 package.json 文件

package.json 文件是项目的配置文件,里面列出了有关项目的相关信息

接着使用 npm install express --save 安装到根目录中的 node_modules 目录下

最后在根目录下创建 server.js 文件,并在文件中编写如下代码:

// 引入 Express 模块
var express = require('express');
// 创建 Express 实例
var app = express();
// 设置路由
app.get('/', function (req, res) {
    res.send('Hello World');
})
// 启动服务器,监听端口 5000
var server = app.listen(5000);

上面是一个简单的应用程序,现在暂时还不需要理解其中的语法,等下将会逐一进行讲解

此时,打开命令行,使用 node server.js 运行程序

打开 http://127.0.0.1:5000/ 即可看到 Hello World 的问候语

3、基础路由设置

路由确定 应用程序如何响应特定端点的客户端请求

每个路由都可以有一个或多个处理函数,这些函数在路由匹配时执行,其语法格式如下:

app.METHOD(PATH, HANDLER)
  • METHOD:HTTP 请求方法
  • PATH:文件路径
  • HANDLER:路由匹配时执行的功能

以下面代码为例,当客户端以 GET 方法请求根路径资源时,执行匿名函数,发送 Hello World 响应

app.get('/', function (req, res) {
    res.send('Hello World');
})

(1)METHOD

METHOD 定义 HTTP 请求方法,Express 支持所有 HTTP 请求方法

例如,app.get(PATH, HANDLER) 用于为 PATH 路径上的 GET 请求方法添加处理函数 HANDLER

特殊的,app.all(PATH, HANDLER) 用于为 PATH 路径上的所有请求方法添加处理函数 HANDLER

(2)PATH

PATH 定义路径,它可以是字符串、字符串模式或正则表达式,下面将以例子进行说明

以下是基于 字符串 匹配的例子:

'/about' 匹配请求路径 /about

以下是基于 字符串模式 匹配的例子:

'/ab?cd' 匹配请求路径 /acd、/abcd(?:匹配 ? 前的字符 0 次或 1次)

'/ab+cd' 匹配请求路径 /abcd,/abbcd 等等(+:匹配 + 前的字符 1 次或多次)

'/ab*cd' 匹配请求路径 /abcd,/abRANDOMcd 等等(*:匹配任意字符串)

以下是基于 正则表达式 匹配的例子(在 / / 中写正则表达式):

/a/ 匹配任意包含字符 a 的请求路径

/.*fly$/ 匹配任意以 fly 结尾的请求路径

另外,我们还可以 在路径中指定参数

参数以 : 作为前缀,用于在 URL 中捕获指定位置的值,并将其保存在 req.params 中

例如,路由路径为:'/users/:userId/books/:bookId'

请求 URL 为:http://127.0.0.1:5000/users/34/books/8989

因此,得到的 req.params 为:{ "userId": "34", "bookId": "8989" }

(3)HANDLER

HANDLER 定义处理请求的方法,它可以是函数、函数数组或两者的组合形式

在使用多组函数时,必须确保使用 next() 方法将控制权传递给后续函数,否则将会直接终止

var express = require('express');
var app = express();
app.get('/', function (req, res) {
    res.send('Hello World');
})
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) {
    console.log('CB2')
}
app.get('/test', [cb0, cb1, cb2])
var server = app.listen(5000);

一般情况下,函数带有两个参数,分别是 RequestResponse 对象,用于处理请求和响应数据

Request 对象 常见的属性和方法有:

  • app:对 Express 应用程序实例的引用

  • ip:IP 地址
  • originalUrl:原始 URL
  • baseURL:基础 URL
  • protocol:协议类型
  • hostname:主机名
  • subdomains:子域名
  • path:资源路径
  • query:查询字符串
  • body:请求主体
  • route:当前匹配的路由
  • params:路由参数
  • cookies:当使用 cookie-parser 中间件时,包含 Cookie 对象
  • signedCookies:当使用 cookie-parser 中间件时,包含已签名的 Cookie 对象
  • get(field):获取指定的 HTTP 头

详细情况请参考:http://www.expressjs.com.cn/4x/api.html#req

Response 对象 常见的属性和方法有:

  • app:对 Express 应用程序实例的引用

  • set(field[,value]):设置 HTTP 头
  • get(field):返回 HTTP 头
  • append(field[,value]):添加 HTTP 头
  • status():设置状态码
  • redirect([status,]path):重定向
  • cookie(name,value[,option]):设置 Cookie
  • clearCookie(name[,options]):清除 Cookie
  • send([body]):传送响应
  • sendStatus(code):传送状态吗
  • sendFile(path[,options][,fn]):传送文件
  • json([body]):传送 JSON
  • end([data][,encoding]):结束响应

详细情况请参考:http://www.expressjs.com.cn/4x/api.html#res

var express = require('express');
var app = express();
app.get('/', function (req, res) {
    res.send('Hello World');
})
app.get('/:user', function (req, res) {
    res.send('Hello ' + req.params['user']);
})
var server = app.listen(5000);

4、高级路由设置

(1)app.route()

如果需要为同一路径的不同请求方法定义不同的处理函数,app.route(path) 是一个不错的选择

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 the book')
    })

(2)express.Router()

express.Router([options]) 可以用于创建路由器的实例,它又被称为 “迷你应用程序”,因为它就像 app 实例一样,可以为它添加中间件和路由,常用的方法如下:

  • METHOD(path[,callback ...]):与 app.METHOD(path,callback[,callback ...]) 类似
  • all(path,[callback ...]):与 app.all(path,callback[.callback ...]) 类似
  • route(path):与 app.route(path) 类似

详细情况请参考:http://www.expressjs.com.cn/4x/api.html#router

可以创建一个路由文件 router.js,并在文件中编写如下代码:

var express = require('express')
var router = express.Router()

// 添加中间件
router.use(function timeLog (req, res, next) {
    console.log('Time: ', Date.now())
    next()
})
// 添加路由
router.get('/', function (req, res) {
    res.send('Home page')
})
// 添加路由
router.get('/about', function (req, res) {
    res.send('About page')
})

module.exports = router

然后,我们可以在应用程序 server.js 中加载路由文件:

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

// ...

app.use('/router', router)

5、静态文件

Express 的内置中间件函数 express.static() 可以 提供 图片、CSS 和 JS 之类的静态文件

其语法格式如下:

express.static(root, [options])
  • root:储存静态文件的根目录路径
  • options:对象,用于提供更详细的信息

例如,我们创建一个简单的文件结构如下:

app(应用程序根目录)
    +-- node_module   (储存模块的文件夹)
    +-- public        (储存资源的文件夹)
        +-- images
            +-- icon.png
            +-- background.png
        +-- hello.html
        +-- style.css
        +-- script.js
    +-- package.json  (用于配置的文件)
    +-- server.js     (主程序文件)

我们可以在 server.js 中声明 public 目录下内容开放访问,即客户端可以通过地址进行请求

例如 http://127.0.0.1:5000/images/icon.pnghttp://127.0.0.1:5000/hello.html

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

如果需要为提供的文件创建虚拟路径前缀,可以在 app.use() 方法的参数中进行指定

例如 http://127.0.0.1:5000/static/images/icon.pnghttp://127.0.0.1:5000/static/hello.html

app.use('/static',express.static('public'))

6、中间件

中间件 (Middleware) 实际上是一个 函数,可以访问请求对象 (req),响应对象 (res) 以及 next 函数

(1)应用程序级中间件

可以使用 app.METHOD()app.use() 方法将应用程序级中间件绑定到 express() 实例

var express = require('express');
var app = express();
app.use(function (req, res, next) {
    // 由于没有指定路径,所以每个请求都会执行该中间件函数的功能
    console.log('Time:', Date.now()) // 中间件函数功能
    next() // 将控制权传递给下一个路由,否则会终止请求-响应周期
})
app.get('/user/:id', function (req, res, next) {
    res.send('USER') // 中间件函数功能
})
var server = app.listen(5000);

注意:中间件加载的顺序很重要,首先加载的中间件函数会先执行

(2)路由器级中间件

路由器级中间件的工作方式与应用程序级中间件的工作方式相同

区别在于路由器级中间件通过 router.METHOD()router.use() 方法绑定到 Router() 实例

var express = require('express');
var app = express();
var router = express.Router();
router.use(function (req, res, next) {
    // 由于没有指定路径,所以每个请求都会执行该中间件函数的功能
    console.log('Time:', Date.now()) // 中间件函数功能
    next() // 将控制权传递给下一个路由,否则会终止请求-响应周期
})
router.get('/user', function (req, res) {
    res.send('USER') // 中间件函数功能
})
app.use('/virtual', router)
var server = app.listen(5000);

(3)错误处理中间件

与其它中间件函数的定义方式相同

区别在于错误处理中间件的参数总是有四个,对应是 function(err, req, res, next)

app.use(function (err, req, res, next) {
    console.error(err.stack)
    res.status(500).send('Error!')
})

(4)内置中间件

除了上面介绍的 express.static() 内置中间件函数外,还有两个比较常用的内置中间件函数:

  • express.json():使用 JSON 帮助解析传入的请求
  • express.urlencoded():使用 RUL 编码帮助解析传入的请求

(5)第三方中间件

第三方中间件可以为 Express 应用程序添加功能,常用的第三方中间件可以参考下面的链接:

7、生成器

最后要介绍的一个内容就是 Express 生成器 express-generator,用于快速创建应用骨架

它包含 express 命令行工具,可以使用 npm install express-generator -g 命令安装

然后,我们就可以通过一个简单的命令创建一个应用的骨架

express --view=pug myapp
    create : myapp\
    create : myapp\public\
    create : myapp\public\javascripts\
    create : myapp\public\images\
    create : myapp\public\stylesheets\
    create : myapp\public\stylesheets\style.css
    create : myapp\routes\
    create : myapp\routes\index.js
    create : myapp\routes\users.js
    create : myapp\views\
    create : myapp\views\error.pug
    create : myapp\views\index.pug
    create : myapp\views\layout.pug
    create : myapp\app.js
    create : myapp\package.json
    create : myapp\bin\
    create : myapp\bin\www

    change directory:
      > cd myapp

    install dependencies:
      > npm install

    run the app:
      > SET DEBUG=myapp:* & npm start

一篇入门Express的更多相关文章

  1. 第一篇 入门必备 (Android学习笔记)

    第一篇 入门必备 第1章 初识Android 第2章 搭建你的开发环境 第3章 创建第一个程序--HelloWorld 第4章 使用Android工具   ●Android之父 Android安迪·罗 ...

  2. Tp5安全篇入门

    输入安全 设置public目录为唯一对外访问目录,不能把资源文件放入到应用目录: 使用框架提供的请求变量获取方法(Request类的param方法及input助手函数)而不是原生系统变量获取用户输入的 ...

  3. 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 9 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 ...

  4. 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 ...

  5. 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 ...

  6. Node.js入门教程 第五篇 (Express框架)

    Express框架 Express是适用于Node.js web的框架,提供了大量实用功能,例如路由功能及http功能. Express 框架核心特性: 可以设置中间件来响应 HTTP 请求. 定义了 ...

  7. 【前端】Vue2全家桶案例《看漫画》之番外篇、express上传漫画(可选)

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/vue_vux_app_extra_1.html 项目github地址:https://github.com/sha ...

  8. 一篇入门 -- Scala

    整体介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. 联邦理工学院洛桑(EPFL)的Martin Odersky于2001 ...

  9. node入门 express ejs

    hello.js var express = require("express"); var app = express(); app.get("/hello" ...

随机推荐

  1. iOS开发-多台机器共用证书问题

    今天又被证书的问题卡壳了: 在公司的电脑上申请的开发.发布证书,回家用自己的电脑从苹果开发者中心上将证书和配置文件都下载下来提示用不了,弄了很久才想起.p12文件,必须从申请证书的电脑上导出,导入到自 ...

  2. dpdpdpdp~~~!!!

    dpdpdpdpdpdp D你妹个P!  妈的劳资就不信征服不了你!!哼!!

  3. HDU 1394 线段树or 树状数组~

    Minimum Inversion Number Description The inversion number of a given number sequence a1, a2, ..., an ...

  4. 4.3 Writing a Grammar

    4.3 Writing a Grammar Grammars are capable of describing most, but not all, of the syntax of program ...

  5. bzoj4825

    LCT 昨天调试一天没出来,今天推倒重写还是gg了,内心崩溃照着源代码抄,结果发现自己把原树fa和splay的fa一起维护,各种re... 其实我们手玩一下,发现其实树的形态变化很小,那么就可以用lc ...

  6. bzoj4869

    http://www.lydsy.com/JudgeOnline/problem.php?id=4869 终于A了...参考了下dalao的代码... 拓展欧几里得定理,改了几次就不变了,但是用的时候 ...

  7. bootstrap的modal弹窗,在多层窗口关闭时只会关闭自窗口,不再关闭父窗口

    bootstrap多层modal弹窗时.当子窗口关闭时,所有父窗口一起关闭. 原因是bootstrap在窗口关闭事件委托时,委托给所有窗口. 如源码: this.$element.on('click. ...

  8. bzoj 1637: [Usaco2007 Mar]Balanced Lineup【瞎搞】

    我是怎么想出来的-- 把种族为0的都变成-1,按位置x排升序之后,s[i]表示种族前缀和,想要取(l,r)的话就要\( s[r]-s[l-1]==0 s[r]==s[l-1] \),用一个map存每个 ...

  9. 公司5:JrVue表格

    组件名称:jr-dynamic-query-table 组件布局 table组件名称:  jr-dynamic-query-table 分页组件名称: el-pagination <div re ...

  10. ACM_校庆素数

    校庆素数 Time Limit: 2000/1000ms (Java/Others) Problem Description: 广财建校33年了,如今迎来了她的校庆. 小财最近想在研究素数,她突发奇想 ...