自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Node.js后端框架設(shè)計(jì)構(gòu)想

開發(fā) 前端
我打算把我的后端的框架定位為建站框架,本文是我的一些思路與初步實(shí)踐。如果園子里有做過后端框架的高手(不限語言),也請指教一下。以下是大概的流程。

后端的核心文件mass.js包含批量創(chuàng)建與刪除文件夾,MD5加密,類型識別與模塊加載等功能?,F(xiàn)在網(wǎng)站名與網(wǎng)站的路徑也還是混淆在里面,以后會獨(dú)立到一個(gè)配置文件中。只要運(yùn)行node mass.js這命令就立即從模板文件中構(gòu)建一個(gè)樣板網(wǎng)站出來。下面就是它建站的最主要代碼:

  1. //--------開始創(chuàng)建網(wǎng)站---------  
  2.  //你想建立的網(wǎng)站的名字(請修正這里)  
  3.  mass.appname = "jslouvre";  
  4.  //在哪個(gè)目錄下建立網(wǎng)站(請修正這里)  
  5.  mass.approot = process.cwd();  
  6.  //用于修正路徑的方法,可以傳N個(gè)參數(shù)  
  7.  mass.adjustPath = function(){  
  8.      [].unshift.call(arguments,mass.approot, mass.appname);  
  9.      return require("path").join.apply(null,arguments)  
  10.  }  
  11.  var dir = mass.adjustPath("")  
  12.  //  mass.rmdirSync(dir);//......  
  13.  mass.require("http,fs,path,scaffold,intercepters",function(http,fs,path,scaffold,intercepters){  
  14.      mass.log("<code style="color:blue;">=========================</code>",true)  
  15.      if(path.existsSync(dir)){  
  16.          mass.log("<code style="color:red">此網(wǎng)站已存在</code>",true);  
  17.      }else{  
  18.          fs.mkdir(dir,0755)  
  19.          mass.log("<code style="color:green">開始利用內(nèi)部模板建立您的網(wǎng)站……</code>",true);  
  20.      }  
  21.      global.mapper = scaffold(dir);//取得路由系統(tǒng)  
  22.      http.createServer(function(req, res) {  
  23.          var arr = intercepters.concat();  
  24.          //有關(guān)HTTP狀態(tài)的解釋 http://www.cnblogs.com/rubylouvre/archive/2011/05/18/2049989.html  
  25.          req.on("err500",function(err){  
  26.              res.writeHead(500, {  
  27.                  "Content-Type": "text/html"  
  28.              });  
  29.              var html = fs.readFileSync(mass.adjustPath("public/500.html"))  
  30.              var arr = []  
  31.              for(var i in err){  
  32.                  arr.push("<li>"+i+"  :   "+err[i]+" </li>")  
  33.              }  
  34.              res.write((html+"").replace("{{url}}",arr.join("")));  
  35.              res.end();  
  36.          });  
  37.          req.on("next_intercepter",function(){  
  38.              try{  
  39.                  var next = arr.shift();  
  40.                  next && next.apply(null,arguments)  
  41.              }catch(err){  
  42.                  req.emit("err500",err);  
  43.              }  
  44.          });  
  45.          req.emit("next_intercepter",req, res);  
  46.      }).listen(8888);  
  47.     console.log("start server in 8888 port")  
  48.  }); 

