使用Express进行Web开发

一、简介

1、Node.js的原始封装程度较低,在进行Web开发时,不像其他语言(比如Java)那样不需要开发者直接处理HTTP协议。它提供的http模块仅仅是一个HTTP服务器内核的封装。使用第三方模块Express就可以很轻松的进行Web开发,因为它为http模块提供了更高层的接口,且还提供了其他许多功能,它只是一个轻量级的Web框架,多数功能只是对HTTP协议中常用操作的封装。

二、安装Express

1、在Node.js中如果一个包是某个工程依赖,那么需要在工程的目录下使用本地模式安装这个包,如果要通过命令行调用这个包中的命令,则需要用全局模式安装。这里的express虽是为工程所用,但是Express提供了快速开始工具,这个工具的功能通常是建立一个网站最小的基础框架,在此基础上完成开发(当然也可以不使用工具而手动建立)。为了使用这个工具,所以需要用全局模式安装Express,因为只有这样才能在命令行中使用它,安装命令为:npm install -g express

三、使用Express工具建立网站基本结构

1、Express在初始化一个项目的时候需要指定模板引擎,默认支持Jade。如下图:

2、为了采用ejs模版引擎,所以采用此命令建立网站基本结构:express -e 项目名。如下图:

该命令会在当前目录下建立子目录NodeWeb,并且产生了一些文件。打开该命令建立的package.json文件,如下:

注意观察这里还依赖了express和ejs模块,所以还需要安装这些模块,再观察建立网站基本结构的命令结果中,可以发现可以进入到该项目目录下并使用命令npm install安装这些依赖,npm install的功能就是检查当前目录下的package.json文件,并自动安装所有指定的依赖。安装依赖如下图:

它就会在项目目录下建立目录node_modules,并将依赖安装在其中,如下图:

四、启动服务器

1、用Express实现的网站实际上就是一个Node.js程序,因此可以直接运行。运行命令:node app.js或node app,即可启动服务器。

 

然后就可以在浏览器中进行访问了,如下图:

2、要关闭服务器的话,在终端中按Ctrl + C。

3、注意:如果对代码做了修改,要想看到修改后的效果必须重启服务器。还可以使用supervisor实现监视代码修改和自动重启,安装命令为:npm install -g supervisor。因为要在命令行中使用supervisor,所以安装模式为全局模式,如下图:

然后用supervisor启动服务器就可以实现代码监视和自动重启,如下图:

五、Express建立的工程结构

 

六、路由控制

1、请求过程解析

当启动服务器并在浏览器输入http://localhost:3000/进行访问,那么请求的方式为GET,请求的路径为/。然后服务器端的app.js会解析请求的路径并调用相应的逻辑,在app.js中又这么一语句:app.get('/', routes.index);,它的作用是规定当请求路径为“/”的GET请求由routes.index函数处理,也就是routes文件夹中index.js中的index函数处理,而index.js文件中的index处理函数通过res.render('index', { title: 'Express' }) 调用视图模板index,也就是view目录中的index.ejs文件,传递title变量给它,最终视图模板生成HTM 页面,返回给浏览器。该HTML页面中包含一个“/stylesheets/style.css”的css文件引用,所以浏览器在接收到内容以后会再次向服务器发起请求。但是app.js中并没有一个路由规则指派到/stylesheets/style.css,但是在app.js中有这么一条语句:app.use(express.static(path.join(__dirname, 'public')));,通过它配置了静态文件服务器,因此/stylesheets/style.css会定向到app.js所在目录中的文件public/stylesheets/style.css,最后向客户端返回css文件内容。所以由Express创建的网站架构如下图:这是一个MVC架构。

2、创建路由规则

创建一个/hello的路由,首先,在app.js文件中在已有的路由规则app.get('/', routes.index)后面添加一行,内容如下:

app.get('/hello', routes.hello);

然后修改routes/index.js,增加hello函数,如下:在这个控制器中并没有访问模型和试图,仅仅向客户端返回系统当前事件而已

exports.hello = function(req, res) {
	res.send('The time is ' + new Date().toString());
};

然后访问/hello(如果没有使用supervisor,要重启服务器),就能得到系统时间,如下图:

app.get是路由规则创建函数,它接受两个参数,第一个参数是请求的路径,第二个参数是一个回调函数,该路由规则被触发时调用回调函数,其参数列表传递两个参数,分别是req和res,表示请求信息和响应信息。

3、路径匹配

除了上面为固定的路径设置路由规则,Express还支持高级的路径匹配模式,如果要为路径为/user/[username]的路径([username]是可变的)配置路由,则可以采用下面的方式:

app.get('/user/:username', function(req, res) {
	res.send('user: ' + req.params.username);
});

注意:这里将回调函数直接写在了get函数里面,而且'/user/:username'中的username是可以随便指定名字的,比如改成uname,那么req.params.username中的username也要改成uname。执行效果如下:

其实像这样的(/user/:username)路径规则会被自动编译为正则表达式,类似于 \/user\/([^\/]+)\/?这样的形式,且路径参数可以在响应函数中通过req.params的属性访问。

路径规则同样支持JavaScript 正则表达式,例如app.get(\/user\/([^\/]+)\/?, callback)。这样可以定义更加复杂的路径规则,不同之处是匹配的参数是匿名的,因此需要通过req.params[0]、req.params[1]这样的形式访问。

4、REST风格的路由规则

Express支持REST风格的请求方式。REST的意思是表征状态转移(Representational State Transfer),它是一种基于HTTP协议的网络应用的接口风格,充分利用HTTP的方法实现统一风格接口的服务。根据REST设计模式,HTTP1.1协议定义了的8种标准的方法中常用的4种通常分别用于实现以下功能:GET:获取、POST:新增、PUT:更新、DELETE:删除。这是因为这4种方法有不同的特点,按照定义,它们的特点如下图:

其中安全是指没有副作用,即请求不会对资源产生变动,连续访问多次所获得的结果不受访问者的影响。而幂等指的是重复请求多次与一次请求的效果是一样的,比如获取和更新操作是幂等的,这与新增不同。删除也是幂等的,即重复删除一个资源,和删除一次是一样的。

Express对8种HTTP请求方法都设计了不同的路由绑定函数,例如前面例子全部是app.get,表示为该路径绑定了GET请求,向这个路径发起其他方式的请求不会被响应。Express支持的所有HTTP请求的绑定函数如下图:需要注意的是app.all 函数,它支持把所有的请求方式绑定到同一个响应函数。

5、控制权转移

Express支持同一路径绑定多个路由响应函数,如下:

app.all('/user/:username', function(req, res) {
	res.send('all methods captured');
});
app.get('/user/:username', function(req, res) {
	res.send('user: ' + req.params.username);
});

但是当访问任何被这两条同样的规则匹配到的路径时,会发现请求总是被前一条路由规则捕获,后面的规则会被忽略。原因是Express在处理路由规则时,会优先匹配先定义的路由规则,因此后面相同的规则被屏蔽。

Express提供了路由控制权转移的方法,即回调函数的第三个参数next,通过调用next(),会将路由控制权转移给后面的规则,如下:

app.all('/user/:username', function(req, res, next) {
	//res.send('all methods captured');
	console.log('all methods captured');
	next();
});
app.get('/user/:username', function(req, res) {
	res.send('user: ' + req.params.username);
});

结果如下图:会发现终端中打印了“all methods captured”,而且浏览器中显示了“user: cdu09"。这说明请求先被第一条路由规则捕获,完成console.log打印功能后使用next()转移控制权,又被第二条规则捕获,向浏览器返回了信息。

该功能可以轻易地实现中间件,而且还能提高代码的复用程度。比如针对一个用户查询信息和修改信息的操作,分别对应了GET和PUT操作,而两者共有的一个步骤是检查用户名是否合法,因此可以通过next()方法实现,如下:

app.all('/user/:username', function(req, res, next) {
	//检查用户是否为cdu09
	if(req.params.username == 'cdu09') {
		next();
	} else {
		next(new Error(req.params.username + ' does not exist.'));
	}
});
app.get('/user/:username', function(req, res) {
	res.send('Get: ' + req.params.username);
});
app.put('/user/:username', function(req, res) {
	res.send('Put: ' + req.params.username);
});

用get方式请求结果如下图:

七、模板引擎

待续。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值