Express
什么是express?
Express是基于Node.js平台,快速,开放,极简的Web框架。 其作用与Node.js内置的http模块类似,都是用来创建Web服务器的。 Express本质上就是一个npm上的第三方包,提供了快速搭建Web服务器的简便方法。 Express中文官网:https://www.expressjs.com.cn/
Express的优势
在没有express的情况下,仍然可以使用Node.js内置的http模块创建Web服务器,而express是基于内置http模块进一步封装出来的,能够极大的提高开发效率。express与http内置模块的关系就好比Web API与Jquery之间的关系,后者是基于前者进一步封装出来的。
Express的基本使用
安装
npm install express@4.17.1
创建最基本的Web服务器
# 导入express模块
const express = require("express");
# 调用express()函数返回一个实例,创建Web服务器
const server = express();
# 调用server.listen(端口号,启动成功的回调函数),启动服务器
server.listen(80,()=>{
console.log("服务器创建成功!");
})
监听GET请求
使用实例的get方法,可以监听客户端的get请求 get方法的参数:url字符串,请求对应的处理函数
参数 | 描述 |
---|
URL字符串 | 客户端请求的URL | req | 请求对象,包含了与请求相关的属性和方法 | res | 响应对象,包含了与响应相关的属性和方法 |
server.get("请求URL",function(req,res){
});
监听POST请求
与监听GET请求基本一致
server.post("请求URL",function(req,res){
});
将内容响应给客户端
server.get("请求URL",function(req,res){
res.send({name:"Chen",age:18});
res.send("get请求成功!");
});
获取URL中携带的查询参数
通过req.query 对象,可以获取URL中携带的查询参数。req.query 默认是个空对象,当客户端发送请求时使用?name=cpf&age=18 这种 查询字符串时,可以通过req.query 访问到相应的属性。比如req.query.name 或者req.query.age
server.get("请求URL",(req,res)=>{
console.log(req.query);
});
获取URL中的动态参数
通过req.params 对象可以获取请求URL中通过: 匹配的动态参数 首先编写get请求
server.get("/user/:id",(req,res)=>{
res.send(req.params);
});
然后在postman中测试请求地址  查看响应结果 
向外托管静态资源
使用express.static() 方法可以对外共享静态资源,方法中需要指定对外共享的文件夹,值得一提的是我电脑里直接用相对地址(./newStruct)没有用,无奈试了一下绝对地址,发现又可以了
const path = require("path");
const express = require("express");
const server = express();
server.use(express.static(path.join(__dirname,"newStruct")));
server.listen(80,()=>{
console.log("托管静态资源的服务器已启动 http://127.0.0.1");
});
如果需要对外托管多个文件夹,则需要多次调用express.static() 即可,当对外托管多个静态资源目录时,如果访问一个在多个文件夹都有的文件名时,会按照托管顺序进行检索
server.use(express.static(path.join(__dirname,"文件夹1")));
server.use(express.static(path.join(__dirname,"文件夹2")));
挂载路径前缀
如果想要在托管的静态资源之前添加路径前缀,即在访问时需要在前面添加一个前缀才可以访问成功。可以使用以下方式:
server.use("/yes",express.static(path.join(__dirname,"newStruct")));
nodemon工具
在编写调试Node.js的项目时,每次修改完代码都需要手动关闭服务器,再重新打开,非常繁琐。这时可以使用nodemon这个工具,它能够监听文件的变动,在代码被修改时,自动帮助我们重启服务器,极大方便了测试与开发。
npm i nodemon -g
在执行js文件时,将node 替换为nodemon 即可
nodemon app.js
Express路由
什么是Express路由
比如我们拨打三大运营商的人工客服电话,会提示我们通过按键进行服务的选取,每个按键会对应一种服务,这种按键与服务之间的映射关系就是路由。 Express中的路由是指客户端的请求 与服务器中处理函数 之间的关系。
Express的路由由三部分组成:请求的类型(METHOD)、请求URL(PATH)、对应处理函数(HANDLER)
server.METHOD(PATH,HANDLER);
例子:
server.get("/",(req,res)=>{
res.send("give you a gift");
});
server.post("/",(req,res)=>{
res.send("Got a POST request");
});
Express路由的匹配过程
每当服务器受到一个请求,需要先经过路由的匹配,服务器会依次按照路由的挂载顺序进行匹配,如果请求类型和请求URL都匹配成功,则Express会将这次请求转交给对应的处理函数进行处理。
模块化路由
为了方便对路由进行模块化管理,Express不建议将路由直接挂载到server实例上,而是推荐将路由抽离为一个单独模块。 创建模块化路由可遵循以下几个步骤:
- 创建路由模块.js文件
- 调用
express.Router() 方法创建路由实例 - 向路由实例上挂载具体的路由
- 使用
module.exports 向外暴露路由对象 - 使用
server.use() 方法注册路由模块
router.js文件
const express = require("express");
const router = express.Router();
router.get("\",(req,res)=>{
res.send("收到了一个get请求");
});
router。post("\",(req,res)=>{
res.send("收到了一个post请求");
});
module.exports = router;
Server.js文件
const express = require("express");
const server = express();
server.use(router);
server.listen(80,()=>{
console.log("服务器已启动!");
});
最后通过nodemon执行Server.js文件
nodemon Server.js
Express中间件
什么是中间件
中间件(Middleware),特指业务流程的中间处理环节。
Express中间件的调用流程
当一个请求到达服务器时,可以连续调用多个中间件,从而对这次请求进行预处理。多个中间件共享同一份req和res。 
Express中间件的格式
Express的中间件,本质上是一个function处理函数。与路由处理函数的区别在于,中间件函数的形参中必须包含next 参数,而路由处理函数只有req 和res 两个形参。 
中间件形参next函数的作用
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
定义中间件函数
定义一个简单的中间件
const mw = function(req,res,next){
console.log("经过了中间件处理");
next();
}
定义一个全局生效的中间件,所谓全局生效的中间件,就是客户端发起的任何请求,到达服务器之后都会经过这个中间件进行处理。 我们通过server.use(中间件函数); 即可定义一个全局中间件
server.use(mw);
定义局部中间件
server.get("/",[mw1,mw2],(req,res)=>{
});
错误级别的中间件
错误级别的中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。 在错误级别的中间件中,必须要有4个参数,从左至又分别是err,req,res,next。需要注意的是,错误级别的中间件需要注册到所有路由之后。
server.use(function(err,req,res,next){
console.log("Error:"+err.message);
res.send("发生了错误:"+err.message);
});
Express内置的中间件
自Express4.16.0之后,Express内置了3个中间件,极大的提高了开发效率。
- express.static() 用于快速托管静态资源的内置中间件且无兼容性问题。例如html文件,图片,css样式等
- express.json() 用于解析JSON格式的请求数据(4.16.0+)
- express.urlencoded() 用于解析URL-encoded格式的请求数据(4.16.0+)
使用中间件的注意事项
- 除错误级别的中间件,其他中间件需要要在注册路由之前注册
- 当执行完中间件的代码时要调用next()函数,并且调用next()函数后不要再写代码
- 连续调用多个中间件时,多个中间件之间共享req和res对象
使用Express编写接口
先创建两个文件,分别是router.js和运行服务器的文件server.js router.js
const express = require("express");
const moment = require("moment");
const router = express.Router();
function ResData() {
this.status = 0;
this.msg = "请求成功!";
this.data = {};
this.time = moment().format("YYYY年MM月DD日 hh:mm:ss");
}
router.get("/get", (req, res) => {
const query = req.query;
let resData = new ResData();
resData.msg = "get请求成功!";
resData.data = query;
res.send(resData);
});
router.post("/post", (req, res) => {
const body = req.body;
let resData = new ResData();
resData.msg = "post请求成功!";
resData.data = body;
res.send(resData);
});
module.exports = router;
server.js
const express = require("express");
const server = express();
const router = require("./router");
server.use(express.urlencoded({ extended: false }));
server.use("/api", router);
server.use((err, req, res, next) => {
console.log("发生了一个错误:" + err.message);
res.send("发生了一个错误:" + err.message);
});
server.listen(80, () => {
console.log("express server running at http://127.0.0.1");
});
接口的跨域问题
当我们在本地创建一个html页面,并且借助Jquery中的ajax向接口请求数据时,就会受到浏览器同源安全策略的影响,产生跨域问题。 由于使用的协议不一致,一个是http协议,一个是file协议,导致出现跨域问题。
跨域问题的解决
第一种方法是使用JSONP方案解决,缺陷是只能支持get请求 第二种方法是使用CORS方案,是目前的主流方案,推荐使用
使用CORS中间件解决跨域问题
cors(Cross-Origin Resource Sharing,跨域资源共享),由一系列HTTP响应头组成,这些HTTP响应头决定了浏览器是否要阻止前端js代码跨域获取资源。它是Express的一个第三方中间件,通过安装和配置cors中间件,可以很方便的解决跨域问题。 使用步骤: 安装cors中间件
npm install cors
在server.js中引入cors中间件
const cors = require("cors");
在路由之前注册cors
server.use(cors());
在这之前还需要配置一个JSONP的接口,防止通过JSONP接口的请求被当成CORS的请求,进而二者间产生冲突。 在注册CORS之前需要配置JSONP的一个接口。
server.get("/api/jsonp",(req,res)=>{
});
server.use(cors());
接下来就可以通过js正常访问配置了cors的接口了。
在服务器端实现JSONP接口
思路:
- 获取客户端发送回来的回调函数的名字
- 得到要通过JSONP响应给客户端的数据
- 根据前两步的数据,拼接出一个函数的调用的字符串
- 把拼接的字符串响应给客户端的<script>标签
server.get("/api/json",(req,res)=>{
const funcName = req.query.callback;
const data = {name:"李四",age:18};
const scriptStr = `${funcName}(${data})`;
res.send(JSON.stringfy(scriptStr));
});
cors在浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能够正常访问开启了cors的服务端接口(IE10+,Chrome4+,Firefox3.5+等)
|