f10@t's blog

express学习(一)-基于NodeJS的Web框架

字数统计: 2.1k阅读时长: 9 min
2021/07/14 1

哎前端,自己就没踏踏实实学过前端的玩意儿,嚷嚷着要学vue要学angular,结果都是接触个皮毛,完后屁颠屁颠回去学Java了...,今天项目需要,学学express,一个基于NodeJS的快速开发web应用的框架(属于Nodejs的后端框架),目的是学会基本使用。vue这些前端框架回头专门记录学学(我也好想会做好看的前端呜呜呜)

express-title

入门demo

首先新建一个目录然后npm init来初始化这个工程,主要是生成package.json这个依赖管理文件,然后我们npm install express --save来安装express,可以自定义入口为app.js(一般的习惯),然后代码如下:

1
2
3
4
5
6
7
8
9
10
11
const express = require('express')
const app = express()
const port = 9999

app.get('/', (req, res)=>{
res.send("express!")
})

app.listen(port, ()=>{
console.log(`express is listening on port: ${port}`);
})

然后node app.js就可以启动应用了,访问根目录就可以看到我们绑定的路由以及对应的handler函数了。

当然一般可以使用express-generator来完成这个工作,安装:npm install -g express-generator。然后就可以新建工程了,比如:

image-20210714122920878

然后在其目录下npm install安装依赖就可以了。最后的目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── app.js
├── bin
└──www
├── node_modules
├── public
│ ├─images
│ ├─javascripts
│ └─stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug

如果你要在视图层使用html作为模板文件的话,需要在app.js中修改他的默认模板引擎,并且要安装ejs模块(npm install ejs --save),修改后的代码如下:

1
2
3
4
5
// view engine setup
// 修改视图层引擎为html
app.set('views', path.join(__dirname, 'views'));
app.engine('.html', require('ejs').__express)
app.set('view engine', 'html');

这样就可以使用html文件了。

路由设置

首先我们来确立几个基本概念,就照着上面的demo(这里再粘贴一下):

1
2
3
const express = require('express')
const app = express()
const port = 9999

首先app这个变量,它是express的一个实例,下面我们定义了一条路由规则:

1
2
3
app.get('/', (req, res)=>{
res.send("express!")
})

定义路由规则的语法是这样的:app.METHOD(URL, HANDLER),其中Handler由请求和响应组成,比如上面的代码中就用响应变量res回执了一个字符串。

URL路径

官方给了几个例子,分别对应不同的HTTP请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 请求根
app.get('/', function (req, res) {
res.send('root')
})

// 请求/about页面
app.get('/about', function (req, res) {
res.send('about')
})

// 请求/random.text
app.get('/random.text', function (req, res) {
res.send('random.text')
})

// 附带规则
// 请求abd或者abcd,b?意思就是有没有?前面这个b都可以
app.get('/ab?cd', function (req, res) {
res.send('ab?cd')
})

// 类似上面,意思中间可以是一堆b,比如abbbbcd
app.get('/ab+cd', function (req, res) {
res.send('ab+cd')
})

// 和上面一个意思,只不过中间可以不是b,比如abq345281cd
app.get('/ab*cd', function (req, res) {
res.send('ab*cd')
})

// 和ab?cd一个意思,即cd这俩可有可无=>abe或者abcde
app.get('/ab(cd)?e', function (req, res) {
res.send('ab(cd)?e')
})

// 正则
// 只要带个a就可以访问
app.get(/a/, function (req, res) {
res.send('/a/')
})

// 以fly结尾就可以,比如butterfly
app.get(/.*fly$/, function (req, res) {
res.send('/.*fly$/')
})

路由参数

当然我们也要处理用户传递的数据的,老规矩,get的参数或者post的参数呗。先看get的,处理方法类似go语言:

1
2
3
app.get('/users/:userId/books/:bookId', function (req, res) {
res.send(req.params)
})

上面这个url传递过来后,就可以拿到userId和bookId这两个变量

