NodeJS的Web框架Express入门

专栏收录该内容

Hi I'm Shendi



最近准备编写一些轻量的Web后端程序,对于Java来说,启动一个应用就吃上百MB,属实吃不消,于是使用了node.js,而web框架选用express,上手还是非常简单的



什么是Express?

Express 是最流行的 Node 框架,它提供了以下机制:

  • 为不同 URL 路径中使用不同 HTTP 动词的请求(路由)编写处理程序。
  • 集成了“视图”渲染引擎,以便通过将数据插入模板来生成响应。
  • 设置常见 web 应用设置,比如用于连接的端口,以及渲染响应模板的位置。
  • 在请求处理管道的任何位置添加额外的请求处理“中间件”。

虽然 Express 本身是极简风格的,但是开发人员通过创建各类兼容的中间件包解决了几乎所有的 web 开发问题。这些库可以实现 cookie、会话、用户登录、URL 参数、POST 数据、安全头等功能。可在 Express 中间件 网页中找到由 Express 团队维护的中间件软件包列表(还有一张流行的第三方软件包列表)。



开发环境

首先需要安装node.js,可以参考 https://sdpro.top/blog/html/article/1086.html

然后执行 npm init 为你的应用创建一个 package.json 文件

最后执行以下命令将 Express 加入你的应用

npm install express --save

如果只是临时安装 Express,不想将它添加到依赖列表中,可执行如下命令:

npm install express --no-save


快速入门


Hello,World 示例

新建一个 js 文件编写程序,可以命名为 index.js

首先引入 express 模块

const express = require('express');

然后获取express的实例

var app = express();

通过实例可以开启一个服务端监听指定端口,并且可以设置http路由,当请求的路由匹配设置的路由时,将执行路由对应的函数操作,如下

// 监听 / 路由,req代表请求实例,res代表响应实例,路由匹配后执行函数
app.get('/', (req, res) => {
	res.send('Hello World!');
});

// 开启服务端监听指定端口
var port = 8080;
app.listen(port, () => {
    console.log(`服务端已开启,监听端口: ${port}`);
});

PS:上面的反引号(`) 是模板字符串,ES6的特性,可以注入参数等


保存js,执行控制台命令 node index.js 启动程序


打开浏览器,输入 localhost:8080 查看效果,效果如下

效果


在任务管理器查看内存占用情况,只占用了11MB

内存占用



基础路由

语法为 app.METHOD(PATH, HANDLER)

其中 METHOD 为请求类型,小写,例如 get,post,delete,put...

PATH为路由路径,字符串

HANDLER为回调函数

例如

app.get('/', function (req, res) {
  res.send('Hello World!');
});
app.post('/', function (req, res) {
  res.send('Got a POST request');
});
app.put('/user', function (req, res) {
  res.send('Got a PUT request at /user');
});
app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user');
});


静态文件

除了提供接口外,正常的后端都拥有一个单独的文件夹对外提供,文件夹内的资源可以直接通过url访问

通过 express.static 来实现

例如将 public 文件夹作为静态资源目录对外提供

const express = require('express');
var app = express();
app.use(express.static('public'));

这样可以直接通过url来访问public下的资源了,默认是根路径 /

例如 public 下有一个文件 img.jpg,监听端口为8080,那么访问的url为 localhost:8080/img.jpg


一般不会将静态资源目录作为根目录,可能会与接口路由重复之类的,可以通过以下方法将路由设置为 static

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

这样,通过 /static/img.jpg 才可以访问上面说的那个文件了


有的时候静态资源目录不在项目根目录,而在其他文件夹,这时候需要指定绝对路径

const path = require('path')
app.use('/static', express.static(path.join("静态地址绝对路径", 'public')))


Express项目生成器

目前我们的编写方式是自由的,没有一个骨架结构,甚至可以将所有接口都写到 index.js 内,这样对于后期维护来说不是很友好。

通过应用生成器工具 express-generator 可以快速创建一个应用的骨架。

可以通过 npx (包含在 Node.js 8.2.0 及更高版本中)命令来运行 Express 应用程序生成器。

我下载的是最新版的node,所以自带了npx

npx express-generator

对于较老的 Node 版本,请通过 npm 将 Express 应用程序生成器安装到全局环境中并使用:

npm install -g express-generator
express

我使用的第二种方法,cnpm install -g express-generator

安装完,执行 express 后,输入 y,会发现在当前文件夹生产了一个基本的项目结构

创建的文件


后面还告诉你要执行 npm install,运行执行 SET DEBUG=wxmp:* & npm start


可以查看 package.json 文件,更改了很多内容,最开始执行的文件为 ./bin/www 这个文件内编写了基本的架构

"scripts": {
    "start": "node ./bin/www"
},
"dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "jade": "~1.11.0",
    "morgan": "~1.9.1"
}

直接使用 express 创建的骨架默认使用的是 jade 模板引擎,加上 --view=pug,使用 pug 模板引擎(jade改名后就是pug,虽然差不多,但有新的当然是使用新的)

模板引擎就是相当于将静态页面,html作为模板,将其中的一些内容替换,例如 JSP 等都是模板引擎

express --view=pug

关于 pug 模板引擎可以前往官网了解 https://pugjs.org/


这里我看了下代码,大概流程是这样,bin/www文件入口文件,监听端口等都在这里面,然后将路由丢给了 app.js

app.js 内统一处理了错误,404之类的,并且处理了路由,引用了 routes文件夹下的两个js,index.js和users.js,并将其加入了路由,也就是说,后面有新的功能,比如商品,就在 routes下新建一个 shop.js,然后在 app.js 内引入并提供路由

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var shopRouter = require('./routes/shop');

var app = express();

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/shop', shopRouter);

而 routes下的文件最后都是导出一个路由(Routes),例如 index.js 的内容

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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;


public 文件夹是静态资源目录,在app.js内设置的路由,根目录

views 文件夹是模板引擎目录,同样也是app.js内设置


启动后,访问 localhost:3000,效果如下

效果

访问的是 routes/index.js,而index.js 渲染 views/index.pug 返回,所以就有了这样的效果


通过 Express 应用生成器创建应用只是众多方法中的一种。你可以不使用它,也可以修改它让它符合你的需求。



路由

这里列举一些常用的


多函数处理一个路由

next函数可以将请求传递给下一个函数

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!')
})

也可以传递数组

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])

当然,上面两种方法也可以合起来使用

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!')
})


模块化路由

可以使用 app.route() 为路由路径创建可链接的路由处理程序。由于路径是在单个位置指定的,因此创建模块化路由很有帮助,减少了冗余和拼写错误

app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (req, res) {
    res.send('Update the book')
  })

使用express.Router类创建模块化、可安装的路由处理程序。路由器实例是一个完整的中间件和路由系统;因此,它通常被称为“mini-app”。

以下示例将路由器创建为模块,在其中加载中间件功能,定义一些路由,并将路由器模块安装在主应用程序中的路径上。

在应用程序目录中创建一个名为birds.js的路由器文件,内容如下:

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

// middleware that is specific to this router
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

然后,在应用程序中加载路由器模块:

var birds = require('./birds')

// ...

app.use('/birds', birds)

这和上面说的Express项目生成器生成的骨架是差不多的


更多的可以查阅官网文档的指南或API参考手册

https://www.expressjs.com.cn/




END

本文链接:https://sdpro.top/blog/html/article/1087.html

♥ 赞助 ♥

尽管去做,或许最终的结果不尽人意,但你不付出,他不付出,那怎会进步呢?