Express详解

安装 express

在目标文件夹下执行如下命令:

cnpm i express

安装完后,在目标文件夹下新建index.js文件:

// 引入 express 模块
var express = require('express');

// 创建 express 实例
var app = express();

// 响应HTTP的GET方法
app.get('/', function (req, res) {
 res.send('Hello World!');
});

// 监听到8000端口
app.listen(8000, function () {
 console.log('Hello World is listening at port 8000');
});

然后在Node.js的命令行环境下执行“node index.js”命令,网站就运行起来了。浏览器访问一下,可以输出相应的信息。

使用

const express = require("express");
const app = express();

// 处理文件路径的模块
const path = require("path");

// view处理
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");

// 定义一个存放静态资源的目录
app.use(express.static("src"));

// 页面路由的处理,此处表示首页的时候处理index
const index = require("./routes/index");
app.use("/", index);

const server = app.listen(8080, function(){
	console.log("启动成功!");
})

中间件

官方介绍:

http://expressjs.com/zh-cn/guide/writing-middleware.html

http://expressjs.com/zh-cn/guide/using-middleware.html

Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。

中间件(Middleware) 就是处理HTTP请求的函数,它最大的特点就是,一个中间件处理完,再传递给下一个中间件。App实例在运行过程中,会调用一系列的中间件。

每个中间件可以从App实例,接收三个参数,依次为request对象(代表HTTP请求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。每个中间件都可以对HTTP请求(request对象)进行加工,并且决定是否调用next方法,将request对象再传给下一个中间件。

use方法

use是express注册中间件的方法,它返回一个函数。下面是一个连续调用两个中间件的例子。

var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
  console.log("In comes a " + request.method + " to " + request.url);
  next();
});

app.use(function(request, response) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Hello world!\n");
});

http.createServer(app).listen(1337);

上面代码使用app.use方法,注册了两个中间件。收到HTTP请求后,先调用第一个中间件,在控制台输出一行信息,然后通过next方法,将执行权传给第二个中间件,输出HTTP回应。由于第二个中间件没有调用next方法,所以request对象就不再向后传递了。

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);

上面代码通过request.url属性,判断请求的网址,从而返回不同的内容。注意,app.use方法一共登记了三个中间件,只要请求路径匹配,就不会将执行权交给下一个中间件。因此,最后一个中间件会返回404错误,即前面的中间件都没匹配请求路径,找不到所要请求的资源。

除了在回调函数内部判断请求的网址,use方法也允许将请求网址写在第一个参数。这代表,只有请求路径匹配这个参数,后面的中间件才会生效。无疑,这样写更加清晰和方便。

app.use('/path', someMiddleware);

上面代码表示,只对根目录的请求,调用某个中间件。

因此,上面的代码可以写成下面的样子。

var express = require("express");
var http = require("http");

var app = express();

app.use("/home", function(request, response, next) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Welcome to the homepage!\n");
});

app.use("/about", function(request, response, next) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end("Welcome to the about page!\n");
});

app.use(function(request, response) {
  response.writeHead(404, { "Content-Type": "text/plain" });
  response.end("404 error!\n");
});

http.createServer(app).listen(1337);

当你不写路径的时候,实际上就相当于"/",就是所有网址

路由get、post这些东西,也是中间件,中间件讲究顺序,匹配上第一个之后,就不会往后匹配了,next函数才能够继续往后匹配。如下实例:

app.get("/",function(req,res,next){
    console.log("1");
    next();
});

app.get("/",function(req,res){
    console.log("2");
});

all方法和HTTP动词方法

针对不同的请求,Express提供了use方法的一些别名。比如,上面代码也可以用别名的形式来写。

var express = require("express");
var http = require("http");
var app = express();

app.all("*", function(request, response, next) {
  response.writeHead(200, { "Content-Type": "text/plain" });
  next();
});

app.get("/", function(request, response) {
  response.end("Welcome to the homepage!");
});

app.get("/about", function(request, response) {
  response.end("Welcome to the about page!");
});

app.get("*", function(request, response) {
  response.end("404!");
});

http.createServer(app).listen(1337);

上面代码的all方法表示,所有请求都必须通过该中间件,参数中的“*”表示对所有路径有效。get方法则是只有GET动词的HTTP请求通过该中间件,它的第一个参数是请求的路径。由于get方法的回调函数没有调用next方法,所以只要有一个中间件被调用了,后面的中间件就不会再被调用了。

除了get方法以外,Express还提供post、put、delete方法,即HTTP动词都是Express的方法。

这些方法的第一个参数,都是请求的路径。除了绝对匹配以外,Express允许模式匹配。

app.get("/hello/:who", function(req, res) {
  res.end("Hello, " + req.params.who + ".");
});

上面代码将匹配“/hello/alice”网址,网址中的alice将被捕获,作为req.params.who属性的值。需要注意的是,捕获后需要对网址进行检查,过滤不安全字符,上面的写法只是为了演示,生产中不应这样直接使用用户提供的值。

如果在模式参数后面加上问号,表示该参数可选。

app.get('/hello/:who?',function(req,res) {
	if(req.params.id) {
    	res.end("Hello, " + req.params.who + ".");
	}
    else {
    	res.send("Hello, Guest.");
	}
});

set方法

