express框架什么用呢?其实express框架可以帮助我快速开发,并且引入了路由和中间件等概念。
就拿之前的元素node项目为例,我们是不是还要去引入http模块,然后去createserver,去声明端口号,然后根据req的url去判断请求的地址和method,再去做相应的操作,过程复杂化了,但是我们使用express框架就可以简化流程,提高开发效率。
安装
当然第一步是初始化项目,npm init -y 去创建一个默认的package.json。我们使用了express框架,我们还需要去下载该第三方,
npm install express -S,为什么要添加到生产模式?之前说了影响到程序正常运行的要添加到生产模式,不影响则添加到开发者模式。
这样一来我们就添加好依赖。
初步使用
const app = require("express")();
// 绑定路由
app.get("/",(req,res)=>{
// 响应请求
res.send("ok");
});
app.listen(3000,()=>{
console.log("app is running....");
});
我们处理了一个请求,就是localhost:3000,都返回ok,别急我们慢慢道来。
托管静态库
什么是托管静态库呢?我们可以这么理解,就是通过设置了静态库,我们就可以通过url去获取静态库中对应的文件。
app.use("/demo",express.static("public"));
app.use(express.static("public_two"));
声明如上,第一种和第二中的区别就是需要加前缀。就采用如上所示的声明方法,我们就可以在浏览器中去请求对应的文件
http://localhost:3000/demo/public/index.html
http://localhost:3000/demo/public/index.css
http://localhost:3000/demo/public/index.js
http://localhost:3000/public_two/index.html
http://localhost:3000/public_two/index.css
http://localhost:3000/public_two/index.js
路由
什么是路由?通过请求路径和请求方法进行路径分发处理
常见的请求方式有四种:get post delete put,外加use route 都可以实现路由。
const express = require("express");
const app = express();
app.get("/asd",(req,res)=>{
res.send("welcome");
});
app.post("/asd",(req,res)=>{
res.send("welcome post");
});
app.put("/asd",(req,res)=>{
res.send("welcome put");
});
app.delete("/asd",(req,res)=>{
res.send("welcome delete");
});
// all方法绑定的路由 与具体的请求方式无关
app.all("/asd",(req,res)=>{
res.send("welcome");
});
// use分发可以处理所有的路由请求
app.use((req,res)=>{
res.send("hi");
});
app.route("/asd").get((req,res)=>{
console.log("get /my");
}).post((req,res)=>{
console.log("post /my");
}).delete((req,res)=>{
console.log("post /my");
}).put((req,res)=>{
console.log("post /my");
});
app.listen(3000,()=>{
console.log("app is running....");
});
- get,post,put,delete,都是常用的请求方式。如发起get请求,路径是/asd,那么浏览器则会显示welcome;若是put请求,路径是/asd那么浏览器则会显示welcome put。
- 若是通过all来处理http请求,则无论发起的是get post put等都会被该方法处理。
- use需要搭配中间件,至于中间件是什么后面会讲解到。这里就可以理解为可以处理所有符合路径的http请求(案例中路径未写),因为所有符合路径的http请求都会回调到use的回调方法里。
- route。当同一个路径有不同的请求方法时,为避免冗余代码我们可以使用route。我们可以将上面的get,post,put,delete通过route整合起来。
中间件
官方的介绍解释Express是一种路由和中间件Web框架,它具有自己的最小功能:Express应用程序本质上是一系列中间件函数调用。
但还是云里雾里的,后面又说了中间件函数是可以访问请求对象(req),响应对象(res)以及应用程序的请求-去响应下一个中间件函数的函数。
所以我们可以这么理解中间件其实就是函数,所以就像app.get app.post等等,他们请求的回调方法其实就是一个中间件。中间件的机制有点像是事件方法,就像点击事件一样从上往下去分发事件。我们先来看看下面案例来加深理解
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);
if(req.params.id==2)
next()
else{
res.end("权限不够")
}
})
app.get('/user/:id', function (req, res, next) {
res.send('User Info11')
res.end(req.params.id)
})
上面案例使用到了use和中间件的使用,use是处理所有符合路径也就是/user的http请求后面 /:id 表示参数,然后我们可以通过中间件函数去控制是否将该事件分发下去,中间件中我们可以进行事件分发的条件。上诉案例中在use的第一个中间件里,我们通过next(),将该事件分发到下一个中间件,下一个中间件判断id是否等于2,若是通过next在进行分发,若不是则结束改事件。
中间件分几种
- 应用程序级中间件
- 路由器级中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
应用程序级中间件
应用级别就是上面app.use的案例
路由器级中间件
路由器级中间件的工作方法与应用程序级中间件的工作方式相同,但它绑定到的是一个实例express.Router();使用如下
const express = require("express");
const app = express();
const router = require("./myrouter.js");
app.use("/admin",router);
app.listen(3000,()=>{
console.log("app is running....");
});
//myrouter.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('home page');
});
router.get('/about', function(req, res) {
res.send('About birds');
});
router.post('/about', function(req, res) {
res.send('About birds');
});
module.exports = router;
将路由文件放置在一个js里,可方便以后的维护。
错误处理中间件
- 错误处理
在讲解错误处理中间件的概念之前,我们先来了解一下错误处理。
错误处理是指express如何捕获和处理同步和异步发生的错误。
同步中的错误处理 若是路由处理程序和中间件内的同步代码中发生的错误不需要额外的工作。因为同步代码中的错误,express会捕获并处理他们。
app.get("/", function (req, res) {
throw new Error("BROKEN"); // Express will catch this on its own.
});
异步中的错误处理 对于有路由处理程序和中间件调用的异步函数返回的错误,他们必须将他传给next(),express将会捕获并处理。
app.get("/", function (req, res, next) {
fs.readFile("/file-does-not-exist", function (err, data) {
if (err) {
next(err); // Pass errors to Express.
}
else {
res.send(data);
}
});
});
可直接把错误传到通过next()函数,传给express处理。若是只返回错误可以直接在回调里直接传入next()
app.get("/", [
function (req, res, next) {
fs.writeFile("/inaccessible-path", "data", next);
},
function (req, res) {
res.send("OK");
}
]);
- 默认错误处理中间件
其实erpress附带了一个内置的错误处理程序,上面不是说了对于同步处理的错误,express会自动捕获然后去处理,可以处理应用程序中可能遇到的任何错误。该内置的处理错误的中间件会被添加到中间件功能堆栈的末尾。
function errorHandler (err, req, res, next) {
}
中间件的结构是这样的,四个参数一个都不能少。
也就是说在同步错误处理也好,异步错误处理通过next()传给express也好,若我们没有编写错误处理程序,都将会交给express的内置的错误处理程序处理,同样的我们也可以去自定义错误处理程序。
- 自定义错误处理中间件
我们通过use方法去自定义,不过自定义错误处理需要定义在其他app.use()路由调用之后
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
function logErrors (err, req, res, next) {
console.error(err.stack)
next(err)
}
function clientErrorHandler (err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' })
} else {
next(err)
}
}
function errorHandler (err, req, res, next) {
res.status(500)
res.render('error', { error: err })
}
logErrors 错误处理程序显示日志,接受处理所有的express捕获到的错误,通过日志打印出错误的堆栈信息,并且通过next()传给下一个错误处理程序
clientErrorHandler 错误处理程序返回前端请求错误信息,主要用于处理网络请求错误,我们编写错误处理代码并去结束响应,若不处理next()传给下一个
errorHandler 错误处理程序返回前端请求错误信息,最后将没被过滤掉的错误一起处理,返回500和错误信息。
内置中间件
内置中间件 其实就是之前说的托管静态库
const express = require("express");
const app = express();
// 挂载内置中间件
app.use(express.static("public"));
第三方中间件
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
// 挂载post参数处理中间件 parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
后面我们会编写一个小项目,在此之前我们先来介绍一些常用的第三方插件
body-parser
尤其是在解析post请求时,需要就去解析参数就要去监听data和end,确实过于繁琐,但是有了body-parser第三方插件。
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.listen(3000,()=>{
console.log("app is running");
});
这样子我们就可以通过 req.body去获取post请求来的参数
art-template
上一篇文章已经介绍了,这个是模板引擎,针对express,art-template也进行了兼容,推出了express-art-etmplate。
const express = require("express");
const path = require("path");
const router = require("./router.js");
const app = express();
// 设置模板引擎
app.set("views",path.join(__dirname,"views"));
// 设置模板引擎
app.set("view engine","art");
// 让express兼容art-template
app.engine("art",require("express-art-template"));
// 配置路由
app.use(router);
app.listen(3000,()=>{
console.log("app is running");
});
第一句的意思就是,我们要创建一个views文件夹,并且告诉express文件夹的位置,
第二句的意思就是,模板引擎文件的后缀名是art
第三句的意思就是,让express去兼容express-art-template
下面演示一下
const express = require("express");
const path = require("path");
const router = require("./router.js");
const app = express();
// 设置模板引擎
app.set("views",path.join(__dirname,"views"));
// 设置模板引擎
app.set("view engine","art");
// 让express兼容art-template
app.engine("art",require("express-art-template"));
app.get("/",(req,res)=>{
res.render("index",{name:"hello"});
})
// 配置路由
app.use(router);
app.listen(3000,()=>{
console.log("app is running");
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="/www/index.css" />
</head>
<body>
<div>
{{name}}
</div>
</body>
</html>
其中res.render方法里面的index其实值指的就是views文件夹下的index.art,第二个参数表示传入的值。
本章节目标已完成,接下来会讲解node与数据库的相关知识,如有表达错的请谅解,并请提出指出,且修改错误,望能共同进步。
来源:CSDN
作者:csdn_gyh
链接:https://blog.csdn.net/gaoyouhuang/article/details/84929607