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