Node.js:用JavaScript写服务器端程序-介绍并写个MVC框架

 

(注:1、本文基于Node.js V0.3.6; 2、本文假设你了解JavaScript; 3、本文假设你了解MVC框架;4、本文作者:QLeelulu,转载请注明出处。5、本文示例源代码learnNode.zip)

Node.js是什么

Node让你可以用javascript编写服务器端程序,让javascript脱离web浏览器的限制,像C#、JAVA、Python等语言一样在服务器端运行,这也让一些熟悉Javascript的前端开发人员进军到服务器端开发提供了一个便利的途径。 Node是基于Google的V8引擎封装的,并提供了一些编写服务器程序的常用接口,例如文件流的处理。Node的目的是提供一种简单的途径来编写高性能的网络程序。

Node.js的性能

hello world 测试:

clip_image002

300并发请求,返回不同大小的内容:

clip_image004

为什么node有如此高的性能?看node的特性。

Node.js的特性

1. 单线程

2. 非阻塞IO

3. Google V8

4. 事件驱动

更详细的了解node请看淘宝UED博客上的关于node.js的一个幻灯片:http://www.slideshare.net/lijing00333/node-js

你好,世界

这,当然是俗套的Hello World啦(hello_world.js):

1/home/qleelulu/.node_modules/http
2/home/qleelulu/.node_modules/http.js
3/home/qleelulu/.node_modules/http.node
4/home/qleelulu/.node_modules/http/index.js
5/home/qleelulu/.node_modules/http/index.node
6/home/qleelulu/.node_libraries/http
7/home/qleelulu/.node_libraries/http.js
8、参考前面
 

复制代码

再看回前面的代码,http.createServer中的回调函数中的request注册了两个事件,前面提到过node的一个特点是事件驱动的,所以这种事件绑定你会到处看到(想想jQuery的事件绑定?例如$('a').click(fn))。关于node的事件我们在后面再细说。request对象的data事件会在接收客户端post上来的数据时候触发,而end事件则会在最后触发。所以我们在data事件里面处理接收到的数据(例如post过来的form表单数据),在end事件里面通过handlerRequest 函数来统一处理所有的请求并分发给相应的controller action处理。

handlerRequest的代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

var route = require('./route');

var handlerRequest = function(req, res){

//通过route来获取controller和action信息

var actionInfo = route.getActionInfo(req.url, req.method);

//如果route中有匹配的action,则分发给对应的action

if(actionInfo.action){

//假设controller都放到当前目录的controllers目录里面,还记得require是怎么搜索module的么?

var controller = require('./controllers/'+actionInfo.controller); // ./controllers/blog

if(controller[actionInfo.action]){

var ct = new controllerContext(req, res);

//动态调用,动态语言就是方便啊

//通过apply将controller的上下文对象传递给action

controller[actionInfo.action].apply(ct, actionInfo.args);

}else{

handler500(req, res, 'Error: controller "' + actionInfo.controller + '" without action "' + actionInfo.action + '"')

}

}else{

//如果route没有匹配到,则当作静态文件处理

staticFileServer(req, res);

}

};

这里导入来一个route模块,route根据请求的url等信息去获取获取controller和action的信息,如果获取到,则通过动态调用调用action方法,如果没有匹配的action信息,则作为静态文件处理。

下面是route模块的代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

var parseURL = require('url').parse;

//根据http请求的method来分别保存route规则

var routes = {get:[], post:[], head:[], put:[], delete:[]};

/**

* 注册route规则

* 示例:

* route.map({

* method:'post',

* url: /\/blog\/post\/(\d+)\/?$/i,

* controller: 'blog',

* action: 'showBlogPost'

* })

*/

exports.map = function(dict){

if(dict && dict.url && dict.controller){

var method = dict.method ? dict.method.toLowerCase() : 'get';

routes[method].push({

u: dict.url, //url匹配正则

c: dict.controller,

a: dict.action || 'index'

});

}

};

exports.getActionInfo = function(url, method){

var r = {controller:null, action:null, args:null},

method = method ? method.toLowerCase() : 'get',

// url: /blog/index?page=1 ,则pathname为: /blog/index

pathname = parseURL(url).pathname;

var m_routes = routes[method];

for(var i in m_routes){

//正则匹配

r.args = m_routes[i].u.exec(pathname);

if(r.args){

r.controller = m_routes[i].c;

r.action = m_routes[i].a;

r.args.shift(); //第一个值为匹配到的整个url,去掉

break;

}

}

//如果匹配到route,r大概是 {controller:'blog', action:'index', args:['1']}

return r;

};

map方法用于注册路由规则,我们新建一个config.js的文件,来配置route规则:

?

1

2

3

4

5

6

7

8

//config.js

var route = require('./route');

route.map({

method:'get',

url: /\/blog\/?$/i,

controller: 'blog',

action: 'index'

});

如果请求的url有匹配的route规则,则会返回controller和action信息。例如上面的route配置,当访问 /blog 这个url的时候,则会调用 ./controllers/blog.js 模块里面的index函数。

当调用action的时候,会传递controllerContext给acation:

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值