express框架与中间件

241 阅读8分钟

express

Express是目前流行的基于Node.js运行环境的Web应用程序开发框架,它简洁且灵活,为Web应用程序提供了强大的功能。Express提供了一个轻量级模块,类似于jQuery(封装的工具库),它把Node.js的HTTP模块的功能封装在一个简单易用的接口中,用于扩展HTTP模块的功能,能够轻松地处理服务器的路由、响应、Cookie和HTTP请求的状态。

利用Express搭建Web服务器

利用Express搭建Web服务器的基本步骤:

  1. 引入express模块;
  2. 调用express()方法创建服务器对象;
  3. 定义路由;
  4. 调用listen()方法监听端口。

a.在src下创建server.js文件

// 引入express模块
const express = require("express");
// 创建Web服务器对象
const app = express();
// 定义GET路由,接收/处理客户端的GET请求
app.get("/", (req, res) => {
    // 对客户端做出响应,send()方法会根据内容的类型自动设置请求头
    res.end("hello express");
})
// 监听3000端口
app.listen(3000);

b.在终端启动

node server.js

Express中间件

Express通过中间件接收客户端发来的请求,并对请求做出响应,也可以将请求交给下一个中间件继续处理。

Express中间件指业务流程中的中间处理环节,可以把中间件理解为客户端请求的一系列方法。如果把请求比作水流,那么中间件就是阀门,阀门可以控制水流是否继续向下流动,也可以在当前阀门处对水流进行排污处理,处理完成后再继续向下流动。 中间件机制可以实现哪些应用?

路由保护:当客户端访问登录页面时,可以先使用中间件判断用户的登录状态,如果用户未登录,则拦截请求,直接响应提示信息,并禁止用户跳转到登录页面。
网站维护公告:在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,并提示网站正在维护中。
自定义404页面:在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,并提示404页面错误信息。

中间件主要由中间件方法请求处理函数这两个部分构成。中间件方法由Express 提供,负责拦截请求。请求处理函数由开发人员编写,负责处理请求。

常用中间件方法

app.get('请求路径', '请求处理函数');  // 接收并处理GET请求
app.post('请求路径', '请求处理函数'); // 接收并处理POST请求
app.use('请求路径', '请求处理函数'); // 接收并处理所有请求

app.get

当客户端向服务器端发送GET请求时,app.get()中间件方法会拦截GET请求,并通过app.get()中间件中的请求处理函数对GET请求进行处理。 同一个请求路径可以设置多个中间件,表示对同一个路径的请求进行多次处理,默认情况下Express会从上到下依次匹配中间件。

示例:使用app.get()定义中间件并返回req.name的值

// 引入express模块
const express = require("express");
// 创建Web服务器对象
const app = express();
// 定义中间件
app.get("/request", (req, res, next) => {
    req.name = "橘猫吃不胖";
    next(); // 启动下一个中间件
})
app.get("/request", (req, res) => {
    res.end(req.name);
})
// 监听3000端口
app.listen(3000);

启动服务器,在浏览器中输入:localhost:3000/request,即可返回对应值

app.post 同理

app.use()中间件

通过app.use()定义的中间件既可以处理GET请求又可以处理POST请求。在多个app.use()设置了相同请求路径的情况下,服务器都会接收请求并进行处理。

示例:使用app.use()定义中间件,处理GET和SET请求

const express = require("express");
const app = express();
// 定义中间件
app.use("/form", ((req, res, next) => {
    req.name = "橘猫吃不胖";
    next();
}))
app.use("/form", (req, res) => {
    res.end(req.name);
})
// 监听3000端口
app.listen(3000);

app.use()方法的请求路径参数可以省略,省略时表示不指定路径,所有的请求都会被处理。

利用express.static()中间件处理静态资源

express.static()是Express框架提供的内置中间件,它接收静态资源访问目录作为参数。

使用express.static()内置中间件可以方便地托管静态文件,在客户端访问服务器的静态资源时使用。常用的静态资源有图片、CSS、JavaScript和HTML文件等。

express.static()参数是静态资源所在的目录,它需要作为app.use()的参数使用,示例代码如下:

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

利用中间件处理错误

在程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败、数据库连接失败等。这时候就需要用到错误处理中间件了,用它来集中处理错误。
示例:进行文件读取操作,返回文件读取失败的错误信息

const express = require("express");
const fs = require("fs");
const app = express();
// 使用app.get()中间件进行文件读取操作
app.get("/readFile", (req, res, next) => {
    // 读取a.txt文件
    fs.readFile("./a.txt", "utf8", (err, result) => {
        if (err !== null) { // 如果错误信息不为空,将该信息传给下一个中间件
            next(err);
        } else {
            res.send(result);
        }
    })
})
// 错误处理中间件
app.use((err, req, res, next) => {
    // 设置响应状态码为500,并发送错误信息
    res.status(500).send(err.message);
})
app.listen(3000);