当然,你也可以用这种骚气一点的处理方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 带个'-'来匹配get的参数
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }

// 同理,也可以用'.'来分隔匹配参数
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }

// 当然,还有正则
Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}

处理程序(Handler)

上面demo的例子只有一个handler函数,实际上也可以组合使用多个handler函数进行跳转,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const express = require('express')
const app = express()
const port = 9999

app.get('/test', (req, res, next)=>{
console.log("this request will be handled by next!")
next() // 交由下一个handler处理
}, (req, res)=> {
res.send("ok")
})

app.listen(port, ()=>{
console.log(`express is listening on port: ${port}`);
})

我们就可以在控制台看到跳转,以及最终回显的结果

image-20210714142325049
image-20210714142212956

当然你也可以单独独立定义函数,然后组成数组,交由app来进行管理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require('express')
const app = express()
const port = 9999


var func1 = function(req, res, next) {
console.log("this is func1")
next()
}

var func2 = function(req, res, next) {
console.log("this is func2")
next()
}

var func3 = function(req, res, next) {
res.send("hello!")
}

app.get('/test', [func1, func2, func3])

app.listen(port, ()=>{
console.log(`express is listening on port: ${port}`);
})
image-20210714142724475
image-20210714142731697

上面的例子是都绑定到了get方法,此外,你也可以将这些方法绑定到不同的方法里:

1
2
3
4
5
6
7
8
9
10
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')
})

比如上面的代码就把不同的处理程序绑定到了/book路径下的不同请求方法中。

响应可执行的方法(Method)

如果以下的方法没有被调用的话,服务端和客户端的通信将一直挂起。比如我们demo里的send方法就可以结束一次请求-响应的循环。

Method Description
res.download() Prompt a file to be downloaded.
res.end() End the response process.
res.json() Send a JSON response.
res.jsonp() Send a JSON response with JSONP support.
res.redirect() Redirect a request.
res.render() Render a view template.
res.send() Send a response of various types.
res.sendFile() Send a file as an octet stream.
res.sendStatus() Set the response status code and send its string representation as the response body.

express.Router()

定义Handler的方式可能有点乱,还有一种模块化的管理路由的方式就是使用express.Router,我们单独在一个文件中写路由规则,然后导出这个模块使用即可。一个例子如下:

首先我们使用express初始化后的工程,在routers/index.js文件中写我们的规则:

1
2
3
4
5
6
7
8
9
var express = require('express');
var router = express.Router();

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

module.exports = router;

然后 views下写我们的视图层文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Hello Express</title>
<link href="stylesheets/style.css" rel="stylesheet">
</head>
<body>
<h2>Hello Express</h2>
</body>

</html>

默认express应用的监听端口是3000,这里使用npm start app.js来启动我们的应用,其本质就是调用了bin目录下的www脚本,其实还是node调用,只不过定义了端口等信息。然后访问网页就可以看到内容了(304是因为我访问过了):

image-20210714171804025

静态资源注册

比如图片这些东西直接使用express自带的static函数就可以注册了,例子如下:

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

上面的代码就把public目录下的所有静态资源都开放给外界使用,比如http://localhost:3000/css/style.css就可以被访问到。如果你还有其他目录的资源想要开放,那么也是使用上面的函数进行注册就可以了。

此外,你也可以将资源挂在到一个虚拟的路径下面,比如:

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

那么上面那个css文件的访问路径就变成了http://localhost:3000/static/css/style.css。上面这种注册方式是因为你的注册语句是写在app.js里面的,如果说你写到其他文件里,express是找不到这个public文件夹的,所以建议这样注册,其中__dirname就是你的项目根目录。

1
app.use('/static', express.static(path.join(__dirname, 'public')))

参考学习

Express - 基于 Node.js 平台的 web 应用开发框架 - Express 中文文档 | Express 中文网 (expressjs.com.cn)

Powered By Valine
v1.5.2
CATALOG
  1. 1. 入门demo
  2. 2. 路由设置
  3. 3. 静态资源注册
  4. 4. 参考学习