只要運(yùn)行mass.js,它會根據(jù)appname與approot判定目標(biāo)路徑是否存在此網(wǎng)站,沒有就創(chuàng)建相應(yīng)文件夾 fs.mkdir(dir,0755)。但更多的文件夾與文件是由scaffold.js完成的。scaffold里面?zhèn)€文件夾列表,用于讓程序從templates把相應(yīng)的文件夾拷貝到網(wǎng)站的路徑下,并建立505.html, 404.html, favicon.ico, routes.js等文件。其中最重頭的是routes,它是用來定義路由規(guī)則。

  1. //routes.js  
  2. //最重要的部分,根據(jù)它生成controller, action, model, views  
  3.    
  4. mass.define("routes",function(){  
  5.     return function(map){  
  6.         //方法路由  
  7.         //        map.get('/','site#index');  
  8.         //        map.get('/get_comments/:post_id','site#get_comments');  
  9.         //        map.post('/add_comment','site#add_comment');  
  10.         //        //資源路由  
  11.         //        map.resources('posts');  
  12.         //        map.resources('users');  
  13.         //        map.get('/view/:post_name','site#view_post');  
  14.         //        map.get('/rss','site#rss');  
  15.    
  16.         // map.resources('posts', {path: 'articles', as: 'stories'});  
  17.         //嵌套路由  
  18.         //        map.resources('posts', function (post) {  
  19.         //            post.resources('users');  
  20.         //        });  
  21.         //命名空間路由  
  22.         map.namespace("tests",function(tests){  
  23.             tests.resources('comments');  
  24.         })  
  25.     //        map.resources('users', {  
  26.     //            only: ['index', 'show']  
  27.     //        });  
  28.     //  
  29.     //        map.resources('users', {  
  30.     //            except: ['create', 'destroy']  
  31.     //        });  
  32.     //        map.resources('users', function (user) {  
  33.     //            user.get('avatar', 'users#avatar');  
  34.     //        });  
  35.     //        map.root("home#index")  
  36.     }  
  37. }); 

上面就是routes.js的所有內(nèi)容。允許建立五種路由:根路由,資源路由,方法路由(get,delete,put,post),命名空間路由,嵌套路由。其實(shí)它們統(tǒng)統(tǒng)都會歸化為資源路由,每個(gè)URL都對應(yīng)一個(gè)控制器與其下的action。它會調(diào)用router.js,讓里面的Router實(shí)例mapper調(diào)用router.js里面的內(nèi)容,然后返回mapper。

  1. //scaffold.js  
  2.         var routes_url = mass.adjustPath('config/routes.js'),  
  3.         action_url = "app/controllers/",  
  4.         view_url = "app/views/",  
  5.         mapper = new Router  
  6.    
  7.         mass.require("routes("+routes_url+")",function(fn){//讀取routes.js配置文件  
  8.             fn(mapper)  
  9.         });  
  10.  //這里省掉,一會兒解說  
  11.    
  12.         return mapper; 

Router實(shí)例mapper在routes運(yùn)行完畢后,那么它的幾個(gè)屬性就會添加了N多成員與元素,我們再利用它來進(jìn)一步構(gòu)建我們的控制器,視圖與模型。

  1. //如 this.controllers = {};現(xiàn)在變?yōu)? 
  2. { comments:  
  3.    { actions: [ 'index', 'create', 'new', 'edit', 'destroy', 'update', 'show' ],  
  4.    
  5.      views: [ 'index', 'new', 'edit', 'show' ],  
  6.      namespace: 'tests' } }  
  7.    
  8. //   this.GET = [];現(xiàn)在變?yōu)? 
  9. [ { controller: 'comments',  
  10.     action: 'index',  
  11.     method: 'GET',  
  12.     namespace: '/tests/',  
  13.     url: '/tests/comments.:format?',  
  14.     helper: 'tests_comments',  
  15.     matcher: /^\/tests\/comments$/i },  
  16.   { controller: 'comments',  
  17.     action: 'new',  
  18.     method: 'GET',  
  19.     namespace: '/tests/',  
  20.     url: '/tests/comments/new.:format?',  
  21.     helper: 'new_tests_comments',  
  22.     matcher: /^\/tests\/comments\/new$/i },  
  23.   { controller: 'comments',  
  24.     action: 'edit',  
  25.     method: 'GET',  
  26.     namespace: '/tests/',  
  27.     url: '/tests/comments/:id/edit.:format?',  
  28.     helper: 'edit_tests_comment',  
  29.     matcher: /^\/tests\/comments\/\d+\/edit$/i },  
  30.   { controller: 'comments',  
  31.     action: 'show',  
  32.     method: 'GET',  
  33.     namespace: '/tests/',  
  34.     url: '/tests/comments/:id.:format?',  
  35.     helper: 'tests_comment',  
  36.     matcher: /^\/tests\/comments\/\d+$/i } ] 

