Express详解
安装 express
在目标文件夹下执行如下命令:
安装完后,在目标文件夹下新建index.js文件:
然后在Node.js的命令行环境下执行“node index.js”命令,网站就运行起来了。浏览器访问一下,可以输出相应的信息。
使用
Express中的路由与路由器
Express中的路由器分为两种类型:
app类型的路由器常使用如下代码创建:
router类型的路由器常使用如下代码创建:
app和router是形为function(request, response, next)形式的函数对象,使用app.verb(),router.verb()形式函数实现路由注册(路由注册本质上是一个观察者模式)。
app.verb()和router.verb()中的verb常使用use、get、post、put、delete、route等动词,不同动词管辖的HTTP请求方法范围不同,这些动词函数的参数形式常为(pathExp, handleCallback)形式:其中pathExp表示请求路径,可为正则表达式;handleCallback为路径映射处理函数。
app是Express框架所构建程序的请求处理入口,app可作为顶层路由器使用,在应用中也可挂载下级路由器(使用router对象)以实现分级路由。
中间件
Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。
中间件(Middleware) 就是处理HTTP请求的函数,它最大的特点就是,一个中间件处理完,再传递给下一个中间件。App实例在运行过程中,会调用一系列的中间件。
每个中间件可以从App实例,接收三个参数,依次为request对象(代表HTTP请求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。每个中间件都可以对HTTP请求(request对象)进行加工,并且决定是否调用next方法,将request对象再传给下一个中间件。
use方法
use是express注册中间件的方法,它返回一个函数。下面是一个连续调用两个中间件的例子。
上面代码使用app.use方法,注册了两个中间件。收到HTTP请求后,先调用第一个中间件,在控制台输出一行信息,然后通过next方法,将执行权传给第二个中间件,输出HTTP回应。由于第二个中间件没有调用next方法,所以request对象就不再向后传递了。
use方法内部可以对访问路径进行判断,据此就能实现简单的路由,根据不同的请求网址,返回不同的网页内容。
上面代码通过request.url属性,判断请求的网址,从而返回不同的内容。注意,app.use方法一共登记了三个中间件,只要请求路径匹配,就不会将执行权交给下一个中间件。因此,最后一个中间件会返回404错误,即前面的中间件都没匹配请求路径,找不到所要请求的资源。
除了在回调函数内部判断请求的网址,use方法也允许将请求网址写在第一个参数。这代表,只有请求路径匹配这个参数,后面的中间件才会生效。无疑,这样写更加清晰和方便。
上面代码表示,只对根目录的请求,调用某个中间件。
因此,上面的代码可以写成下面的样子。
当你不写路径的时候,实际上就相当于"/",就是所有网址
路由get、post这些东西,也是中间件,中间件讲究顺序,匹配上第一个之后,就不会往后匹配了,next函数才能够继续往后匹配。如下实例:
all方法和HTTP动词方法
针对不同的请求,Express提供了use方法的一些别名。比如,上面代码也可以用别名的形式来写。
上面代码的all方法表示,所有请求都必须通过该中间件,参数中的“*”表示对所有路径有效。get方法则是只有GET动词的HTTP请求通过该中间件,它的第一个参数是请求的路径。由于get方法的回调函数没有调用next方法,所以只要有一个中间件被调用了,后面的中间件就不会再被调用了。
除了get方法以外,Express还提供post、put、delete方法,即HTTP动词都是Express的方法。
这些方法的第一个参数,都是请求的路径。除了绝对匹配以外,Express允许模式匹配。
上面代码将匹配“/hello/alice”网址,网址中的alice将被捕获,作为req.params.who属性的值。需要注意的是,捕获后需要对网址进行检查,过滤不安全字符,上面的写法只是为了演示,生产中不应这样直接使用用户提供的值。
如果在模式参数后面加上问号,表示该参数可选。
set方法
set方法用于指定变量的值。
上面代码使用set方法,为系统变量“views”和“view engine”指定值。
response对象
API | 含义 |
---|---|
res.app |
同req.app |
res.append() |
追加指定HTTP头 |
res.set() |
在res.append()后将重置之前设置的头 |
res.cookie() |
设置Cookie |
res.clearCookie() |
清除Cookie |
res.download() |
传送指定路径的文件 |
res.get() |
返回指定的HTTP头 |
res.json() |
传送JSON响应 |
res.jsonp() |
传送JSONP响应 |
res.location() |
只设置响应的Location HTTP头,不设置状态码或者close response |
res.redirect() |
设置响应的Location HTTP头,并且设置状态码302 |
res.send() |
传送HTTP响应 |
res.sendFile() |
传送指定路径的文件 -会自动根据文件extension设定Content-Type |
res.set() |
设置HTTP头,传入object可以一次设置多个头 |
res.status() |
设置HTTP状态码 |
res.type() |
设置Content-Type的MIME类型 |
(1)response.redirect方法
response.redirect方法允许网址的重定向。
response.redirect("/hello/anime");
response.redirect("http://www.example.com");
response.redirect(301, "http://www.example.com");
res.redirect()默认响应状态码是302
可以更改这个状态码作为res.redirect()的第一个参数
当在url地址栏中输入http://localhost:3000
页面就会重定向到http://localhost:3000/demo
(2)response.sendFile方法
response.sendFile方法用于发送文件。
response.sendFile("/path/to/anime.mp4");
(3)response.render方法
response.render方法用于渲染网页模板。
app.get("/", function(request, response) {
response.render("index", { message: "Hello World" });
});
上面代码使用render方法,将message变量传入index模板,渲染成HTML网页。
(4)res.send()
res.send用于向客户端响应信息
并且它的强大之处在于可以智能的处理我们传递的不同类型参数
当参数为字符串,会将响应头Content-Type默认设置为text/html
也就是解析为html呈现在我们的页面上
当参数为数字,会自动帮我们设置响应体(状态码…)
当参数为数组或对象,它会响应一个JSON
requst对象
API | 含义 |
---|---|
req.app |
当callback为外部文件时,用于访问express的实例 |
req.baseUrl |
获取路由当前安装的URL路径 |
req.body/cookies |
获得「请求主体」/ Cookies |
req.fresh/stale |
判断请求是否还「新鲜」 |
req.hostname/ip |
获取主机名和IP地址 |
req.originalUrl |
获取原始请求URL |
req.params |
获取路由的parameters |
req.path |
获取请求路径 |
req.protocol |
获取协议类型 |
req.query |
获取URL的查询参数串 |
req.route |
获取当前匹配的路由 |
req.subdomains |
获取子域名 |
req.acceptsCharsets |
返回指定字符集的第一个可接受字符编码 |
req.acceptsEncodings |
返回指定字符集的第一个可接受字符编码 |
req.acceptsLanguages |
返回指定字符集的第一个可接受字符编码 |
req.accepts() |
检查可接受的请求的文档类型 |
req.get() |
获取指定的HTTP请求头 |
req.is() |
判断请求头Content-Type的MIME类型 |
(1)request.ip
request.ip属性用于获得HTTP请求的IP地址。
(2)request.files
request.files用于获取上传的文件。
(3)req.query
req.query可以获取请求路径参数的对象
向服务器发送请求 http://localhost:3000/?user=tester&pass[a]=123&pass[b]=456
(4)req.params
req.params可以解析复杂路由规则上的属性
(req.param综合了req.query和req.param的功能,但是被移除了不要使用)
向服务器发送请求 http://localhost:3000/123456
这样不论我在根路径后输入的是什么都会被解析为req.params.id
静态资源
静态资源就是指我们在开发中用到的css、js、img等等
它们需要存放到一个静态资源目录
当浏览器发出了一个非HTML文件请求
服务器就会从这个静态资源目录下去查找文件
我们一般在根目录下创建一个public文件来存储
并在public中创建stylesheets、javascripts、images等文件夹
用来存储特定类型的资源
指定静态资源目录的方法上面已经提到了
比如说我们的html中有这样的代码
那么客户端运行发出请求
服务器就会在public的javascripts文件夹下找到jquery.js静态资源
模板引擎
express框架默认是ejs和jade渲染模板
路由
路由的意思就是根据不同的路径,来指定不同的处理方法
我们一般把不同的路由封装进不同的模块
首先在根目录下创建一个文件夹routes存储路由
现在我在routes文件夹下创建俩个路由文件index.js和users.js
修改app.js
这样表示http://localhost:3000/的路由交给index处理
http://localhost:3000/users的路由交给users处理
下面简单的实现一下路由
通过express.Router()创建的router就像一个mini版的app一样
app能做的,router都能做
只是我们把逻辑都封装到了各个路由模块中
上面代码的结果:
body-parser中间件
其实express在3.x版本中内置了很多中间件
但是4.x版本就将出static以外的所有中间件全部抽离出来了
所以就需要我们单独安装
对照表如下:
Express 3.0 | Express 4.0 |
---|---|
bodyParser | body-parser |
compress | compression |
cookieSession | cookie-session |
logger | morgan |
cookieParser | cookie-parser |
session | express-session |
favicon | static-favicon |
response-time | response-time |
error-handler | errorhandler |
method-override | method-override |
timeout | connect-timeout |
vhost | vhost |
csrf | csurf |
刚才就提到了POST请求有所不同
不同的地方就在于我们需要body-parser这个中间件来处理数据
通过req.body来获得数据
首先使用前不要忘记下载
下面这四个方法分别用于对body内容采取不同的处理方法
bodyParser.json(options) 处理JSON数据
bodyParser.raw(options) 处理buffer数据
bodyParser.text(options) 处理文本数据
bodyParser.urlencoded(options) 处理UTF-8编码数据
这样我首先通过get请求获取主页面
提交表单向服务器发送post请求
服务器响应结果
express-generator:使用express搭建应用结构
express模块有一个命令行工具express,可以用来生成基于express模块的应用结构(网站结构)。
express 4.x之后,express命令被独立出来放在了express-generator模块中。我们用下面的命令全局安装express这个命令行工具:
安装完成后,在命令行环境下执行“express --version”,可以看到express的版本是4.16.1。
好了,现在我们使用express命令来创建一个默认的网站。
在命令行环境下导航到node.js这个目录下,执行下面的命令:
然后可以看到:
仔细看上面的图哦,它告诉了我们三类非常重要的信息:
express命令创建的网站的目录结构以及创建的文件
安装依赖(进入到HelloExpress下,执行npm install)
使用npm start启动网站(express 4.x后)
按照响应的提示依次执行:
很快就可以看到下面的图:
看到上图,说明网站已正常运行。你可以在浏览器里访问http://localhost:3000,然后就可以看到这个页面:
到这里,express框架就搭建成功!
最后附上API中文地址:https://cloud.tencent.com/developer/section/1489347