Express基础知识

Express基础知识

路由基础

路由是指确定应用程序如何响应客户端对特定端点的请求,该特定断点是URL和特定的HTTP请求方法(GET,POST)每个路由可以具有一个或多个处理程序函数,这些函数在匹配该路由时执行。路由定义采用以下结构:

app.METHOD(PATH,HANDLER)

  • App是Experss实例
  • METHOD是小写的HTTP请求方法
  • PATH是服务器上的路径
  • HANDLER是当前路由匹配时执行的功能

app.post('/',function (req,res){
    res.send("hello,post")
})

请求对象

Express应用使用路由回调函数的参数,requestresponse对象来处理请求和响应的数据

app.get('/',function(req,res){
    console.log(req,url)    //请求地址
    console.log(req.method) //请求方法
    console.log(req.headers)    //请求头
    console.log("请求参数:",req.query)
})

响应对象

使用node.js原生的发送数据的方法

//结束响应后,发送数据
res.end("hello,world")
​
//直接发送数据
res.write("hello")
​
//使用express中的send方法发送数据
res.send({foo:"bar"})   //发送对象,实际发送一个json字符串
res.status(404).send("sorry")   //发送状态码和内容
​
//发送cookie
res.cookie('foo','bar') //name  value
res.cookie('a',123)

案例

通过该案例创建一个简单的CRUD接口服务,从而掌握Express的基本用法。

需求:实现对任务清单的CRUD接口服务

  • 查询任务列表:get/todos
  • 根据ID查询单个任务:get/todos/:id
  • 添加任务:post/todos
  • 修改任务:PATCH/todos
  • 删除任务:DELETE/todos/:id

路由设计

中间件

中间件

Express的最大特色,也是最重要的一个设计,就是中间件。一个Express应用,就是由许许多多的中间件来完成的。 不去修改自己的代码,以此来扩展或者处理一些功能

在不能干扰原来的流程,同时增加新的工序

AOP面向切面编程

  • 将日志记录,性能统计,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码
  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率和可维护性。
  • 就是在现有代码程序中,在程序声明周期或者横向流程中,加入/减去一个或多个功能,不影响原有的功能

Express中的中间件

在Express中,中间件就是一个可以访问请求对象、响应对象和调用next方法的一个函数

在中间件函数中可以执行以下任何任务:

  • 修改任何代码
  • 修改request或者response响应对象
  • 结束请求响应周期
  • 调用下一个中间件

//使用案例
const express = require('express')
const app = express()
require('dotenv').config()
const port = process.env.PORT || 5000
​
//req:请求对象
//res:响应对象
//next:下一个中间件
//此中间件对于任何请求都会响应,然后在匹配对应的请求类型执行
//因此中间件函数需要放在最上面,有顺序性
app.use((req,res,next)=>{
   console.log(req.method,req.url,Date.now())
   //交出执行权,往后继续匹配执行
   next()
})
​
app.get('/' , (req , res)=>{
​
   res.send('hello from simple server :)')
​
})
​
​
app.listen(port , ()=> console.log('> Server is up and running on port : ' + port))

注意:如果当前的中间件功能没有结束请求-响应周期,则必须调用next()将控制权传递给下一个中间件功能。否则,该请求将会被挂起

应用程序级别中间件

//不关心请求路径:
app.use(function(req,res,next){
    console.log("time:",Date.now())
    next()
})
​
​
//限定请求路径:
app.use('./user/:id',function(req,res,next){
    console.log("Requset type:",req.method)
    next()
})
​
​
//限定请求路径+请求方法:
app.get('/user/:id',funtion(req,res,next){
    res.send("USER")        
})
​
//多个处理函数,两个函数都会被执行,处理函数可以有多个 
app.use('/user/:id',function(req,res,next){
    console.log("Request URL",req.originalUrl)
    next()
},function(req,res,next){
    console.log('Request Type:',req.method)
    next()
})