mapper有四個(gè)數(shù)組屬性,GET,POST,DELETE,PUT,我稱之為匹配棧,這些數(shù)組的元素都是一個(gè)個(gè)對象,對象都有一個(gè)matcher的正則屬性,就是用來匹配請求過來的URL的pathname屬性,當(dāng)然首先我們先取得其method,讓相應(yīng)的匹配棧去處理它。

現(xiàn)在手腳架scaffold.js還很簡鄙,以后它會結(jié)合熱部署功能,當(dāng)用戶修改routes.js或其他配置文件時(shí),它將會自動生成更多的視圖與控制器等等。

然后我們就啟動服務(wù)器了,由于req是EventEmitter的實(shí)例,因此我們可以隨意在上面綁定自定義事件,這里有兩個(gè)事件next_intercepter與err500。err500就不用說了,next_intercepter是用來啟動攔截器群集。這里我們只需要啟動***個(gè)。它在回調(diào)中會自動啟動下一個(gè)。這些攔截器是由intercepters.js 統(tǒng)一加載的。

  1. //intercepters.js  
  2. mass.intercepter = function(fn){//攔截器的外殼  
  3.     return function(req, res, err){  
  4.         if(err ){  
  5.             req.emit("next_intercepter", req, res, err);  
  6.         }else if(fn(req,res) === true){  
  7.             req.emit("next_intercepter", req, res)  
  8.         }  
  9.     }  
  10. }  
  11. var deps = ["mime","postData","query","methodOverride","json","favicon","matcher","handle404"];//"more",  
  12. mass.define("intercepters", deps.map(function(str){  
  13.     return "intercepters/"+str  
  14. }).join(","), function(){  
  15.     console.log("取得一系列欄截器");  
  16.     return [].slice.call(arguments,0)  
  17. }); 

每個(gè)攔截器都會對原始數(shù)據(jù)進(jìn)行處理,并決定是繼續(xù)啟用下一個(gè)攔截器。比如mime攔截器:

  1. mass.define("intercepters/mime",function(){  
  2.     console.log("本模塊用于取得MIME,并作為request.mime而存在");  
  3.     return mass.intercepter(function(req, res){  
  4.         console.log("進(jìn)入MIME回調(diào)");  
  5.         var str = req.headers['content-type'] || '';  
  6.         req.mime = str.split(';')[0];  
  7.         return true;  
  8.     })  
  9. }) 

#p#

postData攔截器

  1. mass.define("intercepters/postData","querystring",function(qs){  
  2.     console.log("本模塊用于取得POST請求過來的數(shù)據(jù),并作為request.body而存在");  
  3.     return mass.intercepter(function(req,res){  
  4.         console.log("進(jìn)入postData回調(diào)");  
  5.         reqreq.body = req.body || {};  
  6.         if ( req._body ||  /GET|HEAD/.test(req.method) || 'application/x-www-form-urlencoded' !== req.mime ){  
  7.             return true;  
  8.         }  
  9.         var buf = '';  
  10.         req.setEncoding('utf8');  
  11.         function buildBuffer(chunk){  
  12.             buf += chunk  
  13.         }  
  14.         req.on('data', buildBuffer);  
  15.         req.once('end',function(){  
  16.             try {  
  17.                 if(buf != ""){  
  18.                     req.body = qs.parse(buf);  
  19.                     req._body = true;  
  20.                 }  
  21.                 req.emit("next_intercepter",req,res)  
  22.             } catch (err){  
  23.                 req.emit("next_intercepter",req,res,err)  
  24.             }finally{  
  25.                 req.removeListener("data",buildBuffer)  
  26.             }  
  27.         })  
  28.     });  
  29. }); 

query攔截器

  1. mass.define("intercepters/query","querystring,url",function(qs,URL){  
  2.     console.log("本模塊用于取得URL的參數(shù)并轉(zhuǎn)為一個(gè)對象,作為request.query而存在");  
  3.     return mass.intercepter(function(req, res){  
  4.         req.query = ~req.url.indexOf('?')  
  5.         ? qs.parse(URL.parse(req.url).query)  
  6.         : {};  
  7.         return true;  
  8.     })  
  9. }) 

methodOverride攔截器

  1. mass.define("intercepters/methodOverride",function(){  
  2.     console.log("本模塊用于校正method屬性");  
  3.     var methods = {  
  4.         "PUT":"PUT",  
  5.         "DELETE":"DELETE"  
  6.     },  
  7.     method = mass.configs.method || "_method";  
  8.     return mass.intercepter(function(req, res){  
  9.         reqreq.originalMethod = req.method;  
  10.         var defaultMethod = req.method === "HEAD" ? "GET" : req.method;  
  11.         var _method = req.body ? req.body[method] : req.headers['x-http-method-override']  
  12.         _method = (_method || "").toUpperCase();  
  13.         req.method = methods[_method] || defaultMethod;  
  14.         if(req.body){  
  15.             delete req.body[method];  
  16.         }  
  17.         return true;  
  18.     })  
  19. }) 

json攔截器

  1. mass.define("intercepters/json",function(){  
  2.     console.log("本模塊處理前端發(fā)過來的JSON數(shù)據(jù)");  
  3.     return mass.intercepter(function(req, res, err){  
  4.         reqreq.body = req.body || {};  
  5.         if (req._body  || 'GET' == req.method || !~req.mime.indexOf("json")){  
  6.             console.log("進(jìn)入json回調(diào)")  
  7.             return true;  
  8.         }else{  
  9.             var buf = '';  
  10.             req.setEncoding('utf8');  
  11.             function buildBuffer(chunk){  
  12.                 buf += chunk;  
  13.             }  
  14.             req.on('data', buildBuffer);  
  15.             req.once('end', function(){  
  16.                 try {  
  17.                     req.body = JSON.parse(buf);  
  18.                     req._body = true;  
  19.                     req.emit("next_intercepter",req,res);  
  20.                 } catch (err){  
  21.                     err.status = 400;  
  22.                     req.emit("next_intercepter",req,res,err);  
  23.                 }finally{  
  24.                     req.removeListener("data",buildBuffer);  
  25.                 }  
  26.             });  
  27.         }  
  28.     })  
  29. }) 

而在這么多攔截器中,最重要的是matcher攔截器,它進(jìn)入框架MVC系統(tǒng)的入口。把原始請求的pathname取出來,然后通過正則匹配它,只要一個(gè)符合就停下來,然后加載對應(yīng)的控制器文件,調(diào)用相應(yīng)的action處理請求!

  1. mass.define("intercepters/matcher","url",function(URL){  
  2.     console.log("用于匹配請求過來的回調(diào)")  
  3.     return mass.intercepter(function(req,res){  
  4.         console.log("進(jìn)入matcher回調(diào)");  
  5.         var pathname = URL.parse(req.url).pathname, is404 = true,method = req.method, arr = mapper[method];  
  6.         for(var i =0, obj; obj = arr[i++];){  
  7.             if(obj.matcher.test(pathname)){  
  8.                 is404 = false 
  9.                 var url = mass.adjustPath("app/controllers/",obj.namespace, obj.controller+"_controller.js")  
  10.                 mass.require(obj.controller+"_controller("+url +")",function(object){  
  11.                     object[obj.action](req,res);//進(jìn)入控制器的action!!!  
  12.                     console.log(obj.action)  
  13.                 },function(){  
  14.                     var err = new Error;  
  15.                     err.statusCode = 404 
  16.                     req.emit("next_intercepter",req,res,err);  
  17.                 })  
  18.                 break;  
  19.             }  
  20.         }  
  21.         if(is404){  
  22.             var err = new Error;  
  23.             err.statusCode = 404 
  24.             req.emit("next_intercepter",req,res,err);  
  25.         }  
  26.     })  
  27. }) 

