最近学习了一下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(path=["/", "/index"]) displayIndex: function() { console.debug(""cory.Page.displayIndex" was called"); var res = this.get("response"); if (res) { var body = ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''+ ''; res.writeHead(200, {"Content-Type": "text/html"}); res.write(body); res.end(); } }, //@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(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配置等。这样更有利于学习成本的降低,减少开发大型后台的人力、时间成本等。
参与回复
登录后即可参与回复。登录