Express模块化路由

虽然可以使用app.get()方法和app.post()方法来实现简单的路由功能,但没有对路由进行模块化管理。在实际的项目开发中,不推荐将不同功能的路由都混在一起存放在一个文件中,因为随着路由的种类越来越多,管理起来会非常麻烦。为了方便路由的管理,通过express.Router()实现模块化路由管理。

express.Router()方法用于创建路由对象route,然后使用route.get()和route.post()来注册当前模块路由对象下的二级路由,这就是一个简单的模块化路由。

express.Router()方法定义route对象的示例代码如下:
定义二级路由:

const express = require("express");
const app = express();
// 定义route对象
const route = express.Router();
// 在route路由下创建二级路由
route.get("/index", (req, res) => {
    res.send("欢迎来到主页");
})
// app.use()注册route模块化路由
app.use("/route", route);
// 监听3000端口
app.listen(3000);

结果如下

image.png

express.Router()方法可以将同一类路由放在一个单独的文件中,每个单独的文件表示一个单独的模块,通过文件的名称来区分路由的功能。

home.js:

const express = require("express");
// 定义home对象
const home = express.Router();
// 在home模块化路由下创建路由
home.get("/index", (req, res) => {
    res.send("欢迎来到博客前台");
})
// 将home导出
module.exports = home;

amin.js:

const express = require("express");
const admin = express.Router();
// 在admin模块化路由下创建路由
admin.get("/index", (req, res) => {
    res.send("欢迎来到博客后台");
})
// 导出admin
module.exports = admin;

module.js:

const express = require("express");
const home = require("./home"); // 导入home
const admin = require("./admin"); // 导入admin
const app = express();
// 注册home模块化路由
app.use("/home", home);
app.use("/admin", admin);
app.listen(3000);

Express接收请求参数

get:
Express框架中的req.query用于获取GET请求参数,框架内部会将GET参数转换为对象并返回。利用req.query获取GET请求参数的示例代码如下。

const express = require("express");
const app = express();
app.get("/query", (req, res) => {
    // 获取get请求参数
    res.send(req.query);
})
app.listen(3000);

启动服务器,在浏览器中输入http://localhost:3000/query?name=zhangsan&age=12, 其中http://localhost:3000/query 表示服务器的请求地址,“?”之后是请求的参数,这部分可以自己编写,参数与参数之间使用“&”隔开,访问结果如下:

image.png\

post:
Express中的req.body用于获取POST请求参数,需要借助第三方body-parser模块将POST参数转换为对象形式。利用req获取POST请求参数的示例代码如下。

npm install body-parser@1.18.3 --save

const express = require("express");
const bodyParsee = require("body-parser");
const app = express();
app.use(bodyParsee.urlencoded({ extended: false }));
app.post("/query", (req, res) => {
    // 获取post请求参数
    res.send(req.body);
})
app.listen(3000);

    <form action="http://localhost:3000/query" method="post">
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="password" name="password">
        <br>
        <input type="submit" value="提交">
    </form>

image.png image.png

接收路由参数

通常情况下,把写在路由请求路径中的参数称为路由参数。通过请求路径传递参数,可以让路由代码看起来非常美观,且请求参数会被清晰地展示出来。

const express = require("express");
const app = express();
app.get("/find/:id", (req, res) => {
    res.send(req.params);
})
app.listen(3000);

cors跨域配置
CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定 浏览器是否阻止前端 JS 代码跨域获取资源。
浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头, 就可以解除浏览器端的跨域访问限制。

CORS 的注意事项
① CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
② CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服 务端接口(例如:IE10+、Chrome4+、FireFox3.5+)

app.get('./cross',(req,res)=>{
 // 设置请求头为允许跨域,其中,'*'的值指定了允许访问该资源的外域 URL。
    res.header('Access-Control-Allow-Origin', '*');
    // 设置服务器支持的所有头信息字段
    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild, sessionToken');
    // 设置服务器支持的所有跨域请求的方法
    res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');

jsonP后端不需要响应头配置

通用配置:

//创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
// 如果URL即请求行的第二段内容路径为/server,则执行该回调函数中的代码
// 并且由response做出响应
app.all("/server",(request,response)=>{
    // 设置响应头            头的名字                   值
    // 这里是设置允许跨域的意思
    response.setHeader("Access-Control-Allow-Origin","*")

    response.setHeader("Access-Control-Allow-Headers","*")

    //设置响应体
    response.send("HELLO AJAX POST-2")
});