使用Node.js实现RESTful API的示例(2)

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()。

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里,类似“: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("https://www.jb51.net/"); 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('https://www.jb51.net/', 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('https://www.jb51.net/', 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对应的操作函数。 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyjyfw.html