当前位置: 首页 > 工具软件 > express > 使用案例 >

Express 的基本使用

靳富
2023-12-01

本文从安装、用法、常用 API 等方面简单介绍了 Express 的用法。

一、Express 简介

1、Express 是什么?

  • 基于 Node 平台开发的 Web 开发框架

  • 提供一系列强大的特性,帮助创建各种 Web和移动设备应用

  • 是 NodeJS 的一个模块

2、为什么使用 Express

  • 为了基于 NodeJS 开发 web 应用程序更高效

二、安装与使用

1、安装

# 新建 my-app 文件夹
mkdir my-app

cd my-app

# 初始化 package-json 文件
npm init -y

# 安装 express 依赖
npm install express -S

2、基本使用

根目录下新建 index.js 文件

const express = require('express');

const app = express();

app.listen(300, () => {
    console.dir('服务启动:http://localhost:3000/');
})

根目录下运行 node index.js,即可看到控制台打印输出。说明服务已经启动

3、路由

基本路由

基本使用方式:

// Get 请求
app.get('/', (req, res) => {
    res.send('欢迎使用 Express(GET)');
});

// POST 请求
app.post('/', (req, res) => {
    res.send('欢迎使用 Express(POST)');
});

// Put 请求
app.put('/', (req, res) => {
    res.send('欢迎使用 Express(PUT)');
});

app.delete('/', (req, res) => {
    res.send('欢迎使用 Express(DELETE)');
});


// ... 等等其他请求方式


// 路径支持正则表达式
app.get('/a+b', (req, res) => {
	res.send('类似于 /ab、/aab、/aaab 等的路径均可访问');
})

或者使用 app.route() 的方式

app.route('/')
    .get((req, res) => {
        res.send('欢迎使用 Express(GET)');
    })
    .post((req, res) => {
        res.send('欢迎使用 Express(POST)');
    })
    .put((req, res) => {
        res.send('欢迎使用 Express(PUT)');
    })
    .delete((req, res) => {
        res.send('欢迎使用 Express(DELETE)');
    })

特殊路由:app.all([path,] callback)

  • 不写 path 参数,默认是根路径
  • 请求路径(pathname)必须要全等于 path,才会执行 callback
  • 任意请求方式都会执行 callback 函数
app.all('/book', (req, res) => {
    res.send('无论任意请求方式,只要请求路径(pathname)为 /book,都会返回这句话');
})

app.use([path,] callback)

  • 不写 path 参数,默认是根路径
  • 只要请求路径(pathname)第一段为 path,就会执行 callback
  • 任意请求方式都会执行 callback 函数
app.use('/book', (req, res) => {
    res.send('无论任意请求方式,只要请求路径(pathname)第一段为 /book,都会返回这句话');
})

4、路由拆分:express.Router([options])

options 中的参数:

属性描述默认值
caseSensitive启用区分大小写。默认情况下禁用,将“/ Foo”和“/ foo”视为相同。
mergeParams保留req.params父路由器的值。如果父级和子级具有冲突的参数名称,则子级的值优先。false
strict启用严格路由。默认情况下禁用,“/ foo”和“/ foo /”由路由器处理相同。

将所有的路由都写在 index.js 文件中,不易维护而且也不安全,所以我们可以把不同路径下的路由进行拆分,分别放在不同文件下,易于维护。这个时候就会用到 express.Router();

app 类似,也可以使用 route()all()use() 等方法

编写路由文件 order.js

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

router.use((req, resp, next) => {
    console.log(new Date().toLocaleString());
    next();
})

router.get('/list', (req, resp) => {
    resp.send('订单列表');
})

router.get('/detail', (req, resp) => {
    resp.send('订单详情');
})

router.post('/submit', (req, resp) => {
    resp.send('提交订单');
})

module.exports = router;

即可在 index.js 中使用


// ...

const order = require('./order.js');

app.use('/order', order);

// ...

访问 http://localhost: 3000/order/list 或者其他 order 文件中的路径即可获取到对应返回结果

5、访问静态资源

  • api: app.use([pathname,] express.static(root,[options]))
    • pathname: 访问路径
    • root: 静态资源文件夹路径
    • options: 其他配置项,可参考这里

此时假如 public 文件是静态文件存放目录,文件夹下有 a.png 的图片文件

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

则此时访问 http://localhost: 3000/public/a.png,可以看到图片正常显示。

6、中间件的使用

app.use([path, ] (req, res, next) => { ...; next() })

  • path 参数可写可不写,不写则默认为根路径,所有访问路径均可使用;
  • 比一般回调函数多一个 next 参数,必须执行,否则不会继续向下执行。

三、常用 API

1、Application

app.listen([port [,host [,backlog]]] [,callback])

启动服务,监听端口地址

app.METHOD(path,callback [,callback ...])

路由请求方式:

  • METHOD 为各种请求方式
  • path:请求路径
  • callback:中间件及回调函数,可包含多个,出最后一个外,其他的必须在最后执行 next() ,否则不会再继续向下执行

app.path()

返回应用程序的规范路径,一个字符串。

var app = express();
var blog = express();
var blogAdmin = express();

app.use('/blog', blog);
blog.use('/admin', blogAdmin);

console.dir(app.path()); // ''
console.dir(blog.path()); // '/blog'
console.dir(blogAdmin.path()); // '/blog/admin'

app.set(name, value) / app.get(name)

  • app.set(name, value):为 name 属性设置 value,存储到服务器中
  • app.get(name):获取 name 属性对应的 value

错误处理中间件的使用

app.use((err, req, res, next) => {
	// 错误处理逻辑
	console.error(err.stack)
	res.status(500).send('Something broke!')
})

2、Request

req.params

获取请求路径中的 param

例如请求路径为:http://localhost:3000/news/2019/10

app.get('/news/:year/:month', (req, res) => {
    res.send(req.params);	// {"year":"2019","month":"10"}
})

req.query

获取 Get 请求路径中传递的查询参数

例如 Get 请求为:http://localhost:3000?name=zgd

app.get('/', (req, resp) => {
    resp.send(req.query);	// {"name": "zgd"}
});

req.body

获取 Post 请求中能够传递的查询参数

例如 Post 请求为:curl -d "name=zgd" http://localhost:3000

app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

app.post('/', (req, resp) => {
    resp.send(req.body);	// {"name": "zgd"}
});

req 获取路径

  • req.baseUrl:安装路由器实例的URL路径,不包含请求参数
  • req.path: 当前请求路径,不包含请求参数
  • req.originalUrl:院士路径,即全路径,包含请求参数
  • req.url:当前请求路径,包含请求参数
app.get('/book/list', (req, res) => {
	res.write(req.baseUrl);	// ''
	res.write(req.path);	// '/book/list'
	res.write(req.originalUrl);	// '/book/list'
});

app.use('/book', book);

// book.js

router.get('/list', (req, res) => {
	res.write(req.baseUrl);	// '/book'
	res.write(req.path);	// '/list'
	res.write(req.originalUrl);	// '/book/list'
})

其他属性

属性描述例子
req.baseUrl安装路由器实例的URL路径。用法查看这里
req.path当前请求路径用法查看这里
req.originalUrl原始 URL 请求路径。后面没有跟请求参数时,相当于是 baseUrl + path;路径后面跟了请求参数,则请求参数也包含在内/* GET /search?q=something */ console.dir(req.originalUrl); // => ‘/search?q=something’
req.cookies此属性是包含请求发送的cookie的对象。如果请求不包含cookie,则默认为{}。console.dir(req.cookies.name)
req.signedCookies同 req.cookies如果cookie已签名,必须使用这个,而不能使用 req.cookies
req.fresh指示请求是否“新鲜”。它是相反的req.stale。用法查看这里
req.stale指示请求是否“陈旧”,并且与之相反req.fresh。用法查看这里
req.hostname包含从HostHTTP标头派生的主机名。/* Host: “example.com:3000” */ console.dir(req.hostname); // => ‘example.com
req.ip包含请求的远程IP地址。console.dir(req.ip); // => ‘127.0.0.1’
req.method包含对应于该请求的HTTP方法的字符串: GET,POST,PUT,等。-
req.protocol包含请求协议字符串:http或者(对于TLS请求)https。console.dir(req.protocol); // => ‘http’
req.route包含当前匹配的路由,一个对象。用法查看这里
req.secure一个布尔属性,如果建立了TLS连接,则该属性为true。相当于:console.dir(req.protocol === ‘https’); // => true
req.subdomains请求的域名中的一组子域。/* Host: “tobi.ferrets.example.com” */ console.dir(req.subdomains); // => [‘ferrets’, ‘tobi’]
req.xhr一个布尔属性,true如果请求的X-Requested-With头字段是“XMLHttpRequest”,则表示该请求是由客户端库(如jQuery)发出的。console.dir(req.xhr); // => true

3、Response

res.end([data] [,encoding])

结束响应过程。

res.end()
res.status(404).end()

res.send([body])

res.end() 的区别:

  • 参数 body 可以是 StringBuffer,也可以是 ArrayObject
  • 会自动添加响应头:“Content-Type: text/html; charset=utf-8”
res.send(Buffer.from('whoop'))
res.send({ some: 'json' })
res.send('<p>some html</p>')

res.sendFile(path [,options] [,fn])

在指定时间发送文件到客户端。Content-Type 会根据文件的扩展名设置响应 HTTP 响应头字段。除非在 options 对象中设置了该选项,否则 path 必须是该文件的绝对路径。

app.get('/file/:name', function (req, res, next) {
  var options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  }

  var fileName = req.params.name
  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err)
    } else {
      console.log('Sent:', fileName)
    }
  })
})

res.sendStatus(statusCode)

设置响应状态码并结束响应

res.sendStatus(200) // equivalent to res.status(200).send('OK')

res.status

设置响应状态码

res.status(200).send('OK')

res.set(field [,value])

将响应的 HTTP 请求头 field 设置为 value。要一次设置多个字段,请传递一个对象作为参数。

res.set('Content-Type', 'text/plain')

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  'ETag': '12345'
})

res.get(field)

返回由指定的HTTP响应头field。该匹配不区分大小写。

res.get('Content-Type')
// => "text/plain"

res.redirect([status,] path)

重定向到指定的 URL path,具有指定的status与HTTP状态代码对应的正整数。如果未指定,则status默认为"302"。

res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')

res.json([body])

用法同 res.send();

res.append(field [,value])

将指定的内容追加 valueHTTP 响应头 field。如果尚未设置标头,则会创建具有指定值的标头。所述 value 参数可以是字符串或数组。

注意:调用res.set()after res.append()将重置先前设置的标头值。

res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>'])
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')
res.append('Warning', '199 Miscellaneous warning')

res.cookie(name,value [, options])

设置 cookie 中的 name 属性为 value

res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true })
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })

res.clearCookie(name [,options])

清除 cookie 中对应的 name 属性

res.cookie('name', 'tobi', { path: '/admin' })
res.clearCookie('name', { path: '/admin' })

Router

与 app 中使用 路由的方式类似:

  • router.Method(path, callback)

  • router.use()

  • router.all()

  • router.route()


四、参考文档

 类似资料: