Node.js学习:使用Loopback3.0构建应用程序(一)

一、安装

安装LoopBack工具来创建和开发LoopBack 3.0应用程序。

安装Node.js

node下载地址

安装loopback工具

虽然你可以自己从头开始编写一个LoopBack应用程序,但是安装一个LoopBack CLI工具能够使它更容易入门。它将构建应用程序的基本结构,然后您可以根据需要进行自定义。

LoopBack提供了两个工具的选项:LoopBack CLIIBM API Connect开发工具包,这里可以选择LoopBack CLI来进行应用程序的构建。

安装Loopback CLI工具

npm install -g loopback-cli

这一步将安装 lb 命令行工具,用于构建和修改LoopBack应用程序。

安装更新

如果之前安装过strongloop,需要进行一次版本的更新:

npm install -g strongloop

如果遇到任何问题,可以尝试卸载重装:

npm uninstall -g strongloop
npm cache clear
npm install -g strongloop

二、使用Loopback创建一个应用

创建一个简单的API

首先使用loopback-cli创建一个新的应用:

lb

LoopBack应用生成器将提示您输入应用程序的名称。

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |  Let's create a LoopBack |
   `---------´   |       application!       |
    ( _´U`_ )    '--------------------------'
    /___A___\
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `
[?] What's the name of your application? loopback-getting-started
[?] Enter name of the directory to contain the project: loopback-getting-started

这里可以替换成任何你喜欢的名字,本教程使用了官方文档中的名称:loopback-getting-started。

接下来cli工具会询问要创建什么样的应用程序:可以选择 hello-world

? What kind of application do you have in mind? (Use arrow keys)
  api-server (A LoopBack API server with local User auth)
  empty-server (An empty LoopBack API, without any configured models or datasources)
❯ hello-world (A project containing a controller, including a single vanilla Message and
    a single remote method)
  notes (A project containing a basic working example, including a memory database)  

然后,生成器将在其构建应用程序时创建如下信息,包括:

  1. 初始化项目的文件夹结构。
  2. 创建默认的JSON文件。
  3. 创建默认的JavaScript文件。
  4. 下载并安装依赖节点模块(省去手动安装npm的一步)。

创建一个数据模型

完成了初始项目的构建,接下来我们将创建一个自动具有REST API接口的CoffeeShop模型。

进入应用程序目录,然后运行LoopBack模型生成器:

lb model

生成器将提示输入数据模型的名称,输入CoffeeShop:

[?] Enter the model name: CoffeeShop

它会询问您是否要将模型附加到已经一些已经定义的数据源。 此时,只有默认的内存数据源可用。按Enter键选择它:

...
[?] Select the data-source to attach CoffeeShop to: (Use arrow keys)
❯ db (memory)

然后,生成器将提示您使用基类作为模型。由于您在最终会把该模型连接到数据库中的持久数据源,所以这里选择PersistedModel:

[?] Select model's base class: (Use arrow keys)
  Model
❯ PersistedModel
  ACL
  AccessToken
  Application
  Change
  Checkpoint

PersistedModel是连接到持久性数据源(如数据库)的所有模型的基础对象,也就是基类。

关于Loopback中的模型:

模型是LoopBack的核心,表示如数据库或其他后端服务(REST,SOAP等)等后端数据源。 LoopBack模型是具有Node和REST API的JavaScript对象。

LoopBack的一个关键功能是当您定义一个模型时,它将自动附带预定义的REST API,并具有完整的创建,读取,更新和删除操作。

Basic模型对象具有添加钩子和验证数据的方法。其他模型对象都“继承”它。模型具有继承层次结构,如下图所示:将模型附加到持久性数据源时,它将成为具有创建,检索,更新和删除操作的连接模型。 LoopBack的内置模型继承自它。

model的继承关系

LoopBack的强大优点之一是它自动为您的模型生成REST API。生成器将询问您是否要公开此REST API。

再次输入Enter接受默认值,并通过REST暴露CoffeeShop模型:

[?] Expose CoffeeShop via the REST API? (Y/n) Y

LoopBack使用模型名称的复数自动创建与模型关联的REST路由。默认情况下,它将您的名称复数(通过添加“s”),但是如果需要,您可以指定自定义复数形式。

按Enter接受默认复数形式(CoffeeShops):

[?] Custom plural form (used to build REST URL):

接下来,系统会询问您是要仅在服务器上创建模型,还是在/common目录中创建模型,这些模型可能由服务器端口和客户端LoopBack API使用。选择common,即使在这个应用程序中,你只使用服务器端模型:

? Common model or server only?
❯ common
  server

每个模型都有属性。现在,您将为CoffeeShop模型定义一个属性“name”。

选择字符串作为属性类型:

Let's add some CoffeeShop properties now.
Enter an empty property name when done.
[?] Property name: name
   invoke   loopback:property
[?] Property type: (Use arrow keys)
❯ string
  number
  boolean
  object
  array
  date
  buffer
  geopoint
  (other)

每个属性可以是可选的或必需的。输入 y 以将 name 设为必需:

[?] Required? (y/N)

然后系统会提示您输入属性的默认值;按Enter键不设默认值:

? Default value[leave blank for none]:

然后,系统会提示您添加其他属性。按照提示添加名为“city”的必需属性。

Let's add another CoffeeShop property.
? Property name: city
? Property type: string
? Required? Yes
? Default value[leave blank for none]:

当提示输入下一个属性的名称时,按Enter键结束模型创建过程。

模型生成器将在应用程序的 common / models 目录中创建两个定义模型的文件: coffee-shop.jsoncoffee-shop.js

LoopBack模型生成器自动将驼峰式的模型名称(例如MyModel)转换为小写字母名称(my-model)。例如,如果您使用模型生成器创建一个名为“FooBar”的模型,它将在 common/models 中创建foo-bar.jsonfoo-bar.js文件。但是,模型名称(“FooBar”)将通过模型的名称属性进行保留。

运行应用程序

$ node .
...
Browse your REST API at http://0.0.0.0:3000/explorer
Web server listening at: http://0.0.0.0:3000/

现在打开你的浏览器到http://0.0.0.0:3000/explorerhttp://localhost:3000/explorer 。您将看到StrongLoop API资源管理器:

通过使用LoopBack的一系列简单的步骤,您创建了一个CoffeeShop模型并为它设置了一些属性,然后通过REST进行公开。

三、使用API​​资源管理器

运行API​​资源管理器

运行应用: node .

转到 http://localhost:3000/explorer。您将看到StrongLoop API资源管理器中显示了该应用程序的两个模型:User和CoffeeShop:

探索CoffeeShop模型

除了CoffeeShop模型之外,Loopback还会为每个应用程序生成默认的用户模型及其接口。

展开CoffeeShops之后,可以看到它所有的API接口。

大致浏览这些API接口:您可以看到它们涵盖了所有的创建,读取,更新和删除(CRUD)等操作。你可以去post一条数据来试试看。

四、将API连接到数据源

添加一个数据源

现在,您将使用数据源生成器定义数据源:

$ lb datasource

生成器将提示您命名数据源:

[?] Enter the data-source name:

接下来,生成器将提示您输入数据源的类型,这里以mySql为例:

? Select the connector for mysqlDs: (Use arrow keys)
❯ In-memory db (supported by StrongLoop)
  IBM DB2 (supported by StrongLoop)
  IBM DashDB (supported by StrongLoop)
  IBM MQ Light (supported by StrongLoop)
  IBM Cloudant DB (supported by StrongLoop)
  IBM DB2 for z/OS (supported by StrongLoop)
  MongoDB (supported by StrongLoop)
(Move up and down to reveal more choices)

然后该工具将提示您输入数据源配置,对于MySQL,您可以以URL格式或单独输入所有设置。

Connector-specific configuration:
? Connection String url to override other settings (eg: mysql://user:pass@host/db):

按回车键跳过。

提示:尽量使用自己的MySQL数据库服务器,并创建一个名为“getting_started”的新数据库,数据库名称可以自己定义,但是请确保datasources.json中的mysqlDs.database属性与之匹配。

如果没有,您可以使用在demo.strongloop.com上运行的StrongLoop MySQL服务器。但它是一个共享资源,两个用户可能会同时运行创建样本数据的脚本,这可能会引发冲突。因此,我们建议您使用自己的MySQL服务器。

如果使用StrongLoop MySQL服务器,请输入如下所示的设置。如果使用您自己的MySQL服务器,请输入服务器的主机名,端口号和登录信息。

? host: demo.strongloop.com
? port: 3306
? user: demo
? password: L00pBack
? database: getting_started
? Install loopback-connector-mysql@^2.2 Yes

当工具提示您安装连接器时,运行npm install loopback-connector-mysql --save。该工具还将数据源定义添加到server/datasources.json文件中,如下所示。请注意刚刚添加的“mysqlDs”数据源,以及名为“db”的内存数据源,默认情况下是这样。

/server/datasources.json

{
  "db": {
    "name": "db",
    "connector": "memory"
  },
  "mysqlDs": {
      "host": "demo.strongloop.com",
      "port": 3306,
      "url": "",
      "database": "getting_started",
      "password": "L00pBack",
      "name": "mysqlDs",
      "user": "demo",
      "connector": "mysql"
    }
}

将CoffeeShop模型连接到MySQL

现在你创建了一个MySQL数据源,并且有一个CoffeeShop模型,接下来需要把它们联系起来。LoopBack应用程序使用model-config.json文件将模型链接到数据源。编辑/server/model-config.json并查找CoffeeShop条目:

/server/model-config.json

...
  "CoffeeShop": {
    "dataSource": "db",
    "public": true
  }
  ...

把dataSource属性从db更改为mysqlDs。使CoffeeShop模型附加到刚刚创建和配置的MySQL数据源:

/server/model-config.json

...
  "CoffeeShop": {
    "dataSource": "mysqlDs",
    "public": true
  }
  ...

添加一些测试数据

现在LoopBack中已经有了一个CoffeeShop模型,如何在MySQL数据库中创建相应的表?

您可以直接尝试执行一些SQL语句,不过LoopBack提供了一个Node API,可以自动执行一个称作auto-migration的程序。

loopback-getting-started模块包含用于演示自动迁移的create-sample-models.js脚本。

注意:以下自动迁移脚本是在应用程序初始启动时LoopBack执行的引导脚本的示例。使用引导脚本进行初始化,并执行应用程序启动时执行的任何其他逻辑。

/server/boot/create-sample-models.js

module.exports = function(app) {
  app.dataSources.mysqlDs.automigrate('CoffeeShop', function(err) {
    if (err) throw err;

    app.models.CoffeeShop.create([{
      name: 'Bel Cafe',
      city: 'Vancouver'
    }, {
      name: 'Three Bees Coffee House',
      city: 'San Mateo'
    }, {
      name: 'Caffe Artigiano',
      city: 'Vancouver'
    }, ], function(err, coffeeShops) {
      if (err) throw err;

      console.log('Models created: \n', coffeeShops);
    });
  });
};

这将保存一些测试数据到数据源。

五、扩展API

添加远程方法

按着如下步骤:

  1. 查看您的应用程序的/common/models目录。你会注意到文件夹里有coffee-shop.js和coffee-shop.json这两个文件。
  2. 在编辑器中打开coffee-shop.js,默认情况下,它包含一个空的函数:
module.exports = function(CoffeeShop) {};
  1. 将以下代码添加到此函数中:
module.exports = function(CoffeeShop) {
  CoffeeShop.status = function(cb) {
    var currentDate = new Date();
    var currentHour = currentDate.getHours();
    var OPEN_HOUR = 6;
    var CLOSE_HOUR = 20;
    console.log('Current hour is %d', currentHour);
    var response;
    if (currentHour > OPEN_HOUR && currentHour < CLOSE_HOUR) {
      response = 'We are open for business.';
    } else {
      response = 'Sorry, we are closed. Open daily from 6am to 8pm.';
    }
    cb(null, response);
  };
  CoffeeShop.remoteMethod(
    'status', {
      http: {
        path: '/status',
        verb: 'get'
      },
      returns: {
        arg: 'status',
        type: 'string'
      }
    }
  );
};

这定义了一个称为“状态”的简单远程方法,它不需要任何参数,并且根据当前时间检查时间并返回一个表示“打开营业”或“对不起我们关闭”的JSON状态消息。

当然,在实践中,您可以使用远程方法来做更多有趣和复杂的事情,例如在将数据保留到数据库之前操纵输入数据。您还可以更改调用远程方法的路由,并定义复杂参数并返回值。

使用远程方法

  1. 回到应用程序根目录,运行应用程序:
$ node .
  1. 转到http:// localhost:3000 / explorer查看API资源管理器。然后点击CoffeeShops,你会看到有一个新的REST端点,GET / CoffeeShop / status调用远程方法。

点击try it out!您会看到调用远程方法的结果:

{
  "status": "Open for business."
}

通过LoopBack,很轻易地添加了一个远程方法。

在远程方法中执行创建,检索,更新和删除方法

状态远程方法是微不足道的,但远程方法还可以访问任何标准模型创建,检索,更新和删除方法来执行数据处理和验证。这是一个简单的例子(这不是在loopback-getting-started库中):

module.exports = function(CoffeeShop) {
...
  CoffeeShop.getName = function(shopId, cb) {
    CoffeeShop.findById( shopId, function (err, instance) {
        var response = "Name of coffee shop is " + instance.name;
        cb(null, response);
        console.log(response);
    });
  }
...
  CoffeeShop.remoteMethod (
        'getName',
        {
          http: {path: '/getname', verb: 'get'},
          accepts: {arg: 'id', type: 'number', http: { source: 'query' } },
          returns: {arg: 'name', type: 'string'}
        }
    );
}

然后如果您访问远程方法,例如:

http://0.0.0.0:3000/api/CoffeeShops/getname?id=1

将会得到响应:

{
  "name": "Name of coffee shop is Bel Cafe"
}

六、添加一个静态页面

中间件简介

在继续之前,您首先需要了解Express中间件的基础知识。中间件只是一个JavaScript函数,可以访问表示HTTP请求的请求对象(req),表示HTTP响应的响应对象(res),以及Express应用程序的请求 - 响应周期中,由一个名为next的变量表示的下一个中间件。

中间件可以做什么?

  • 执行任何代码。
  • 更改请求和响应对象。
  • 结束请求 - 响应周期。
  • 调用堆栈中的下一个中间件。

LoopBack中间件就像Express中间件,除了LoopBack添加了相位的概念,使您能够轻松设置调用中间件的顺序。这避免了Express的一个棘手问题:确保中间件在需要的时候能够执行。

当您使用应用程序生成器创建应用程序时,它将创建一个server/middleware.json文件,指定中间件在哪个阶段执行。注册新的中间件与编辑此JSON文件一样简单:

server/middleware.json

{
  "initial:before": {
    "loopback#favicon": {}
  },
  "initial": {
    "compression": {},
    "cors": {
      "params": {
        "origin": true,
        "credentials": true,
        "maxAge": 86400
      }
    },
    "helmet#xssFilter": {},
    "helmet#frameguard": {
      "params": [
        "deny"
      ]
    },
    "helmet#hsts": {
      "params": {
        "maxAge": 0,
        "includeSubdomains": true
      }
    },
    "helmet#hidePoweredBy": {},
    "helmet#ieNoOpen": {},
    "helmet#noSniff": {},
    "helmet#noCache": {
      "enabled": false
    }
  },
  "session": {},
  "auth": {},
  "parse": {},
  "routes": {
    "loopback#rest": {
      "paths": [
        "${restApiRoot}"
      ]
    }
  },
  "files": {},
  "final": {
    "loopback#urlNotFound": {}
  },
  "final:after": {
    "strong-error-handler": {}
  }
}

middleware.json中的每个顶层键都定义了一个中间件阶段:initialsessionauth等等,到final为止。在给定阶段之前和之后,还有修改器注册中间件。在给定阶段的前后也有注册中间件的修改器。

更换或修改默认的根路由处理程序

应用程序通常需要提供静态内容,如HTML和CSS文件,客户端JavaScript文件,图像等。
使用LoopBack应用程序默认的脚手架很容易做到。您将去配置应用程序去启动/client文件夹中的静态资源。

首先,您必须禁用根URL的默认路由处理程序。当你加载应用程序的根URL [http:// localhost:3000/](http:// localhost:3000/)时,你看到应用程序用一个简单的状态消息,如这个:

{"started":"2014-11-20T21:59:47.155Z","uptime":42.054}

这是因为默认情况下,脚手架应用程序具有一个名为root.js的启动脚本,该脚本为根路径(“/”)设置路由处理中间件:

server/boot/root.js

module.exports = function(server) { // Install a `/` route that returns server status
  var router = server.loopback.Router();
  router.get('/', server.loopback.status());
  server.use(router);
};

该代码说,对于根URI(“/”)的任何GET请求,应用程序将返回loopback.status()的结果。要加入您自己的静态页面,您需要禁用此脚本。要么删除它,要么将其重命名为没有.js结尾的东西(确保应用程序不会执行它)。

定义静态中间件

接下来,您需要定义静态中间件来为/ client目录中的文件提供服务。

server/middleware.json

...
"files": {},
...

添加以下内容:

server/middleware.json

...
"files": {
  "loopback#static": {
    "params": "$!../client" 
  }
},
...

添加一个HTML文件

这些行定义静态中间件,使应用程序将/ client目录中的文件作为静态内容。$!字符表示路径是相对于middleware.json文件的位置。

/client/index.html

<head><title>LoopBack</title></head>
<body>
    <h1>LoopBack Rocks!</h1>
    <p>Hello World... </p>
</body>

运行

现在再次运行应用程序:

node .

打开http://0.0.0.0:3000/

七、添加自定义的Express路由

引入引导脚本

当LoopBack应用程序启动(也称为引导(bootstraps))时,它将运行/server/boot目录中的脚本,称为引导脚本。默认情况下,LoopBack按字母顺序加载引导脚本。

应用程序生成器创建的标准LoopBack应用脚手架中包含执行基本初始化的以下标准引导脚本(在/ server / boot中):

  • authentication.js - 通过调用app.enableAuth()来启用应用程序的身份验证。
  • root.js - 使用loopback.status()中间件定义/返回服务器状态的根路由。

添加一个新的启动脚本

例如,在/server/boot目录中添加一个名为routes.js的新引导脚本,其代码如下:

/server/boot/routes.js

module.exports = function(app) {
  // Install a "/ping" route that returns "pong"
  app.get('/ping', function(req, res) {
    res.send('pong');
  });
}

除此之外,也可以使用Express路由器中间件,如下所示:

/server/boot/routes.js

module.exports = function(app) {
  var router = app.loopback.Router();
  router.get('/ping', function(req, res) {
    res.send('pongaroo');
  });
  app.use(router);
}

实际上,您也可以使用Express API在server.js中添加路由。例如,在调用app.start()之前将此调用添加到app.use():

server/server.js

...
app.use('/express-status', function(req, res, next) {
  res.json({ running: true });
});

// start the server if `$ node server.js`
if (require.main === module) {
  app.start();
}

LoopBack应用程序可以轻松地执行Express应用程序可以执行的所有操作。如果您熟悉Express,LoopBack将会更容易学习。

运行引导脚本

现在,再次运行应用程序:

加载http://0.0.0.0:3000/ping。您会得到一个'pong'的响应。

现在一个简单的loopback应用程序就已经搭建完成了。

八、下一步

接下来的教程将涵盖:

  • 在单个应用程序中使用多个数据源。
  • 模型之间的关系。
  • 远程钩子。
  • 使用权限控制来保护REST接口。
  • 用户注册和认证
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容