<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        使用Node.js實現RESTful API的示例

        來源:懂視網 責編:小采 時間:2020-11-27 22:33:36
        文檔

        使用Node.js實現RESTful API的示例

        使用Node.js實現RESTful API的示例:RESTful基礎概念 REST(Representational State Transfer)描述了一個架構樣式的網絡系統,它首次出現在 2000 年 Roy Fielding 的博士論文中。在REST服務中,應用程序狀態和功能可以分為各種資源。資源向客戶端公開,客戶端可以對資源進行增刪改操作。資源的
        推薦度:
        導讀使用Node.js實現RESTful API的示例:RESTful基礎概念 REST(Representational State Transfer)描述了一個架構樣式的網絡系統,它首次出現在 2000 年 Roy Fielding 的博士論文中。在REST服務中,應用程序狀態和功能可以分為各種資源。資源向客戶端公開,客戶端可以對資源進行增刪改操作。資源的

        RESTful基礎概念

        REST(Representational State Transfer)描述了一個架構樣式的網絡系統,它首次出現在 2000 年 Roy Fielding 的博士論文中。在REST服務中,應用程序狀態和功能可以分為各種資源。資源向客戶端公開,客戶端可以對資源進行增刪改操作。資源的例子有:應用程序對象、數據庫記錄、算法等等。

        REST通過抽象資源,提供了一個非常容易理解和使用的API,它使用 URI (Universal Resource Identifier) 唯一表示資源。REST接口使用標準的 HTTP 方法,比如 GET、PUT、POST 和 DELET在客戶端和服務器之間傳輸狀態。

        狹義的RESTful關注點在于資源,使用URL表示的資源及對資源的操作。Leonard Richardson 和 Sam Ruby 在他們的著作 RESTful Web Services 中引入了術語 REST-RPC 混合架構。REST-RPC 混合 Web 服務不使用信封包裝方法、參數和數據,而是直接通過 HTTP 傳輸數據,這與 REST 樣式的 Web 服務是類似的。但是它不使用標準的 HTTP 方法操作資源。

        和傳統的RPC、SOA相比,RESTful的更為簡單直接,且構建于標準的HTTP之上,使得它非常快速地流行起來。

        Node.js可以用很少代碼簡單地實現一個Web服務,并且它有一個非常活躍的社區,通過Node出色的包管理機制(NPM)可以非常容易獲得各種擴展支持。

        對簡單的應用場景Node.js實現REST是一個非常合適的選擇(有非常多的理由選擇這個或者那個技術棧,本文不會介入各種語言、架構的爭論,我們著眼點僅僅是簡單)。

        應用樣例場景

        下面,就用一個App游戲排行榜后臺服務來說明一下如何用Node.js快速地開發一個的RESTful服務。 

        當App游戲玩家過關時,會提交游戲過關時間(秒)數值到REST服務器上,服務器記錄并對過關記錄進行排序,用戶可以查看游戲TOP 10排行榜。 

        游戲應用提交的數據格式使用JSON表示,如下:

        {
        
         "id": "aaa",
        
         "score": 9.8,
        
         "token": "aaa-6F9619FF-8B86-D011-B42D-00C04FC964FF"
        
        };
        

        Id為用戶輸入的用戶名,token用于區別不同的用戶,避免id重名,score為過關所耗費的時間(秒)。

        可以使用curl作為客戶端測試RESTful服務。

        提交游戲記錄的命令如下:

        代碼如下:
        curl -d "{\"cmd\":1,\"record\":{\"id\":\"test11\",\"score\":29.8,\"token\":\"aaa\"}}" http://localhost:3000/leaderboards

        這個命令的語義不僅僅是狹義的REST增刪改,我們為它添加一個cmd命令,實際上通過POST一個JSON命令,把這個服務實現為REST-RPC。

        刪除游戲記錄的命令格式如下:

        curl -X DELETE http://localhost:3000/leaderboards/aaa

        或(使用REST-RPC語義)

        curl -d "{\"cmd\":2,\"record\":{\"id\":\"test11\"}}" http://localhost:3000/leaderboards

        查看TOP 10命令如下:

        curl http://localhost:3000/leaderboards

        標準REST定義中,POST和PUT有不同含義,GET可以區分單個資源或者資源列表。對這個應用我們做了簡化,ADD和UPDATE都統一使用POST,對單個資源和列表也不再區分,直接返回TOP 10數據。

        一些準備工作

        安裝Node.js

        本文使用的版本是v5.5.0。

        尋找一款方便的IDE

        本文作者使用Sublime敲打代碼,eclipse+nodeclipse生成框架代碼和調試。

        Node.js中基礎的HTTP服務器

        在Node中,實現一個HTTP服務器是很簡單的事情。在項目根目錄下創建一個叫app.js的文件,并寫入以下代碼:

        var http = require("http");
        
         
        
        http.createServer(function(request, response) {
        
         response.writeHead(200, {"Content-Type": "text/plain"});
        
         response.write("Hello World");
        
         response.end();
        
        }).listen(3000);
        
        

        用Node.js執行你的腳本:node server.js

         打開瀏覽器訪問http://localhost: 3000/,你就會看到一個寫著“Hello World”的網頁。

        即使完全不懂Node,也可以非常直觀的看到這里通過require引入了一個http模塊,然后使用createServer創建HTTP服務對象,當收到客戶端發出的HTTP請求后,將調用我們提供的函數,并在回調函數里寫入返回的頁面。

        接下來,我們將把這個簡單的應用擴展為一個RESTful服務。

         簡單直觀的RESTful服務

        現在需要超越“hello world”,我們將修改之前的http回調函數,根據請求類型返回不同的內容。

        代碼如下:

        var server = http.createServer(function(req, res) {
        
         var result;
        
         switch (req.method) {
        
         case 'POST':
        
         break;
        
         case 'GET':
        
         break;
        
         case 'DELETE':
        
         break;
        
         }
        
        });
        
        

        通過req.method,可以得到請求的類型。

        1. 增加和修改

        其中POST請求,是要求我們添加或更新記錄,請求的數據可以通過回調得到。

        代碼如下:

         var item = '';
        
         req.setEncoding('utf8');
        
         req.on('data', function(chunk) {
        
         item += chunk;
        
         });
        
         req.on('end', function() { 
        
         try {
        
         var command = JSON.parse(item);
        
         console.log(commandNaNd+ ';'+ command.record.id+ ':'+ command.record.score+ '('+ command.record.token+ ')');
        
         if (commandNaNd === CMD.UPDATE_SCORE){
        
         addRecord(command.record,result);
        
         }
        
         else if (commandNaNd === CMD.DEL_USE){
        
         db('leaderboards').remove({id:command.record.id});
        
         }
        
         res.end(JSON.stringify(result));
        
         }
        
         catch (err) {
        
         result.comment= 'Can\'t accept post, Error: '+ err.message;
        
         result.code= ErrCode.DataError;
        
         console.log(result.comment);
        
         res.end(JSON.stringify(result));
        
         }
        
         });
        
        

        當框架解析讀入數據時,會調用req.on('data', function(chunk)提供的回調函數,我們把請求的數據記錄在item中,一有數據,就調用item += chunk,直到數據讀入完成,框架調用req.on('end', function()回調,在回調函數中,使用JSON.parse把請求的JSON數據還原為Javascript對象,這是一個命令對象,通過commandNaNd可以區分是需要添加或刪除記錄。

        addRecord添加或更新記錄。

        代碼如下:

        function addRecord(record,result) {
        
         var dbRecord = db('leaderboards').find({ id: record.id });
        
         if (dbRecord){ 
        
         if (dbRecord.token !== record.token){
        
         result.code= ErrCode.DataError;
        
         result.comment= 'User exist';
        
         }
        
         else{
        
         db('leaderboards')
        
         .chain()
        
         .find({id:record.id})
        
         .assign({score:record.score})
        
         .value();
        
         result.comment= 'OK, New Score is '+ record.score;
        
         }
        
         }
        
         else{
        
         db('leaderboards').push(record);
        
         }
        
        }
        
        

        命令執行結束后,通過res.end(JSON.stringify(result))寫入返回數據。返回數據同樣是一個JSON字符串。

        在這個簡單的樣例中,使用了lowdb(https://github.com/typicode/lowdb#license?utm_source=ourjs.com)。

        LowDB 是一個基于Node的純Json文件數據庫,它無需服務器,可以同步或異步持久化到文件中,也可以單純作為內存數據庫,非常快速簡單。LowDB 提供Lo-Dash接口,可以使用類似.find({id:record.id})風格的方法進行查詢。通過chain(),可以把多個操作連接在一起,完成數據庫的查找更新操作。

        這個簡單的數據庫實現,如果游戲僅保存得分高的用戶記錄,實際上已經可以滿足我們的應用了。對更復雜的應用,Node也提供了各種數據庫連接模塊,比較常見的是mongodb或mysql。 

        2. 返回TOP 10

        通過查詢數據庫里的數據,首先使用.sortBy('score'),取前10個,返回到記錄集中,然后使用JSON.stringify轉為字符串,通過res返回。

        代碼如下:

         var records= [];
        
         var topTen = db('leaderboards')
        
         .chain()
        
         .sortBy('score')
        
         .take(10)
        
         .map(function(record) {
        
         records.push(record);
        
         })
        
         .value();
        
         res.end(JSON.stringify(records));
        
        

        3. 刪除記錄

        RESTful的刪除資源ID一般帶著URL里,類似“http://localhost:3000/leaderboards/aaa”,因此使用var path = parse(req.url).pathname解析出資源ID“aaa”。

        代碼如下:

         case 'DELETE':
        
         result= {code:ErrCode.OK,comment: 'OK'};
        
         try {
        
         var path = parse(req.url).pathname;
        
         var arrPath = path.split("/");
        
         var delObjID= arrPath[arrPath.length-1];
        
         
        
         db('leaderboards').remove({id:delObjID});
        
         res.end(JSON.stringify(result));
        
         break;
        
         }
        
        

        至此,我們實現了一個帶基本功能,可真正使用的RESTful服務。

        實際應用場合的REST服務可能會更復雜一些,一個應用或者會提供多個資源URL的服務;或者還同時提供了基本的WEB服務功能;或者REST請求帶有文件上傳等等。

        這樣,我們的簡單實現就不夠看了。

        Express框架

        Express 是一個基于 Node.js 平臺的 web 應用開發框架,它提供一系列強大的特性,幫助你創建各種 Web應用。

        可以使用eclipse+nodeclipse生成默認的express應用框架。一個express應用如下所示

        var express = require('express')
        
         , routes = require('./routes')
        
         , user = require('./routes/user')
        
         , http = require('http')
        
         , path = require('path');
        
         
        
        var app = express();
        
         
        
        // all environments
        
        app.set('port', process.env.PORT || 3000);
        
        app.set('views', __dirname + '/views');
        
        app.set('view engine', 'ejs');
        
        app.use(express.favicon());
        
        app.use(express.logger('dev'));
        
        app.use(express.bodyParser());
        
        app.use(express.methodOverride());
        
        app.use(app.router);
        
        app.use(express.static(path.join(__dirname, 'public')));
        
         
        
        // development only
        
        if ('development' == app.get('env')) {
        
         app.use(express.errorHandler());
        
        }
        
         
        
        app.get('/', routes.index);
        
        app.get('/users', user.list);
        
         
        
        http.createServer(app).listen(app.get('port'), function(){
        
         console.log('Express server listening on port ' + app.get('port'));
        
        });
        
        

        Express是一個Web服務器實現框架,雖然我們用不上頁面和頁面渲染,不過作為樣例,還是保留了缺省生成的頁面,并對其進行簡單解釋。

        在這個生成的框架代碼里,選擇view engine模板為ejs,這是一個類似JSP的HTML渲染模板引擎,app.get('/', routes.index)表示把HTTP的“/”請求路由給routes.index處理,routes.index對應于工程結構下的index.js文件處理,其內容如下:

        exports.index = function(req, res){
        
         res.render('index', { title: 'Express' });
        
        };
        

        這個函數調用了對應view目錄下的index.ejs模板,并把{ title: 'Express' }傳遞給ejs模板,在ejs模板中,可以使用<%= title %>得到傳入的json對象。 

        Express框架實現RESTful服務

        首先我們實現一個自己的服務類,在routes子目錄中,創建leaderboards.js文件,這個文件結構大致為定義REST對應的操作函數。 

        exports.fnList = function(req, res){
        
        }; 
        
        exports.fnGet = function(req, res){ 
        
        };
        
        exports.fnDelete = function(req, res){
        
        }; 
        
        exports.fnUpdate = function(req, res){
        
        };
        
        exports.fnAdd = function(req, res){ 
        
        };
        
        

        在app.js文件中,需要把HTTP請求路由給對應函數。

        var leaderboards = require('./routes/leaderboards');
        
        …
        
        app.get('/leaderboards', leaderboards.fnList);
        
        app.get('/leaderboards/:id', leaderboards.fnGet); 
        
        app.delete('/leaderboards/:id', leaderboards.fnDelete); 
        
        app.post('/leaderboards', leaderboards.fnAdd); 
        
        app.put('/leaderboards/:id', leaderboards.fnUpdate); 
        

        這樣就把標準Web服務請求路由到leaderboards處理。因為請求中帶有POST數據,可以使用

        var bodyParser = require('body-parser');
        
        // parse various different custom JSON types as JSON
        
        app.use(bodyParser.json({ limit: '1mb',type: 'application/*' }));
        

        把請求的JSON結構解析后添加到req.body中。Limit是為避免非法數據占用服務器資源,正常情況下,如果解析JSON數據,type應該定義為'application/*+json',在本應用里,為避免某些客戶端請求不指明類型,把所有輸入都解析為JSON數據了。

        'body-parser'是一個很有用的庫,可以解析各種類型的HTTP請求數據,包括處理文件上傳,詳細可以參見https://www.npmjs.com/package/body-parser。

         有了這個路由映射機制,我們不再需要考慮URL和數據的解析,僅僅指定路由,實現對應函數就可以了。

        exports.fnList = function(req, res){
        
         var result= {code:ErrCode.OK,comment: 'OK'};
        
         try {
        
         var records= [];
        
         var topTen = db('leaderboards')
        
         .chain()
        
         .sortBy('score')
        
         .take(10)
        
         .map(function(record) {
        
         records.push(record);
        
         })
        
         .value();
        
         res.end(JSON.stringify(records));
        
         }catch (err) {
        
         result.comment= 'Can\'t get leaderboards, Error: '+ err.message;
        
         result.code= ErrCode.DataError;
        
         console.log(result.comment);
        
         res.end(JSON.stringify(result));
        
         }
        
         return;
        
        }; 
        
        

         對類似http://localhost:3000/leaderboards/aaa的URL,express已經解析到req.param里了,可以通過req.param('id')得到。

        exports.fnDelete = function(req, res){
        
         var result= {code:ErrCode.OK,comment: 'OK'};
        
         try {
        
         var resID= req.param('id');
        
         db('leaderboards').remove(resID);
        
         res.end(JSON.stringify(result));
        
         
        
         console.log('delete record:'+ req.param('id'));
        
         }
        
         catch (err) {
        
         result.comment= 'Can\'t DELETE at '+ req.param('id')+ ', Error: '+ err.message;
        
         result.code= ErrCode.DelError;
        
         console.log(result.comment);
        
         res.end(JSON.stringify(result)); 
        
         }
        
        }; 
        
        

        使用了bodyParser.json()后,對POST請求中的JSON數據,已經解析好放到req.body里了,代碼中可以直接使用。

        function processCmd(req, res){
        
         var result= {code:ErrCode.OK,comment: 'OK'}; 
        
         try{
        
         var command = req.body;
        
         console.log(req.bodyNaNd+ ';'+ req.body.record.id+ ':'+ req.body.record.score+ '('+ req.body.record.token+ ')');
        
         if (commandNaNd === CMD.UPDATE_SCORE){
        
         addRecord(command.record,result);
        
         console.log('add record:'+ command.record.id);
        
         }
        
         else if (commandNaNd === CMD.DEL_USE){
        
         db('leaderboards').remove({id:command.record.id});
        
         console.log('delete record:'+ command.record.id);
        
         }
        
         res.end(JSON.stringify(result));
        
         }
        
         catch (err) {
        
         result.comment= 'Can\'t accept post, Error: '+ err.message;
        
         result.code= ErrCode.DataError;
        
         console.log(result.comment);
        
         res.end(JSON.stringify(result));
        
         }
        
         return;
        
        }
        
        exports.fnUpdate = function(req, res){
        
         processCmd(req,res);
        
        };
        
        exports.fnAdd = function(req, res){ 
        
         processCmd(req,res);
        
        };
        
        

        使用express的好處是有一些細節可以扔給框架處理,代碼結構上也更容易寫得清晰一些。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        使用Node.js實現RESTful API的示例

        使用Node.js實現RESTful API的示例:RESTful基礎概念 REST(Representational State Transfer)描述了一個架構樣式的網絡系統,它首次出現在 2000 年 Roy Fielding 的博士論文中。在REST服務中,應用程序狀態和功能可以分為各種資源。資源向客戶端公開,客戶端可以對資源進行增刪改操作。資源的
        推薦度:
        標簽: 實現 js 接口
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲综合色在线观看亚洲| 国产高清视频在线免费观看| 久久久久亚洲精品男人的天堂 | 91精品视频免费| 久久久亚洲欧洲日产国码二区 | 亚洲国产日韩综合久久精品| 蜜桃视频在线观看免费网址入口| 亚洲国产精品日韩在线观看| 久久不见久久见免费影院| 伊人久久亚洲综合影院首页| 妞干网在线免费视频| 久久亚洲色WWW成人欧美| 亚洲国产精品成人AV无码久久综合影院| 色天使色婷婷在线影院亚洲| 免费国产成人高清视频网站| 2022免费国产精品福利在线| 亚洲精品高清无码视频| 99精品一区二区免费视频| 亚洲国产成+人+综合| 日韩一区二区三区免费体验| jizz中国免费| 日木av无码专区亚洲av毛片| 久久久久国产精品免费免费搜索 | 亚洲日本一区二区三区在线| 99爱免费观看视频在线| 亚洲xxxx视频| 亚洲午夜久久久久妓女影院| 91九色老熟女免费资源站 | 午夜在线免费视频| 亚洲AV综合色区无码一区爱AV| 1000部禁片黄的免费看| 亚洲国产AV一区二区三区四区 | 精品亚洲视频在线观看 | 亚洲国产成人手机在线电影bd| 国产精品四虎在线观看免费| 国产在线精品一区免费香蕉| 亚洲国产精品午夜电影| 国产精品亚洲高清一区二区 | 在线看无码的免费网站| 激情无码亚洲一区二区三区| 亚洲国产AV无码专区亚洲AV|