将js进行到底:node学习5
HTTP开发之Connect工具集——中间件
继学习node.js的TCP API和HTTP API之后,node.js web开发进入了正轨,但这就好像Java的servlet一样,我们不可能使用最基础得Servlet对象去写网站,我们也不能使用最基本的node http API去写一个完整得网站,我们需要更加强大得工具集,web套件,甚至是web开发框架(诸如Java下的Spring MVC),来提供开发者更人性化得web开发环境。
创建网站的基本任务——为何要有中间件
- 独立托管静态文件,诸如:html,css,js,images
- 处理错误和不存在的地址
- 处理不同类型的请求
如果我们上来就直接用上一章的http模块来做的话,我们需要先实现一个“框架”才能做到一个网站最基本的任务,如果是运用生产环境的话,我们希望有这样的一个“框架”——connect工具集,最好称它为工具集,他离所谓的“框架”依旧有点差距。
Connect是基于http API之上的,也就是基于node http模块写出来的,方便web开发者使用,他提供了一些工具方法能够上一些重复性的工作便于实现,让开发者更加专注于应用的功能业务。
Connect已经是十分基础的node web开发工具集,在实际开发中很少看到,以后回介绍稍微高级点的express(对于实际开发来说依然很基础)
特别注意:《了不起的node.js》一书中的代码和connect版本过时了,如果使用最新版的connect需要参照如下方法使用!
导入Connect等中间件模块
Connect模块并非node.js的原生模块,需要引入外部模块
同时还要导入“serve-static”,“content-disposition”提供静态文件访问支持
最终完整package.json:
{
"name":"node-connect",
"version":"0.0.1",
"description":"Use connect to create a website",
"dependencies":{
"connect":"latest",
"serve-static":"latest",
"content-disposition":"latest"
}
}
node npm包搜索管理网站:https://www.npmjs.com/
注:除了connect外,还导入了serve-static,这个包原本属于connect集合,后官方独立出来了,《了不起的node.js》使用的是1.8.x版本的connect(太老了)还包含着static中间件,这里使用了3.0.0+的版本,则需要额外导入这个静态中间件模块。
这些是官网独立的中间件(Connect/Express负责管理)
将不同功能的中间件从connect独立出来是一件好事,方便管理维护!(对于开发者需要注意查看更新)
npm install
引用connect模块
//引入connect模块
var connect = require("connect");
//依然需要引入http模块
var http = require("http")
//依然使用http模块创建服务器
http.createServer().listen(3000);
connect现在是http中间件,如果使用本文最新的connect版本就不能出现《了不起的node.js》一书中的connect.createServer(),因为connect已经移除了这个方法!!!
createServer交给了http模块去做,充分体现了connect是中间件的特性,而不是代替http!
依然使用http.createServer()创建http服务器!!!
使用serve-static中间件托管静态文件
node本身不像nginx,apache,他不是一个完整的http服务器,而是一个语言解析器。
通过对node.js API的开发,可以构建类似nginx一样的功能,负责提供用户静态页面,这就需要用到serve-static中间件
首先serve-static中间件原本属于connect中间件,现在已经独立出来了,也就说其实和connect关系已经不大了,但我依然将两者放在一回中解说。
静态文件指的是:html,css,图片,js等等
在项目目录下新建一个views目录,存放静态html文件
新建index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>hello world</h1>
</body>
</html>
index.js返回静态页面代码:
//引入http模块
var http = require("http");
//引入serveStatic模块
var serveStatic = require('serve-static')
var finalhandler = require('finalhandler');
var serve = serveStatic(__dirname+'/views',{'index':['index.html','index.htm']});
http.createServer(function(req,res){
serve(req,res,finalhandler(req,res));
}).listen(3000);
finalhandler是什么?
作用是友好处理找不到页面访问不到URL的异常和错误,如果删除,用户访问非法地址将会导致node抛出异常停止工作。
访问首页之外的页面?
views下创建一个hello.html,直接在浏览器地址后面+“/hello.html”即可访问这个页面。
访问图片文件?
如何提示下载文件?
var contentDisposition = require('content-disposition')
var finalhandler = require('finalhandler')
var http = require('http')
var serveStatic = require('serve-static')
var serve = serveStatic(__dirname+'/files', {
'index': false,
'setHeaders': setHeaders
})
//强制下载
function setHeaders (res, path) {
res.setHeader('Content-Disposition', contentDisposition(path))
}
http.createServer(function onRequest (req, res) {
serve(req, res, finalhandler(req, res))
}).listen(3000);
新建一个files目录,下载的文件放在里面即可。
到此,serve-static中间件简化了开发者托管静态文件的代码,我们不必向上一章那样使用fs+http方式去自己实现输出流文件给浏览器客户端。
使用connect中间件处理不同的请求
在上一回中,如果要对用户不同访问给出对应的返回,我们需要在同一个createServer中不停的写if...else if....else if...else....if.........来判断,这样显得代码十分冗余,而且根本无法把所有情况写清楚,也无法扩展,且根本无法维护。
上一回的部分代码:
//请求为图片
if(req.method == 'GET' && req.url.substr(-4)==".jpg"){
fs.stat(__dirname+req.url,function(err,stat){
if(err || !stat.isFile()){
res.writeHead(404);
res.end("找不到图片");
return;
}
serve(__dirname+req.url,'application/x-jpg');
});
}else if(req.method=="GET" && req.url=='/'){
//请求为html文件
serve(__dirname+'/form.html','text/html');
}else{
res.writeHead(404);
res.end("网址丢了");
return;
}
接下来使用connect重写这些代码:(代码是基于static-serve那块修改过来的)
//下载文件模块
var contentDisposition = require('content-disposition')
//不需要finalhandler
//var finalhandler = require('finalhandler')
//http模块创建http服务器必须
var http = require('http')
//静态文件托管中间件
var serveStatic = require('serve-static')
//connect工具集
var connect = require("connect");
var app = connect();
app.use(function(req,res,next){
//任何请求都会打印!是必然执行的一步
console.error('%s %s',req.method,req.url)
next();
});
//图片显示
app.use("/images",function(req,res,next){
serveStatic(__dirname+"/images")(req,res,next);
});
//下载文件
app.use("/files",function(req,res,next){
serveStatic(__dirname+"/files",{'index':false,'setHeaders':setHeaders})(req,res,next);
});
//最终处理,所有next都执行不通后到达此处
app.use(function(req,res,next){
res.writeHead(404);
res.end('404 Not Found')
//没有next了,这是最终方法,返回404 not found就行了
});
//强制下载函数
function setHeaders (res, path) {
res.setHeader('Content-Disposition', contentDisposition(path))
}
//建立http服务器
http.createServer(app).listen(3000);
注意到我们依然需要http模块来建立http服务器,然后引入了connect模块,以及之前的serve-static和content-disposition。
这一段代码实际上是把上一回分类请求处理和这一回静态文件托管强强联手了
如果说serve-static这个中间件解决的是静态文件托管的话,那么connect中间件其实是解决了路由,请求定向的控制。这样我们不再需要通过手写的if...else来判断用户请求了什么类型的文件。
next()函数
这个函数在connect中扮演了十分重要的角色,作用:将不同种类的请求线性的串联在一行,每一个app.use()其实类似于原来我们写的if...else语句,next就是在处理不了的情况下,执行另一个app.use(),这样只要回掉函数做不了就抛给下一个做,这样不停的“甩锅”,最终谁都做不了就有一个最终函数,开发者需要建立这样的最终函数,里面没有next()了,说明到最后一步了,必须返回错误给用户看了。我们这里最终函数是一个404错误反馈。
use()函数
第一个参数可以给定一个请求的目录,相对于node执行的项目目录,相当于浏览器网址后面第一个“/”后面的参数。
将js进行到底:node学习5的更多相关文章
- 【特别推荐】Node.js 入门教程和学习资源汇总
这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...
- Node.js 入门教程和学习资源汇总
这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...
- Node.js环境搭建和学习(windwos环境)
Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...
- node 学习笔记 - Modules 模块加载系统 (1)
本文同步自我的个人博客:http://www.52cik.com/2015/12/11/learn-node-modules-path.html 用了这么久的 require,但却没有系统的学习过 n ...
- [学姿势]实验室搬砖+node学习
这周开始进行收尾工作,我当然没有进行核心技术的开发,主要负责的是对web端进行展示上的修修补补,主要包括添加VLC播放器.rtsp视频流以及一些js细节. 1.VLC 全称为Video Lan Cli ...
- 2015第40周二Node学习
node历史 今天看cnode开源项目用了io.js,在查这个项目时发现这篇文章node历史,node.js和io.js关系谈到Node.js的由来,不可避免要聊到它的创始人Ryan Dahl.在20 ...
- 2015第40周一Node学习
node学习尝试 早上看了张丹大牛博客文章nodeJS学习路线图和node从零入门系列,感觉获益匪浅,尝试了里面几项内容,对node有了更深入的认识. npm npm是一个node包管理和分发工具,已 ...
- Node学习——开篇
前言:自从下决心转学前端以来,我的专业课java基本荒废了,所以对于后台开发的逻辑也已基本忘干净了.但是作为一名准前端程序猿,我认为还是有必要了解后端开发的,虽不必深入学习,但是能够了解项目从前端到后 ...
- node 学习资料
Node 学习资料: 资料名称 网址 Node.js 中文API文档 http://nodejs.cn/api/ Node 菜鸟教程 http://www.runoob.com/nodejs/node ...
- Node学习HTTP模块(HTTP 服务器与客户端)
Node学习HTTP模块(HTTP 服务器与客户端) Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端.http.Server 是一个基 ...
随机推荐
- android studio compile api implementation 区别
compile与api 二者等同,无区别 implementation与compile或implementation与api implementation编译的依赖只作用于当前的module.即APP ...
- java读取本地json数组并解析
1.本地json位置 2,json数据 {"garbages":[{"id":"/m/011k07","ename":& ...
- 深入理解spring中的AOP原理 —— 实现MethodInterceptor接口,自已动手写一个AOP
1.前言 AOP是面向切面编程,即“Aspect Oriented Programming”的缩写.面对切面,就是面向我们的关注面,不能让非关注面影响到我们的关注面.而现实中非关切面又必不可少,例 ...
- thrift生成c++服务端和客户端
https://blog.csdn.net/jdx0909/article/details/84727523 https://blog.csdn.net/luoyexuge/article/detai ...
- Excel文件比较工具的使用
本工具用于比较两个文件夹中对应Excel工作簿中单元格数据是否不同. 如果有内容不同的单元格,就在结果报告中表示出来. 点击如下链接,下载. Excel文件比较工具.rar 解压缩后,看到1个exe文 ...
- binary-heap(二叉堆)原理及C++代码实现
二叉堆可以看做一个近似的完全二叉树,所以一般用数组来组织. 二叉堆可以分为两种形式:最大堆和最小堆.最大堆顾名思义,它的每个结点的值不能超过其父结点的值,因此堆中最大元素存放在根结点中.最小堆的组织方 ...
- [LC] 350. Intersection of Two Arrays II
Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...
- day47-线程-锁和死锁
#1.锁:防止多个线程同时读写某一块内存区域. from threading import Thread from threading import Lock def func(): global n ...
- Java 网址短链接服务原理及解决方案
一.背景 现在在各种圈的产品各种推广地址,由于URL地址过长,不美观.不方便收藏.发布.传播以及各种发文字数限制等问题,微信.微博都在使用短链接技术.最近由于使用的三方的生成.解析短链接服务开始限制使 ...
- Excel-DNA项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【C#版】
Excel-DNA项目中的自定义功能区和自定义任务窗格需要用到各种命名空间.添加所需文件,才能实现.后来我发现可以把所有代码都写在Class1.cs这个默认文件中. 大家可以在Visual Studi ...