要从路由器中间件堆栈中跳过其余中间,请调用`next('route')将控制权传递给下一条路由。

注意:next(‘route’)仅在使用app.METHOD()或者router.METHOD()函数加载的中间件函数中有效

中间件也可以在数组中声明为可重用。此示例显示了一个带有中间件子堆栈的数组,该子堆栈处理对/user/:id路径的GET请求

const express = require('express')
const app = express()
require('dotenv').config()
const port = process.env.PORT || 5000
​
function logOriginalUrl(req,res,next){
   console.log("Request URL:",req.originalUrl)
   next()
}
​
function logMethod(req,res,next){
   console.log("Request Type:",req.method)
   next()
}
​
var logStuff = [logOriginalUrl,logMethod]
​
app.get('/' ,logStuff, (req , res,next)=>{
​
   res.send('hello from simple server :)')
​
})
​
​
app.listen(port , ()=> console.log('> Server is up and running on port : ' + port))

错误处理中间件

已与其他中间件函数相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数(特别是使用签名(err,req,res,next))之外:

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

错误处理中间件始终带有四个参数。您必须提供四个参数以将其标识为错误处理中间件函数,即使不需要使用改next对象,也必须指定他以维护签名,否则,该next对象将被解释为常规中间件

app.use((err,req,res,next)=>{
    res.status(500).json({
        error:err.message
    })
})

如果将任何内容传递给该next()函数(字符串除外‘route’),Express都会将当前请求视为错误,并且将跳过所有剩余的非错误处理路由和中间件函数。

app.get('/gets' , (req , res,next)=>{
   fs.readFile("./db123.json",(err,data)=>{
      //发现错误,则交给错误处理中间件处理
      if (err) next(err)
      res.send(data)
   })
})
​
//最后挂载错误处理中间件
//错误处理中间件一定是四个参数
app.use((err,req,res,next)=>{
   res.status(500).json({
      err:err.message
   })
})

通常会在所有路由之后配置处理404的内容,请求会从上到下依次匹配

//在所有的路由后面,处理404的相关请求
app.use((req,res,next)=>{
    res.status(404).send("404 not Found")
})

路由方法

路由方法是从HTTP方法之一派生的,并附加到express该类的实例,

有一种特殊的路由方法,app.all()用于为所有HTTP请求方法的路径加载中间件功能。例如,无论是使用GET,POST,PUT,DELETE还是http模块支持的任何其他HTTP请求方法,都会对路由/secret的请求执行以下处理程序

app.all('/secret',function(req,res,next){
    console.log("Accessing the secret section...")
    next()
})

路由路径

//此路由路径会将请求匹配到/about
app.get('/about',function(req,res){
    res.send('about')
})
​
//此路由路径会将请求匹配到/random.text
app.get('/random.text',function(req,res){
    res.send("random.text")
})
​
//此路由路径将acd和匹配abcd
app.get('/ab?cd',function(req,res){
    res.send('ab?cd')
})
​
//这条路线的路径将会匹配abcd、abbcd、abbbcd
app.get('/ab+cd',function(req,res){
    res.send("ab+cd")
})
​
//基于正则表达式的路由路径
//匹配其中带有"a"的任何内容
app.get('/a/',function(req,res){
    res.send("/a/")
})
​
//匹配butterfly和dragonfly
app.get('/.*fly$/',function(req,res){
    res.send('/.*fly$/')
})

路由路径参数

路由参数被命名为URL段,用于捕获URL中在其位置处指定的值,捕获的值将填充到req.params对象中,并将路径中指定的route参数的名称作为其各自的键

app.get('/users/:id',(req,res)=>{
    console.log(req.params.id)
    res.send("get/users/:id")
})

路径参数的名称必须由“文字字符”[[A-Za-z0-9_]]组成。由于连字符(-)和点(.)是按字面解释的,因此可以将它们与路由参数一起使用,以实现有用的目的

Route path:/flights/:from:to
Request URL:http://locoalhost:3000/flights/LAX-SFO
req.params:{"from":'LAX','to':"SFO"}

要更好的控制可以由route参数匹配的确切字符串,可以在括号(())后面附加一个正则表达式:

Route path:/user/:userID(\d+)
Request URL:http://localhost:3000/user/42
req.params:{"userID":"42"}Route path:/user/:userID(\d+)
Request URL:http://localhost:3000/user/42
req.params:{"userID":"42"}

由于正则表达式通常是文字字符串的一部分,因此请确保\使用其他反斜杠对所有字符进行转义,例如\\d+。在Express4.x中,不以常规方式解释正则表达式中的*字符

路由处理程序

路由处理程序可以采用函数,函数数组或二者组合的形式

//回调数组,同时执行多个回调函数
var a = function(req,res,next){
    console.log('a')
    next()
}
​
var b = function(req,res,next){
    console.log('b')
    next()
}
​
var c = function(req,res,next){
    console.log('c')
    next()
}
​
app.get('/example/c',[a,b,c])

res下表中相应对象()上的方法可以将响应发送到客户端,并终止请求-响应周期,如果没有从路由处理程序调用这些方法,则客户端请求将被挂起

方法描述
res.download()提示要下载的文件
res.end()结束响应过程
res.json()发送JSON相应
res.jsonp()发送带有JSONP支持的JSO相应
res.redirect()重定向请求
res.render()渲染视图模板
res.send()发送各种类型的相应
res.sendFile()将文件作为八位字节流发送
res.sendStatus()设置响应状态代码,并将其字符串表示形式发送为相应正文

app.route()

您可以使用来为路由路径创建可链接的路由处理程序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")
    })

快速路由器

在app目录中创建一个快速路由器

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("Birds home page")
})
​
router.get('/about',function(req,res){
    res.send("About birds")
})
​
module.exports = router

在应用程序中加载路由器模块

var birds = require('./birds')
app.use('/birds',birds)

© 版权声明
THE END
喜欢就支持以下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容