当前位置: 首页 > 工具软件 > rest-hapi > 使用案例 >

第8章-使用Express.js和Hapi构建Node.js-REST-API服务-8.4.重构:使用Hapi搭建REST API服务器

司徒耀
2023-12-01

Hapi是一个企业级的框架。他比Express.js复杂,功能更加丰富,更适合大团队开发使用。由Walmart Labs的Eran Hammer维护。

Hapi是一个框架,他的日志功能十分强大。
安装好Hapi后

一、创建程序入口文件hapi-app.js

//1.引入依赖模块

var hapi = require('hapi'),
  mongoskin = require('mongoskin'),

//2.创建一个Hapi服务器对象

server = hapi.createServer('localhost', 3000)

//3.连接数据库

var db = mongoskin.db('mongodb://@localhost:27017/test', {safe:true})
var id = mongoskin.helper.toObjectID

//4.定义方法,接收数据库名参数,然后异步加载数据库。接收的参数是URL,返回值是数据库集合

var loadCollection = function(name, callback) {
  callback(db.collection(name))
}

//5.这里和Express.js差异最大。
//我们需要把路径、回调函数等信息作为属性传入,而且在回调中第二个参数是reply而不是Express.js中的res(或response)
//server.route()函数接收一个数组做参数,每条路由是数组的一个元素
//这里第一条路由给主页使用(“/”)

server.route([
  {
    method: 'GET',
    path: '/',
    handler: function(req, reply) {
      reply('Select a collection, e.g., /collections/messages')
    }
  },

//6.用来响应GET /collection/:collectionName请求,其中主要的处理逻辑是在回调函数中调用loadCollection方法。
//这个方法用来查询相关的对象(find({})),然后输出排序并消减条目(最后10条)之后的结果:

    {
    method: 'GET',
    path: '/collections/{collectionName}',
    handler: function(req, reply) {
      loadCollection(req.params.collectionName, function(collection) {
        collection.find({}, {limit: 10, sort: [['_id', -1]]}).toArray(function(e, results){
          if (e) return reply(e)
          reply(results)
        })
      })
    }
  },

//7.用来创建一个新对象(POST /collections/collectionName),使用loadCollection方法,然后调用insert方法,并把请求数据(req.paylod)传入

    {
    method: 'POST',
    path: '/collections/{collectionName}',
    handler: function(req, reply) {
      loadCollection(req.params.collectionName, function(collection) {
        collection.insert(req.payload, {}, function(e, results){
          if (e) return reply(e)
          reply(results)
        })
      })
    }
  },

//注:URL中的每个参数都需要放在{}之中,同Express.js中使用的:name形式有所区别。因为”:”本身是一个合法的RUL字符,所以如果把他用作变量界定符的话,那么就没办法在URL中正常使用他了。
//8.通过对象ID获取单条记录

(/collection/collectionName/id)
    {
    method: 'GET',
    path: '/collections/{collectionName}/{id}',
    handler: function(req, reply) {
      loadCollection(req.params.collectionName, function(collection) {
        collection.findOne({_id: id(req.params.id)}, function(e, result){
          if (e) return reply(e)
          reply(result)
        })
      })
    }
  },

//9.更新记录,根据URL中的collectionName参数,调用loadCollection方法,来获取相应的数据库集合

    {
    method: 'PUT',
    path: '/collections/{collectionName}/{id}',
    handler: function(req, reply) {
      loadCollection(req.params.collectionName, function(collection) {
        collection.update({_id: id(req.params.id)},
          {$set: req.payload},
          {safe: true, multi: false}, function(e, result){
          if (e) return reply(e)
          reply((result === 1) ? {msg:'success'} : {msg:'error'})
        })
      })
    }
  },

//10.删除记录,先通过URL中的参数(collectionName)获取到响应的元素集合,然后通过ID删除这些元素,并返回结果(成功或者失败)

    {
    method: 'DELETE',
    path: '/collections/{collectionName}/{id}',
    handler: function(req, reply) {
      loadCollection(req.params.collectionName, function(collection) {
        collection.remove({_id: id(req.params.id)}, function(e, result){
           if (e) return reply(e)
           reply((result === 1) ? {msg:'success'} : {msg:'error'})
         })
      })
    }
  }
])

//11.控制日志的配置

var options = {
  subscribers: {
    'console': ['ops', 'request', 'log', 'error']
  }
};
server.pack.require('good', options, function (err) {
  if (!err) {
      // 插件加载成功
  }
});

//12.启动服务

server.start()

二、Hapi相对于Express.js的不同之处

1.使用数组定义路由规则
2.使用method、path、handler等属性定义路由对象
3.使用loadCollection方法替代中间件
4.在URL中使用{name}格式替换:name格式

 类似资料: