本文共 8541 字,大约阅读时间需要 28 分钟。
Express 可以创建各种 Web 应用,可以使用 npm install express
下载。
该框架简化了 Node.js 的网站配置,具有以下特性:
Express 提供了 get 和 post 方法用来区分 get 和 post 请求。使用 send 方法向客户端响应数据。
Express 可以接收客户端发送来的数据,可以进行响应,也可以将请求交给下一个中间件进行处理。
中间件可以对客户端发来的请求进行拦截,减少服务器的带宽。
中间件就是一堆方法,例如上面提供了get 和 post 方法,语法结构如下:
app.get('/', (req, res, next)=>{})app.post('/', (req, res, next)=>{})
上述语法结构中如果调用了回调函数中的 next()
方法,表示将本次请求交给下一个中间件进行处理。
const express = require('express')const app = express()const port = 3000app.get('/', (req, res, next) => { req.str = '这是第一个中间件设置的变量'; next()})app.get('/', (req, res) => { res.send(req.str)})app.listen(port, () => console.log(`Example app listening on port port!`))
浏览器地址栏中输入 localhost:3000
页面显示如下:
这是第一个中间件设置的变量
express 对象的 get 和 post 方法分别接收 get 和 post 请求,如果想要接收所有的请求方式需要使用 use 方法。
use 方法可以直接传入一个回调函数,将匹配所有请求路径上的任何请求。也可以将第一个参数设置为请求地址,将匹配该地址上的所有请求。
如下代码所示:const express = require('express')const app = express()const port = 3000// 匹配该网站所有的请求app.use((req ,res, next)=>{ // 当访问 localhost:3000 会执行 log console.log('this is use function.'); // 继续向下匹配 next()})app.use('/index', (req,res,next)=>{ console.log('this is index page.'); next();})app.get('/', (req, res) => { // 响应 hello world res.send('Hello World!')})app.listen(port, () => console.log(`Example app listening on port port!`))
在浏览器地址栏中输入,localhost:3000
,终端结果:
this is use function.
在浏览器地址栏中输入,localhost:3000/index
,终端结果:
this is use function.this is index page.
中间件可以用来做路由保护,当用户访问页面时,可以使用中间件判断用户的登陆,如果用户登陆了才调用 next()
方法;如果没有登陆则拦截请求,直接向客户端返回数据。
const express = require('express')const app = express()const port = 3000// 用户是否登陆let flag = trueapp.use((req,res,next)=>{ if (flag) { next(); } res.send('请登录')})app.get('/', (req, res) => res.send('Hello World!'))app.listen(port, () => console.log(`Example app listening on port port!`))
当将第 6 行代码中的 flag 修改为 false 时,页面显示请登录,如果修改为 true,正常显示 hello world。
中间件还可以进行网站维护公告,例如12点-15点之间不允许访问该网站,需要在所有中间件之前定义一个 use 方法,并且不能调用 next 方法。如下代码所示:
const express = require('express')const app = express()const port = 3000app.use((req,res,next)=>{ res.send('当前网站正在维护')})app.get('index', (req,res,next)=>{ res.send('欢迎来到首页')})app.get('/', (req, res) => res.send('Hello World!'))app.listen(port, () => console.log(`Example app listening on port port!`))
在浏览器地址栏中输入 localhost:3000
无论访问该网站下的哪个页面都会出现 当前网站正在维护
使用 use 方法还可以自定义 404 页面,当用户输入一个不存在的页面时,在所有中间件最后加上 use 方法,会接收之前中间件匹配不到的请求。
如下代码所示:const express = require('express')const app = express()const port = 3000app.get('/index',(req,res,next)=>{ res.send('欢迎来到首页')})app.use((req,res,next)=>{ res.status(404) .send('页面不存在')})app.get('/', (req, res) => res.send('Hello World!'))app.listen(port, () => console.log(`Example app listening on port port!`))
当输入一个不存在的路由时,页面显示 页面不存在
,状态码为 404
当服务器读取本地文件时,经常会出现一些错误,如果发生了错误需要使用异常处理中间件来处理错误。
如下代码所示:const express = require('express')const app = express()const port = 3000app.get('/', (req,res,next)=>{ throw new Error('服务器发生异常')})app.use((err,req,res,next)=>{ res.status(500) .send(err.message)})app.listen(port, () => console.log(`Example app listening on port port!`))
上面方法仅仅用来捕获同步 API 的错误,异步 API 错误的捕获需要借助 next 方法,如下代码所示:
const express = require('express')var fs = require('fs');const app = express()const port = 3000app.get('/', (req, res, next) => { // 异步 API 读取 xxx.js 文件,如果此文件存在那么会将文件中的内容返回到页面 fs.readFile('./01_express初探.js', function (err, data) { if (err){ // 如果不存在会将错误赋值为 next 的参数,向下执行 next(err) }else{ res.send(data.toString()) } });})app.use((err, req, res, next)=>{ if (err) { res.status(500).send(err.message) }else{ res.send('hello world!') }})app.listen(port, () => console.log(`Example app listening on port port!`))
如果需要捕获异步函数中的异常,需要使用 try...catch
语句。将 catch 语句中的异常对象放入 next 方法的参数中。
通常一个 /
请求路径下具有子级请求路径,多个路径写在一起代码较为杂乱,不宜维护。可以使用 express 对象的 Router 方法,为网站创建路由对象。步骤如下:
如下代码所示:
const express = require('express')const app = express()const port = 3000// Router 路由对象,使用该对象可以创建一级路由const home = express.Router()// 为 home 一级对象分配请求地址,一旦访问 localhost:3000/home 就找到 home 对象app.use('/home',home)// 为一级路由设置请求路径当访问 home/index 时触发home.use('/index', (req,res,next)=>{ res.send('欢迎来到博客首页')})app.get('/', (req, res) => res.send('Hello World!'))app.listen(port, () => console.log(`Example app listening on port port!`))
在浏览器地址栏输入:localhost:3000/home/index
页面显示 欢迎来到博客首页
。
可以综合之前所学模块化来实现不同路由分文件存储,如下代码所示:
admin.js 文件:
const express = require('express')const admin = express.Router()admin.use('/index', (req,res,next)=>{ res.send('欢迎来到管理页面')})module.exports = admin
home.js 文件:
const express = require('express')const home = express.Router()home.use('/index', (req, res, next) => { res.send('欢迎来到博客首页')})module.exports = home
app.js 文件:
const express = require('express')const app = express()const port = 3000// 引入另外两个模块的路由对象const admin = require('./route/admin')const home = require('./route/home')// 为引入的模块对象分配请求路径app.use('/admin', admin)app.use('/home', home)app.get('/', (req, res) => res.send('Hello World!'))app.listen(port, () => console.log(`Example app listening on port port!`))
Express 提供了 req.query
方法,可以获取 get 请求方式中携带的参数,返回值为对象的形式。
const express = require('express')const app = express()const port = 3000app.get('/', (req, res) => { console.log(req.query); res.send('Hello World!')})app.listen(port, () => console.log(`Example app listening on port port!`))
代码第 6 行,将地址栏中输入的 GET 请求参数在控制台中输出,并且返回值为对象形式。
如果在浏览器地址栏中输入:localhost:3000?msg=asdasd
终端打印结果为:{ msg: 'asdasd' }
POST 参数的获取需要借助 body-parser
第三方模块,npm install body-parser
即可下载。
const express = require('express')const body_parser = require('body-parser')const app = express()const port = 3000// 使用 use 方法拦截所有请求// 在 use 方法内部使用 body-parser.urlencoded() 方法将 POST 参数添加到 req 对象的 body 属性上,然后调用 next 方法,让下一个路由处理app.use(body_parser.urlencoded({ extended: false}))app.post('/add',(req,res,next)=>{ console.log(req.body);})app.listen(port, () => console.log(`Example app listening on port port!`))
第 9 行代码中的 {extended: false}
将该属性置为 false,表示使用 queryString 处理请求参数;如果置为 true,表示使用第三方模块 qs 处理请求参数。
在定义请求路径时,可以使用 /:
的形式指定路由参数,当指定路由参数之后对该地址发请求时如果没有输入该参数则找不到该页面。使用 Express 框架提供的 req.params
属性可以获取当前路由下传递的参数,返回对象格式。
const express = require('express')const app = express()const port = 3000// 使用 /: 的形式可以为请求路径之后定义路由参数,// 路由参数可以使用 req.params 获取,返回对象格式// 如果在访问时没有指定路由参数,会找不到该页面app.get('/index/:id/:name', (req, res) => { res.send(req.params)})app.listen(port, () => console.log(`Example app listening on port port!`))
在浏览器中输入 localhost:3000/index/12/hello
结果如下:
{ "id":"12","name":"hello"}
Express 实现静态资源访问,相对于原生 Node.js 来说变得非常简单,只需要在 use()
方法中调用 express.static()
方法即可,然后在 static
方法中传入静态资源所在的目录,可以在浏览器中访问静态资源。
const express = require('express')const app = express()const port = 3000app.use(express.static('public'))app.listen(port, () => console.log(`Example app listening on port port!`))
在浏览器地址栏中输入 localhost:3000/index.html
这样当前目录下的 public 文件夹中的 index.html 被加载到页面中。
在调用 static 方法之前,还可以指定虚拟路径,可以将上述代码中的 use 方法改成下面这样:
app.use('desc', express.static('public'))
在访问时,需要输入 localhost:3000/desc/index.html
才会访问到 index.html 页面。
Express 中依然使用 art-template
模板引擎,为了更好的配合 Express
框架, art-template
官方提供了 express-art-template
模板引擎。
如果想要使用该模板引擎需要同时下载 art-template
和 express-art-template
。
在使用模板引擎之前需要进行配置,首先需要告诉 Express
使用的哪一款模板引擎,然后需要设置模板存放的目录,需要设置默认后缀。
向 Express
声明使用的模板引擎需要使用 engine
方法,第一个参数为模板文件的后缀,第二个参数为使用的模板引擎;
set
方法设置。如下代码所示: const express = require('express')const path = require('path')const app = express()const port = 3000// 使用 engine 方法向 express 声明使用的模板引擎和模板文件后缀名app.engine('art', require('express-art-template'))// 使用 set 方法告诉 express 模板文件的路径app.set('views', path.join(__dirname, 'views'))// 告诉 express 默认模板文件的后缀名app.set('view engine', 'art')app.get('/', (req, res) => { // 使用 render 方法渲染模板,第一个参数为模板的名称(路径) // 第二个参数为对象形式,要为模板中变量填充的数据 res.render('index', { msg: '这是index模板' })})app.listen(port, () => console.log(`Example app listening on port port!`))
在地址栏中输入:localhost:3000
页面响应:这是index模板
。
可以为 服务器对象的 locals
属性添加新属性来设置模板中的共享数据,也就是说在 locals
属性下定义的数据可以被所有模板使用。
转载地址:http://cvjv.baihongyu.com/