2013年1月20日 星期日

ExpressJS三兩事

ExpressJS應該是學Node.js的開發者必碰的框架,一些基本的說明收錄如下:

專案之初

專案採用ExpressJS之框架建置,建置過程減列如下:

    # mkdir ~/project  # express ~/project/ProjectName  # cd ~/project/ProjectName  # npm install  

目錄結構

  • app.js : 程式進入點
  • views/ : 放置*.ejs檔案,為view module的程式碼位置,亦即與java中的jsp相同地位的程式
  • routes/ : 放置route相關處理的程式碼,預設ExpressJS將app.js中的routing處理都拉到routes/下面
  • public/ : 放置靜態資源的位置
  • node_modules : 透過npm install後,npm會將定義域package.json中的所需函式庫都下載安裝至此

Configure

Igongsha將view engine由預設jade修改為ejs,設定部分主要如下:

    var express = require('express')    , partials = require('express-partials')    ....;    var app = express();    // Initial the layout system in expressjs 3.x  app.use(partials());    app.configure(function(){    //Set listen port     app.set('port', process.env.PORT || 7800);    //Set views' folder    app.set('views', __dirname + '/views');    //Set view engine, we choide ejs here    app.set('view engine', 'ejs');    ...    //Set public folder    app.use(express.static(path.join(__dirname, 'public')));  });    //Set running mode  app.configure('development', function(){    app.use(express.errorHandler());  });    //Set routing (this use the routes middleware, that default use the index.js under $project/routes)  app.get('/', routes.index);  

Routing

Routing簡單的說就是URL存取位置,你可以直接在app.js中寫處理,也可以拉出到middleware中

Under app.js:

    //That can access using http://host:port/test  app.get('/test', function(req, res){    res.end('...');  })  

Or move to middleware:

    //app.js  app.get('/test', routes.test);    //routes/index.js  exports.test = function(req, res){    res.end('...');  }  

Routing Types

ExpressJS依據HTTP method wrapper routing成get, post, del, put, all,說明如下:

  • app.get: HTTP GET傳遞方式,此方式傳遞時,無法使用req.body取值,通常可以作為讀取資料之用
  • app.post: HTTP POST傳遞方式,可以使用req.body取出Form中參數的傳遞,通常可以作為新增資料之用
  • app.del: HTTP DELETE傳遞方式,通常可以作為刪除資料之用
  • app.put: HTTP PUT傳遞方式,通常可以作為更新資料之域
  • app.all: 接受所有HTTP協定,內部可用req.method判斷傳入的Method為何

Middleware

舉凡非view的,通常nodejs稱作middleware,而我習慣說是lib...,一個存放商業邏輯的地方...

  • lib/*.js : 存放moddleware或函式庫或工具的地方
  • routes/*.js : 存放app.js中抽出的routing處理的地方,也可以說是route的middleware
  • node_modules/* : 定義於package.json中的dependency,在npm install後都會被安裝於此

View

頁面程式的產生工廠,類似java中的jsp,可以透過scriptlet的語法'<%- ... %>', '<%= ... %>', '<% ... %>'來嵌入後台程式碼,其中差別說明如下: '<%- ... %>', 用來嵌入不被跳脫(tag的<或>會被轉譯)的程式碼 '<%= ... %>', 用來嵌入需要被跳脫的程式碼 * '<% ... %>', 用來放置運算 views/layout.ejs

    <h1>This is from view/layout.ejs</h1>    <%-body%>    <footer>    <p align="center" style="width:100%">&copy; MiCloud 2013</p>  </footer>  

sample.ejs

    <title><%=title%></title>  Hello <%=user%>  <ul>  <%  for(var i=0; i<10; i++) {  %>  <li>This is ... <%=i%></li>  <%  }  %>  </ul>  

URL Access

已上面app.get('/test', routes.test)為例,伺服器啟動後,就可以使用http://server_ip:port/test來存取routes.test裡面的運算,而參數的存取,可以透過下面幾種方式:

  • req.params.xxx或req.params[xxx]: 如果routing的定義中有使用到:xxx的路徑,例如app.get('/test/:xxx', routes.test)的話,那就可以透過req.params來取xxx的值
  • req.body.xxx: 如果有使用到form的post時候,可以透過req.body.xxx來存取form中id/name=xxx的欄位傳送過來的值
  • query parameters: 如果參數的傳遞是使用url query string來傳遞時候,則可以使用req.url取出url,並透過url.parse()解析url之後,再取出該參數,範例如下:
    var url_parts = url.parse(req.url, true);  var query = url_parts.query;  console.log(query.xx);  

Static Pages

Express中的靜態資源位置,是在一開始的app.configure()中設定的,通常是寫這樣:

      app.use(express.static(path.join(__dirname, 'public')));  

因此,專案Code Gen後的預設目錄一般為public目錄,這些目錄下的檔案會忠實的呈現在routing上,例如$project/public/test.html檔案,會呈現在url:http://server_ip:port/test.html上,而其他靜態資源(image, video, music...)均可以透過這樣的規則放置與存取。