***殿后的是handle404攔截器:

  1. mass.define("intercepters/handle404","fs,path",function(fs){  
  2.     console.log("本模塊用于處理404錯(cuò)誤");  
  3.     return function(req, res, err){  
  4.         console.log("進(jìn)入handle404回調(diào)");  
  5.         var accept = req.headers.accept || '';  
  6.         if (~accept.indexOf('html')) {  
  7.             res.writeHead(404, {  
  8.                 "Content-Type": "text/html"  
  9.             });  
  10.             var html = fs.readFileSync(mass.adjustPath("public/404.html"))  
  11.             res.write((html+"").replace("{{url}}",req.url));  
  12.             res.end();  
  13.         } else if (~accept.indexOf('json')) {//json  
  14.             var error = {  
  15.                 message: err.message,   
  16.                 stack: err.stack  
  17.             };  
  18.             for (var prop in err) error[prop] = err[prop];  
  19.             var json = JSON.stringify({  
  20.                 error: error  
  21.             });  
  22.             res.setHeader('Content-Type', 'application/json');  
  23.             res.end(json);  
  24.         // plain text  
  25.         } else {  
  26.             res.writeHead(res.statusCode, {  
  27.                 'Content-Type': 'text/plain'  
  28.             });  
  29.             res.end(err.stack);  
  30.         }  
  31.     }  
  32. }) 

再回過頭來看控制器部分,從模板中生成的controller非常簡單:

  1. mass.define("comments_controller",function(){  
  2.     return {  
  3.         "index":function(){},  
  4.         "create":function(){},  
  5.         "new":function(){},  
  6.         "edit":function(){},  
  7.         "destroy":function(){},  
  8.         "update":function(){},  
  9.         "show":function(){}  
  10.     }  
  11.  }); 

因此你需要動手改到其可用,如

  1. "show":function(req,res){  
  2.     
  3.     res.writeHead(200, {  
  4.         "Content-Type": "text/html"  
  5.     });  
  6.     var html = fs.readFileSync(mass.adjustPath("app/views/tests/show.html"))  
  7.     res.write(html);  
  8.     res.end();  
  9.                

以后會判定action的結(jié)果自動調(diào)用視圖。

當(dāng)然現(xiàn)在框架還很簡單,只用了半天時(shí)間而已。它必須支持ORM與靜態(tài)文件緩存才行。此外還有cookie,session等支持,這些做成一個(gè)攔截器就行了。

總結(jié)如下:

◆ 判定網(wǎng)站是否存在,沒有通過手腳架構(gòu)建一個(gè)

◆ 讀取routes等配置文件,生成MVC系統(tǒng)所需要的控制器,視圖與模型。

◆ 通過熱部署功能,監(jiān)視用戶對配置文件的修改,進(jìn)一步智能生成需要控制器,視圖與模型。

◆ 通過一系列攔截器處理請來,直到matcher攔截器里面進(jìn)入MVC系統(tǒng),這時(shí)通過模型操作數(shù)據(jù)庫,渲染頁面。攔截器群集的應(yīng)用大大提高應(yīng)用的伸縮性?,F(xiàn)在還沒有來得及得node.js的多線程,可能這里面能發(fā)掘出許多好東西呢。

原文:http://www.cnblogs.com/rubylouvre/archive/2011/12/13/2286280.html

【編輯推薦】

  1. 用Web socket和Node.js實(shí)現(xiàn)HTML 5畫布的實(shí)時(shí)繪圖
  2. 走近Node.js的異步代碼設(shè)計(jì)
  3. 使用Node.js開發(fā)多人玩的HTML 5游戲
  4. Node.js提速指南
  5. Node.js初體驗(yàn)
責(zé)任編輯:陳貽新 來源: 司徒正美的博客
相關(guān)推薦

2020-04-20 16:00:05

Node.js框架JavaScript

2020-05-29 15:33:28

Node.js框架JavaScript

2019-08-29 10:58:02

Web 開發(fā)框架

2020-12-28 19:13:11

Node.js后端框架

2024-03-15 09:26:59

2012-03-07 14:32:41

Node.js

2014-10-30 10:28:55

Node.js

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開發(fā)指南基礎(chǔ)介紹

2011-12-23 13:58:57

node.js

2020-07-15 08:06:04

Node.js框架開發(fā)

2022-10-18 18:43:40

Node.js低代碼

2021-01-11 09:00:00

開發(fā)Node.js后端

2022-07-14 08:16:24

Node.js后端自動化測試

2011-09-09 14:23:13

Node.js

2011-11-01 10:30:36

Node.js

2011-09-08 13:46:14

node.js

2011-09-02 14:47:48

Node

2017-06-28 08:31:11

Node.jsMVC微服務(wù)

2012-10-24 14:56:30

IBMdw
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號