set方法用于指定变量的值。

app.set("views", __dirname + "/views");

app.set("view engine", "jade");

 上面代码使用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()的第一个参数

//app.js
var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.redirect(302, 'demo');
});
app.get('/demo', function(req, res){
  res.end();
});

app.listen(3000);

当在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用于向客户端响应信息 

并且它的强大之处在于可以智能的处理我们传递的不同类型参数

app.get('/', function(req, res, next){
  res.send('express');
});

当参数为字符串,会将响应头Content-Type默认设置为text/html

也就是解析为html呈现在我们的页面上

app.get('/', function(req, res){
  res.send(200);
});

当参数为数字,会自动帮我们设置响应体(状态码…)

app.get('/', function(req, res){
  res.send([1, 2, 3]);
});

 当参数为数组或对象,它会响应一个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

//app.js
var express = require('express');
var app = express();

app.get('/', function(req, res, next){
  console.log(req.query);
  console.log(req.query.user); //tester
  console.log(req.query.pass.a); //123
  console.log(req.query.pass.b); //456
  res.end();
});

app.listen(3000);

(4)req.params

req.params可以解析复杂路由规则上的属性 
(req.param综合了req.query和req.param的功能,但是被移除了不要使用)

向服务器发送请求 http://localhost:3000/123456

//app.js
var express = require('express');
var app = express();

app.get('/:id', function(req, res, next){
  console.log(req.params.id); //123456
  res.end();
});

app.listen(3000);

这样不论我在根路径后输入的是什么都会被解析为req.params.id 

静态资源

静态资源就是指我们在开发中用到的css、js、img等等 

它们需要存放到一个静态资源目录 

当浏览器发出了一个非HTML文件请求 

服务器就会从这个静态资源目录下去查找文件 

我们一般在根目录下创建一个public文件来存储 

并在public中创建stylesheets、javascripts、images等文件夹 

用来存储特定类型的资源

指定静态资源目录的方法上面已经提到了

var path = require('path');
app.use(express.static(path.join(__dirname, 'public')));

比如说我们的html中有这样的代码

<link href="/javascripts/jquery.js" rel="stylesheet" media="screen">

 那么客户端运行发出请求

服务器就会在public的javascripts文件夹下找到jquery.js静态资源

模板引擎

express框架默认是ejs和jade渲染模板 

路由

路由的意思就是根据不同的路径,来指定不同的处理方法 

我们一般把不同的路由封装进不同的模块

首先在根目录下创建一个文件夹routes存储路由

现在我在routes文件夹下创建俩个路由文件index.js和users.js

修改app.js

//app.js
var express = require('express');
var path = require('path');
var app = express();

var index = require('./routes/index');
var users = require('./routes/users');

app.use('/', index);
app.use('/users', users);

app.listen(3000);

这样表示http://localhost:3000/的路由交给index处理 
http://localhost:3000/users的路由交给users处理

下面简单的实现一下路由

//routes/index.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res){
  res.end('index');
});

router.get('/123', function(){
  res.end(123);
});

module.exports = router;

 

//routes/users.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.end('users');
});

module.exports = router;

通过express.Router()创建的router就像一个mini版的app一样

app能做的,router都能做 

只是我们把逻辑都封装到了各个路由模块中

上面代码的结果:

 

body-parser中间件

其实express在3.x版本中内置了很多中间件

但是4.x版本就将出static以外的所有中间件全部抽离出来了

所以就需要我们单独安装

对照表如下:

Express 3.0Express 4.0
bodyParserbody-parser
compresscompression
cookieSessioncookie-session
loggermorgan
cookieParsercookie-parser
sessionexpress-session
faviconstatic-favicon
response-timeresponse-time
error-handlererrorhandler
method-overridemethod-override
timeoutconnect-timeout
vhostvhost
csrfcsurf

刚才就提到了POST请求有所不同

不同的地方就在于我们需要body-parser这个中间件来处理数据

通过req.body来获得数据

首先使用前不要忘记下载

npm install body-parser --save
//app.js
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.get('/', function(req, res){
  res.send('<form method="POST" action="./form">\
              <input type="text" name="user">\
              <input type="submit">\
            </form>');
});
app.post('/form', function(req, res){
  console.log(req.body);
  var user = req.body.user;
  res.send('账号: ' + user);
});

app.listen(3000);

 下面这四个方法分别用于对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这个命令行工具:

cnpm install -g express-generator

安装完成后,在命令行环境下执行“express --version”,可以看到express的版本是4.16.1。

好了,现在我们使用express命令来创建一个默认的网站。

在命令行环境下导航到node.js这个目录下,执行下面的命令:

express FirstExpress

然后可以看到:

仔细看上面的图哦,它告诉了我们三类非常重要的信息:

express命令创建的网站的目录结构以及创建的文件

安装依赖(进入到HelloExpress下,执行npm install)

使用npm start启动网站(express 4.x后)

按照响应的提示依次执行:

cd FirstExpress

cnpm install

npm start

很快就可以看到下面的图:

看到上图,说明网站已正常运行。你可以在浏览器里访问http://localhost:3000,然后就可以看到这个页面:

到这里,express框架就搭建成功!

最后附上API中文地址:https://cloud.tencent.com/developer/section/1489347

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值