Express简介
是一个简洁而灵活的node.js Web应用框架,提供了一系列强大特性帮助创建各种Web应用和丰富的HTTP工具
核心特性
- 可以设置中间件来响应HTTP请求
- 定义了路由表用于执行不同的HTTP请求动作
- 可以通过向模板传递参数来动态渲染HTML页面
路由
路由的介绍
可以为一个路径同时映射多个路由,这样当访问该路径时,多个路由都会被触发,触发顺序是按照路由的设置顺序触发的,多个路由只能返回一个响应;
同一次请求里的req和res一定是相同的对象,哪怕是配置的多个路由;
可以通过next来控制路由是否向下进行,如果不调用next,则不会向下继续,而调用next则会触发下一个路由
路由的设置
路由的设置方式:
app.<method>(path,callback);
< method>表示要处理的请求方式,可以是get post或all;
path 是服务器端的路径,也是要映射的路径,以斜杠/开头,斜杠/代表根目录;
callback是当路由匹配到时需要执行的函数,当path对应的地址被访问时,要调用的回调函数,回调函数中有三个参数——req、res、next
以下为设置路由的两种方式:
app.get("/hello",function (req , res , next) {});
// GET 方法请求路由
app.get('/', function (req, res) {
res.send('GET request to the homepage');
});
// POST 方法请求路由
app.post('/', function (req, res) {
res.send('POST request to the homepage');
});
路由路径
路由路径和请求方法一起定义了请求的端点,可以是字符串、字符串模式、正则表达式
url地址的格式:
协议名://域名/ip地址:端口号/路径/资源名?查询字符串
相对路径:
指相对于当前资源所在目录的位置;
在服务器中,路径都是相对于虚拟路径的;
相对路径使用.或..开头,或者直接写路径;“.”或直接写路径表示在当前文件夹中寻找;”..”表示去上一级文件夹中寻找;
绝对路径:
绝对路径使用“/”开头;
/代表的是服务器中的根目录;
绝对路径永远相对于服务器的根目录,不会因为文件的位置的改变而改变;
在开发环境是服务器的时候,应该使用绝对路径,而不是用相对路径;
request和response对象
request对象
request对象表示HTTP请求,包含了请求查询字符串、参数、内容、HTTP头部等属性
常见属性——
req.hostname / req.ip:获取主机名和IP地址;
req.originalUrl:获取原始请求URL,请求首页的路径;
req.path:获取请求路径
req.protocol:获取协议类型
req.query:获取URL的查询参数串
req.route:获取当前匹配的路由
req.header:所有的请求头
req.get():获取指定的HTTP请求头
req.is():判断请求头Content-Type的MIME类型
response对象
response对象表示HTTP响应,即在接收到请求时服务器向客户端发送的HTTP响应数据
常见属性——
res.set()在res.append()后将重置之前设置的头;
res.set():设置HTTP头,传入object可以一次设置多个头
res.download():
将文件设置为响应头并提供给客户端进行下载;
使用该方法发送的文件,无论浏览器是否能打开,都会弹出下载窗口;
res.sendFile( pa th [,o pt io n s ] [,f n ] ):将文件设置响应体并发送给客户端;使用该方法发送的文件,如果浏览器能打开则自动打开,否则将会弹出下载窗口。
将文件设置响应体并发送给客户端
使用该方法发送的文件,如果浏览器能打开则自动打开,否则将会弹出下载窗口;
res.get():返回指定的HTTP头
res.location():只设置响应的Location HTTP头,不设置状态码或者close response
res.send():传送HTTP响应,设置的仅仅只是响应体!而响应首行和响应响应头默认已经设置好了。注意,send请求只能调用一次!
res.sendStatus()服务器发送给浏览器的响应状态码;
get方式设置路由
app.get()用来设置get()路由
参数为两个,一个为路由映射的请求地址,第二个为回调函数
app.get('/example/b', function (req, res, next) {
console.log('通过路由发送内容');
next();
}, function (req, res) {
res.send('你好,我是hello路由返回的内容');
});
post方式设置路由
app.post()用来设置post路由
app.post('/process_post', urlencodedParser, function (req, res) {
// 输出 JSON 格式
var response = {
"first_name":req.body.first_name,
"last_name":req.body.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})
Express.Router
Express.Router作为一个单独的组件,类似小型的express应用程序一样,有自己的use、get、param、route方法
使用 express.Router 类创建模块化、可挂载的路由句柄,Router 实例是一个完整的中间件和路由系统,因此常称其为一个 “mini-app”
基本用法
Express.Router是一个构造函数,调用后返回一个路由器实例。然后,使用该实例的HTTP动词方法,为不同的访问路径指定回调函数;最后,挂载到某个路径
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('首页');
});
router.get('/about', function(req, res) {
res.send('关于');
});
app.use('/', router);
router.use()方法为router对象指定中间件,在数据正式发给用户之前,对数据进行处理
router.use(function(req, res, next) {
console.log(req.method, req.url);
next();
});
router.param()方法用于路径参数的处理,param方法必须放在HTTP动词方法之前
router.param('name', function(req, res, next, name) {// 对name进行验证或其他处理…… console.log(name);
req.name = name;
next();
});
router.get('/hello/:name', function(req, res) {
res.send('hello ' + req.name + '!');
});
HTTP模块
express框架建立在node.js内置的http模块上
http模块生成服务器的原始代码如下:
var http = require("http");
var app = http.createServer(function(request,response){
response.writeHead(200, {"Content-Type":"text/plain"});
response.end("Hello world!");
});
app.listen(3000, "localhost");
express框架的核心是对http模块的再包装:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello world!');
});
app.listen(3000);
两者差别在于express框架在http模块上加了一个中间层
中间件
express和中间件的关系
Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件
中间件的性质
每个中间件都是一个handler,用来处理HTTP请求的函数,依次传入request,response,next三个参数
中间件讲究顺序,匹配上第一个之后,就不会往后匹配了。next函数才能够继续往后匹配
基本的中间件结构如下:
function myFunMiddleware(request, response, next) {
// 对request和response作出相应操作
// 操作完毕后返回next()即可转入下個中间件
next();
}
中间件的功能
- 执行任何代码
- 修改请求和相应对象
- 终结请求-响应循环
- 调用堆栈中的下一个中间件
如果当前中间件没有终结请求-响应循环,则必须调用next()
方法将控制权交给下一个中间件,否则请求就会被挂起
中间件的分类
Express应用可以使用如下几种中间件:
- 应用级中间件
应用级中间件绑定到app对象,使用app.use(),app.get(),app.post(),app.put()
- 路由级中间件
路由级中间件绑定的对象为express.Router()
- 错误处理中间件
错误处理中间件和其他中间件定义类似,只是要使用4个参数:err,req,res,next
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
- 内置中间件
express.static是express唯一内置的中间件,基于serve-static,负责在express应用中托管静态资源 - 第三方中间件
通过使用第三方中间件从而为express应用增加更多功能。
安装所需功能的node模块,并在应用中加载,可以在应用级加载,也可以在路由级加载
use方法
use是express注册中间件的方法,它返回一个函数
调用几次app.use()就注册了几个中间件
use方法内部可以对访问路径进行判断,据此实现简单的路由根据不同的请求网址,返回不同的网页内容
方法一:
在回调函数内部判断请求的网址:
var express = require("express");var http = require("http");var app = express();
app.use(function(request, response, next) { if (request.url == "/") {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the homepage!\n");
} else {
next();
}
});
app.use(function(request, response, next) { if (request.url == "/about") {
response.writeHead(200, { "Content-Type": "text/plain" });
} else {
next();
}
});
app.use(function(request, response) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.end("404 error!\n");
});
http.createServer(app).listen(1337);
方法二:
允许将请求网址写在第一个参数,表示只有请求路径匹配了这个参数,后面的中间件才生效
app.use('/path', someMiddleware);
API
express()
创建Express应用程序
express()函数是express模块导出的顶级函数
var express = require('express');
var app = express();
express.json([options])
是Express中的内置中间件功能,使用JSON有效负载解析传入的请求
express.static(root,[options])
是Express中的内置中间件功能
提供静态文件,基于serve-static,root参数指定从中提供静态资源的根目录
该函数通过req.url与提供的root目录组合来确定要提供的文件,当找不到文件时,它不是返回404响应,而是调用next()
继续下一个中间件,允许堆叠和回退
exoress.Router([options])
创建一个新的路由器对象
var router = express.Router([options]);
可选options参数指定路由器的行为:
- caseSensitive
启用区分大小写,默认情况下禁用 - mergeParams
保留req.params父路由器的值。如果父级和子级具有冲突的参数名称,则子级的值优先。默认值为false - strict
启用严格路由,默认情况下禁用
express.urlencoded([options])
是Express中的内置中间件功能
可选options对象的属性值如下:
- extended
- inflate
- limit
- parameterLimit
- type
- verify