node.js与dojo完美的融合-开发完全面向对象化
发布于 3年前 作者 cory 3763 次浏览

最近学习了一下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包导入进去:

Project结构图
最外层的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啦。
运行效果:
Hello World

这样,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配置等。这样更有利于学习成本的降低,减少开发大型后台的人力、时间成本等。

2 回复

这里用到的define方法是什么啊?

觉得还是不要让 dojo 框架染指 node,,哪怕基础库也没必要……

回到顶部