Connect模块背景

Node.js的愿望是成为一个能构建高速,可伸缩的网络应用的平台,它本身具有基于事件,异步,非阻塞,回调等特性,这在前几篇专栏中有过描述。 正是基于这样的一些特性,Node.js平台上的Web框架也具有不同于其他平台的一些特性,其中Connect是众多Web框架中的佼佼者。
Connect在它的官方介绍中,它是Node的一个中间件框架。超过18个捆绑的中间件和一些精选第三方中间件。尽管Connect可能不是性能最好的 Node.jsWeb框架,但它却几乎是最为流行的Web框架。为何Connect能在众多框架中胜出,其原因不外乎有如下几个:

  • 模型简单
  • 中间件易于组合和插拔
  • 中间件易于定制和优化
  • 丰富的中间件

Connect自身十分简单,其作用是基于Web服务器做中间件管理。至于如何如何处理网络请求,这些任务通过路由分派给管理的中间件们进行处理。 它的处理模型仅仅只是一个中间队列,进行流式处理而已,流式处理可能性能不是最优,但是却是最易于被理解和接受。基于中间件可以自由组合和插拔的情况,优 化它十分容易。
Connect模块目前在NPM仓库的MDO(被依赖最多的模块)排行第八位。但这并没有真实反映出它的价值,因为排行第五位的Express框架实际上是依赖Connect创建而成的。关于Express的介绍,将会在后续的专栏中一一为你讲解。

中间件

让我们回顾一下Node.js最简单的Web服务器是如何编写的:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

我们从最朴素的Web服务器处理流程开始,可以看到HTTP模块基于事件处理网络访问无外乎两个主要的因素,请求和响应。同理的是Connect的中间件也是扮演这样一个角色,处理请求,然后响应客户端或是让下一个中间件继续处理。如下是一个中间件最朴素的原型:

 function (req, res, next) {
  // 中间件
}

在中间件的上下文中,有着三个变量。分别代表请求对象、响应对象、下一个中间件。如果当前中间件调用了res.end()结束了响应,执行下一个中间件就显得没有必要。

流式处理

为了演示中间件的流式处理,我们可以看看中间件的使用形式:

var app = connect();

// Middleware
app.use(connect.staticCache());
app.use(connect.static(__dirname + '/public'));
app.use(connect.cookieParser());
app.use(connect.session());
app.use(connect.query());
app.use(connect.bodyParser());
app.use(connect.csrf());
app.use(function (req, res, next) {
  // 中间件
});
app.listen(3001);

Conncet提供use方法用于注册中间件到一个Connect对象的队列中,我们称该队列叫做中间件队列。

Conncet的部分核心代码如下,它通过use方法来维护一个中间件队列。然后在请求来临的时候,依次调用队列中的中间件,直到某个中间件不再调用下一个中间件为止。

app.stack = [];
app.use = function(route, fn){
  // …   // add the middleware
  debug('use %s %s', route || '/', fn.name || 'anonymous');
  this.stack.push({ route: route, handle: fn });   return this;

};

值得注意的是,必须要有一个中间件调用res.end()方法来告知客户端请求已被处理完成,否则客户端将一直处于等待状态。
流式处理也是Node.js中用于流程控制的经典模式,Connect模块是典型的应用了它。流式处理的好处在于,每一个中间层的职责都是单一的,开发者通过这个模式可以将复杂的业务逻辑进行分解。

路由

从前文可以看到其实app.use()方法接受两个参数,route和fn,既路由信息和中间件函数,一个完整的中间件,其实包含路由信息和中间件函数。路由信息的作用是过滤不匹配的URL。请求在遇见路由信息不匹配时,直接传递给下一个中间件处理。
通常在调用app.use()注册中间件时,只需要传递一个中间件函数即可。实际上这个过程中,Connect会将/作为该中间件的默认路由,它表示所有的请求都会被该中间件处理。
中间件的优势类似于Java中的过滤器,能够全局性地处理一些事务,使得业务逻辑保持简单。
任何事物均有两面性,当你调用app.use()添加中间件的时候,需要考虑的是中间件队列是否太长,因为每一层中间件的调用都是会降低性能的。为了提高性能,在添加中间件的时候,如非全局需求的,尽量附带上精确的路由信息。
以multipart中间件为例,它用于处理表单提交的文件信息,相对而言较为耗费资源。它存在潜在的问题,那就是有可能被人在客户端恶意提交文件,造成服务器资源的浪费。如果不采用路由信息加以限制,那么任何URL都可以被攻击。

app.use("/upload", connect.multipart({ uploadDir: path })); 

加上精确的路由信息后,可以将问题减小。

MVC目录

借助Connect可以自由定制中间件的优势,可以自行提升性能或是设计出适合自己需要的项目。Connect自身提供了路由功能,在此基础上,可 以轻松搭建MVC模式的框架,以达到开发效率和执行效率的平衡。以下是笔者项目中采用的目录结构,清晰地划分目录结构可以帮助划分代码的职责,此处仅供参 考。

