最近学习了一下node.js,由于我是dojo出身,所以,觉得node.js并不是非常的面向对象化,并不满足面向对象的几个基本条件“封装”、“继承”、“多态”、“重载”等,虽然这些条件,JS是可以模拟出来的,但是重复的造轮子,会使得开发低下,性能堪忧。于是乎鄙人打算写一个node.js的OO module,然后看了一下dojo1.7的源码,发现原来,dojo1.7已经开始支持node.js了,这样就非常好了,我也不必去造轮子了。好了,废话少说,让我们来来看看,dojo是如何进入node.js的上下文的吧。
该文章分两个部分:
1.我们来做一个小的test,来验证dojo是否已加入node.js的上下文中;
2.我们把nodebeginner里面的一个上传图片的例子,用dojo来完成。
第一部分:
开发环境我们可以采用eclipse来完成。将dojo包导入进去:
最外层的dojo文件夹中放入的是dojo库。
我们在这个工程中,新建一个入口类Main.js
(function() {
this.dojoConfig = {
has: {
"host-node": 1
}
};
require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”);
define("Main", [], function() {
console.info(“Hello World!”);
});
})();
这里说明一下,this表示的是node.js的上下文,这里给dojo设置host-node,因为dojo默认的模式是host-browser(浏览器窗口模式)。这里还要把dojo.js这个文件require进来,这样就OK啦。
运行效果:
这样,dojo就很轻松的融入到node.js的环境中了,是不是很简单^^¥。好了,下面在第二部分中我们来做一个上传文件的实例来表现dojo在开发node.js这一块强大的OO技术吧。(BTW:上传文件这个例子其实很简单,但是为了表现出用OO的形式来开发node.js,所以会故意写的有点复杂,请不要喷我<##>)
第二部分:
首先我们新建一个cory包,Main.js也需要稍微改一下,如下:
(function() {
this.dojoConfig = {
has: {
"host-node": 1
},
paths: {
cory: “…/…/cory”
}
};
require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”);
define("Main", [], function() {
console.info(“Hello World!”);
});
})();
paths就是注册自定义包的位置。这里cory包和最外层的dojo文件夹并列。
然后在cory包中,一共新建4个类,Server.js、UrlParser.js、Router.js、Page.js。
cory.Server:用于创建http服务器。
cory.UrlParser:用于解析URL。
cory.Router:将解析好URL中的pathname进行路由。
cory.Page:对应相应的URL做出逻辑处理。
下面就把各个类的代码展示给大家,主要是展示其语法,至于逻辑的话,nodebeginner.org有详细介绍。
cory.Server:
define([
"…/dojo/_base/kernel",
"…/dojo/_base/declare",
“…/dojo/Stateful”
], function(dojo, declare, Stateful) {
// summary:
// This server to listen the port which you setted.
return declare("cory.Server", Stateful, {
// default value
port: 8888,
_http: dojo.http,
postscript: function(args) {
this.inherited(arguments);
if (args && args.port) {
this.set("port", args.port);
}
},
start: function(/Function?/callback) {
console.debug(“Server is starting…”);
var _port = this.get(“port”);
this._http.createServer(function(request, response) {
callback(request, response);
}).listen(_port);
console.debug("Server has started. The port is " + _port + “.”);
}
});
});
cory.UrlParser:
define([“…/dojo/_base/declare”], function(declare) {
return declare("cory.UrlParser", null, {
parse2Pathname: function(/String/url) {
var pathname = dojo.url.parse(url).pathname;
console.debug("The current path name is: “” + pathname + “".”);
return pathname;
}
});
});
cory.Router:
define(["…/dojo/_base/declare", “…/dojo/Stateful”], function(declare, Stateful) {
return declare("cory.Router", Stateful, {
request: null,
response: null,
//根据不同的url地址名称,路由到不同的页面逻辑处理。
//返回是否路由成功。
rout: function(/Object/path, /String/pathname) {
console.debug("About to route a request for " + pathname);
var _classAndFunc = path[pathname];
var res = this.get(“response”);
if (!_classAndFunc) {
console.debug(“But this path was not found.”);
if (res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write(“404 Not found”);
res.end();
}
}
var _lastIndex = _classAndFunc.lastIndexOf(“.”);
var _className = _classAndFunc.substring(0, _lastIndex);
var _funcName = _classAndFunc.substring(_lastIndex + 1);
var _page = new dojo.getObject(_className)();
_page.set("request", this.get(“request”));
_page.set("response", res);
_page_funcName;
}
});
});
cory.Page:
define(["…/dojo/_base/declare", “…/dojo/Stateful”], function(declare, Stateful) {
return declare("cory.Page", Stateful, {
request: null,
response: null,
//[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@Page](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)(path=[“/", “/index”])
displayIndex: function() {
console.debug(“"cory.Page.displayIndex” was called”);
var res = this.get(“response”);
if (res) {
var body =
'<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; '+
<br/> 'charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post" enctype="multipart/form-data">'+
'<input type="file" name="upload" />'+
'<input type="submit" value="Upload file" />'+
'</form>'+
'</body>'+
'</html>';
res.writeHead(200, {"Content-Type": “text/html"});
res.write(body);
res.end();
}
},
//[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@Page](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)(path=[“/upload”])
upload: function() {
console.debug(“"cory.Page.upload” was called”);
var req = this.get(“request”),
res = this.get(“response”);
if (req && res) {
var form = new dojo.formidable.IncomingForm();
console.debug(“about to parse”);
form.parse(req, function(error, fields, files) {
console.debug(“parsing done.”);
dojo.fs.renameSync(files.upload.path, “C:\Documents and Settings\Cory\Local Settings\Temp\test.png”);
res.writeHead(200, {"Content-Type": “text/html"});
res.write(“received image:”);
res.write("");
res.end();
});
}
},
//[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@Page](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)](/user/Page)(path=[“/show”])
show: function() {
console.debug(“"cory.Page.show” was called”);
var res = this.get(“response”);
if (res) {
dojo.fs.readFile("C:\Documents and Settings\Cory\Local Settings\Temp\test.png", "binary", function(error, file){
if (error) {
res.writeHead(500, {"Content-Type": "text/plain"});
res.write(error + “\n”);
} else {
res.writeHead(200, {"Content-Type": "image/x-png"});
res.write(file, “binary”);
}
res.end();
})
}
}
});
});
Main.js也需要一点小改动:
(function() {
this.dojoConfig = {
has: {
"host-node": 1
},
paths: {
cory: “…/…/cory”
}
};
require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”);
var d = dojo;
["http", "url", "fs", “formidable”].forEach(function(requiredName) {
d[requiredName] = require(requiredName);
});
define("Main", [
"dojo/_base/kernel",
"cory/Server",
"cory/UrlParser",
"cory/Router",
“cory/Page”
], function(dojo, Server, UrlParser, Router) {
//这里将地址和类中的方法进行绑定。
//其中cory.Page是页面类,后面的.displayIndex、.upload、.show都是该类的方法。
var pathMap = {
"/": "cory.Page.displayIndex",
"/index": "cory.Page.displayIndex",
"/upload": "cory.Page.upload",
"/show": “cory.Page.show”
};
var server = new Server();
server.set("port", 8888);
server.start(function(request, response) {
var router = new Router();
router.set("request", request);
router.set("response", response);
router.rout(pathMap, new UrlParser().parse2Pathname(request.url));
});
});
})();
运行效果:
后台控制台运行效果:
怎么样,这样的面向对象的方式,让思路更清晰,要比nodebeginner上的例子,引用传来传去的清晰多了吧。
后记:如果采用dojo来开发node.js后台程序,那么,可以继续封装成,类似于servlet形式,甚至可以进行json配置等。这样更有利于学习成本的降低,减少开发大型后台的人力、时间成本等。