├── Makefile // 构建文件,通常用于启动单元测试运行等操作
├── app.js // 应用文件
├── automation  // 自动化测试目录
├── bin  // 存放启动应用相关脚本的目录
├── conf  // 配置文件目录
├── controllers  // 控制层目录
├── helpers  // 帮助类库
├── middlewares  // 自定义中间件目录
├── models  // 数据层目录
├── node_modules  // 第三方模块目录
├── package.json  // 项目包描述文件
├── public  // 静态文件目录
│   ├── images  // 图片目录
│   ├── libs  // 第三方前端JavaScript库目录
│   ├── scripts  // 前端JavaScript脚本目录
│   └── styles  // 样式表目录
├── test  // 单元测试目录
└── views  // 视图层目录

Connect模块解析的更多相关文章

  1. Connect模块解析 转载

    来自对<了不起的Node.js>一书的学习ConnectNode.js为常规的网络应用提供了基本的API.然而,实际情况下,绝大部分网络应用都需要完成一系列类似的操作,这些类似的操作你一定 ...

  2. 深入浅出Node.js---Connect模块解析 。转载

    文章地址:https://blog.csdn.net/zhangyuan19880606/article/details/51509205 1 Connect模块背景 Node.js的愿望是成为一个能 ...

  3. django 数据库连接模块解析及简单长连接改造

    django 数据库连接模块解析及简单长连接改造工作中纯服务端的项目用到了线程池和django的ORM部分.django 的数据库连接在每一个线程中开启一份,并在查询完毕后自动关闭连接. 线程池处理任 ...

  4. TypeScript 素描 - 模块解析、声明合并

    模块解析 模块解析有两种方式 相对方式  也就是以/或 ./或-/开头的,比如import jq  from "/jq" 非相对方式  比如 import model  from ...

  5. python-pcap模块解析mac地址

    python-pcap模块解析mac地址 作者:vpoet mail:vpoet_sir@163.com import pcap import binascii a = pcap.pcap() a.s ...

  6. webpack模块解析

    前面的话 在web存在多种支持JavaScript模块化的工具(如requirejs和r.js),这些工具各有优势和限制.webpack基于从这些系统获得的经验教训,并将模块的概念应用于项目中的任何文 ...

  7. TypeScript和Node模块解析策略

    一般我们在模块化编码时,总会导入其它模块,通常我们使用如下语法: import { A } from './a'; // ES6语法 import { A } from 'a'; var A = re ...

  8. 利用Bioperl的SeqIO模块解析fastq文件

    测序数据中经常会接触到fastq格式的文件,比如说拿到fastq格式的原始数据后希望查看测序碱基的质量并去除低质量碱基.一般而言大家都是用现有的工具,比如说fastqc这个Java写的小程序,确实很好 ...

  9. optparse模块解析命令行参数的说明及优化

    一.关于解析命令行参数的方法 关于“解析命令行参数”的方法我们一般都会用到sys.argv跟optparse模块.关于sys.argv,网上有一篇非常优秀的博客已经介绍的很详细了,大家可以去这里参考: ...

随机推荐

  1. 在WPF中使用CefSharp嵌入浏览器

    日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中.下面我们使用CefSharp嵌入浏览器来实现. 首先先介绍一下CefSharp嵌入式浏览器,它是基于Google浏览器的一个组件,我们可以在 ...

  2. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  3. hibernate base

    第一个类:Person.java package org.crazyit.app.domain; import java.io.Serializable;import java.util.ArrayL ...

  4. 直接拿来用!最火的Android开源项目(二)(转)

    GitHub上的开源项目不胜枚举,通过这些项目,也能让开发者在应用开发过程中事半功倍,作为开发者的你,在用这些开源项目吗?今天我们将介绍另外20个在GitHub上备受欢迎的Android开源项目,你准 ...

  5. loj 1036(dp)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25913 思路:易证存在一条从左上角到右下角的折线,沿着格子边缘的. ...

  6. 滑动listview隐藏和显示顶部布局

    需求: 1.listview向下滑动时,隐藏顶部布局 2.listview向上滑动到最上面,显示顶部布局 3.顶部布局的隐藏和显示有过渡效果 4.第一次加载listview时,顶部不要隐藏 布局: 注 ...

  7. cvKMeans2函数用法概述

    一般情况下,我们通过C++/Matlab/Python等语言进行实现K-means算法,结合近期我刚刚学的C++,先从C++实现谈起,C++里面我们一般采用的是OpenCV库中写好的K-means函数 ...

  8. 用js完成毫秒格式数据的日期格式化任务

    后台传过来的数据  creationTime  在后台是Date类型的 毫秒转换成  05-24  月 日格式的 //获得月日得到日期oTime function getMoth(str){ var  ...

  9. Ipython console in Spyder stuck on “connecting to kernel”

    简短地记录下,今天排除的spyder的BUG, 现象:打开Spyder时其他正常,但是Ipython console 不能正常获取到kernel,一直转圈,显示“connecting to kerne ...

  10. DHCP欺骗(DHCP Sproofing)

    DHCP欺骗(DHCP Sproofing)   DHCP Sproofing同样是一种中间人攻击方式.DHCP是提供IP地址分配的服务.当局域网中的计算机设置为自动获取IP,就会在启动后发送广播包请 ...