LoopBack3.0最佳实践(二)——快速构建

本文的内容为通过Loopback的脚手架工具快速构建一个hello world应用程序,并初步了解Model、数据源等核心概念。当然,快速上手LoopBack,官方的文档是最权威的最丰富的,英文基础好的朋友可以出门左转搭乘官方的公交车:

不想看英文的懒人朋友请留步,我们继续,本文的可读性更好,而且代码可以到Github下载。

1. 安装CLI

LoopBack的快速打开方式为安装命令行脚手架工具LoopBack CLI。在安装Node.js之后,有两种安装CLI的方法:

1
2
1. npm install -g loopback-cli (仅安装LoopBack CLI,交互命令为`lb`)
2. npm install -g apiconnect (安装API Connect开发套件,可以用`apic loopback`这个命令启动LoopBack CLI)

这两种方式安装的LoopBack CLI,具体的交互命令基本相同,会有一些微小的差别。本文仅以介绍LoopBack为目的,所以将采用loopback-cli作为示例。关于LoopBack和API Connect之间的关系可参见本系列的第一篇文章《初识LoopBack》

2. 创建hello world应用

仅需在命令行键入lb这个命令,就可以按照交互式的提示去创建一个LoopBack应用。我们用loopback-hello-world作为工程的名字:

1
2
3
4
5
$ lb
? What's the name of your application? loopback-hello-world
? Enter name of the directory to contain the project: loopback-hello-world

? Which version of LoopBack would you like to use? 3.x (current)

在选择工程类型的时候,有4种选项

1
2
3
4
5
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)
  • empty-server 只包含基本的LoopBack脚手架代码
  • api-server 在empty-server的基础上,增加了用户认证的一些配置
  • hello-world 在api-server基础上,增加了一个Message模型,用于演示Model的作用
  • notes 在api-server基础上,增加了一个Note模型,与hello-world的区别在于多了一些默认的REST API

这里我们选择hello-world,回车之后CLI会创建下面这些基本的文件,并且自动安装了所有package.json中的依赖包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.
├── client
│   └── README.md
├── node_modules
├── common
│   └── models
│   ├── message.js
│   └── message.json
├── package.json
└── server
├── boot
│   ├── authentication.js
│   └── root.js
├── component-config.json
├── config.json
├── datasources.json
├── middleware.development.json
├── middleware.json
├── model-config.json
└── server.js

然后启动应用程序

1
2
3
$ node .
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer

访问localhost:3000根路径,返回的是一行关于应用程序运行状态的信息,工程里并没有定义前端页面。

1
{"started":"2017-10-04T06:33:55.674Z","uptime":5.538}

访问localhost:3000/explorer则是一个Swagger页面,LoopBack称之为Explorer

直接在页面上操作,访问后端预定义好的REST API,给输入参数赋值后,点击try it out可返回结果

3. 解构hello world工程

首先来看一下loopback-hello-world的工程目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.
├── client --> 存放前端代码
│   └── README.md
├── node_modules
├── common --> 存放前端和后端共用的代码
│   └── models --> 存放Model配置文件和定义文件
│   ├── message.js --> 定义message这个Model暴露的Rest方法
│   └── message.json --> 定义message这个Model的相关属性
├── package.json --> 定义依赖库
└── server --> 存放后端代码
├── boot --> 存放引导脚本,当LoopBack应用程序启动时,会按字母顺序加载引导脚本
│   ├── authentication.js --> 控制是否启用应用程序的身份验证,默认为启用
│   └── root.js --> 配置应用程序的根路由,即访问'/'时返回的结果
├── component-config.json --> 定义应用程序需要的Loopback组件
├── config.json --> 定义应用程序的基本配置,如API前缀、占用端口等
├── datasources.json --> 定义数据源
├── middleware.json --> 定义默认使用的中间件
├── middleware.development.json --> 定义在development环境下使用的中间件。多个运行环境可以有不同的配置
├── model-config.json --> 定义应用程序中Model的加载路径,以及具体Model的数据源
└── server.js --> 应用程序启动脚本

工程里的代码和配置文件主要围绕着模型(Model)、数据源(Datasource)、中间件(Middleware)、组件(Component)这些概念来定义,我们来认识一下Looback的“四大金刚“:

  • Model
    在Loopback的世界里,一个Model不仅仅是Property的集合,还可以提供REST API Endpoint方法,并且集成ORM功能。开发者仅需要定义Property和配置参数,Loopback会自动集成API和数据持久化方法。一个Model由模型配置文件(xxx.json)和模型定义文件(xxx.js)组成。
  • Datasource
    Loopback里的Datasource,不仅仅可以是Mysql、Orcle等数据库,也可以是Web Service,还可以是MQ、RPC、Email等服务。Model和Datasource绑定,可以将数据持久化到任何地方。
  • Middleware
    由于Loopback基于Express完成http路由,其中间件的概念与Express Middleware的概念一致,是一个在Http请求的响应周期中执行的JavaScript函数,在API Endpoint方法之前或之后调用。类似于Java中的拦截器(interceptor)。
  • Component
    组件是Loopback提供的用于与第三方服务集成的插件机制,目前支持的组件有消息推送(Push notifications)、云存储(Storage component)、第三方认证(Third-party login)、Swagger等。这些插件都是独立的Nodejs Module,需要安装后才能被应用程序调用。

4. 添加Model

定义一个Model仅仅需要在命令行键入lb model,然后跟随其交互指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
? Enter the model name: 
(注:定义Model名称)

? Select the datasource to attach CoffeeShop to: (Use arrow keys)
❯ db (memory)
(no datasource)
(注:选择Model绑定的数据源。由于我们没有定义数据源,所以这里只能先选择内存)

? Select model's base class (Use arrow keys)
Model
❯ PersistedModel
ACL
AccessToken
Application
Change
Checkpoint
(注:选择父类。这里有7种Loopback内嵌Model,我们可以先选择最常用的PersistedModel)

? Expose CoffeeShop via the REST API? (Y/n)
(注:是否暴露REST API接口)

? Custom plural form (used to build REST URL): CoffeeShop
(注:自定义Model名称的复数形式。会用于定义API的URL。上一步选择Y时,会进入这一步,否则直接下一步)

? Common model or server only? (Use arrow keys)
❯ common
server
(注:Model是否需要被前后端共用。Loopback的工程是前后端一体的,选择common时,Model的相关代码会被放在一个Common的路径下,更容易被前端调用)

然后定义Model的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Enter an empty property name when done.
(注:下面的交互命令是个循环,直接回车可退出)

? Property name:
(注:属性名称)

? Property type: (Use arrow keys)
❯ string
number
boolean
object
array
date
buffer
(Move up and down to reveal more choices)
(注:选择属性类型)

? Required? (y/N)
(注:是否必需)

? Default value[leave blank for none]:
(注:默认值,可不设定)

我们在工程中添加一个新的Model,咖啡店 - CoffeeShop,包含name和city两个字段

定义完之后,我们可以看到代码有了如下的变化

  • 修改了server/model-config.json
    1
    2
    3
    4
      "CoffeeShop": {
    "dataSource": "db",
    "public": true
    }
  • 新增了common/models/coffee-shop.js和common/models/coffee-shop.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    {
    "name": "CoffeeShop",
    "plural": "CoffeeShop",
    "base": "PersistedModel",
    "idInjection": true,
    "options": {
    "validateUpsert": true
    },
    "properties": {
    "name": {
    "type": "string",
    "required": true
    },
    "city": {
    "type": "string",
    "required": true
    }
    },
    "validations": [],
    "relations": {},
    "acls": [],
    "methods": {}
    }
    后面我们会看到所有新建的Model一般都会有这两个文件,Model配置文件(xxx.json)中可以配置一个Model的基本属性,Model定义文件(xxx.js)中可以添加Model的自定义方法,该文件不是必需,即在没有自定义方法的情况下也可以不需要Model定义文件。所以如果想手动创建一个Model,可以直接创建Model定义文件Model配置文件,同时修改model-config.json即可。

好了,重启应用程序,我们可以看到Loopback自动为我们集成了各种增删改查的REST方法,目前数据只能持久化到内存。

5. 添加数据源

命令行键入lb datasource,跟随其交互命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
? Enter the datasource name:
(注:定义Datasource名称)

? Select the connector for mysql: (Use arrow keys)
❯ In-memory db (supported by StrongLoop)
In-memory key-value connector (supported by StrongLoop)
IBM Object Storage (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)
Cassandra (supported by StrongLoop)
Redis key-value connector (supported by StrongLoop)
MongoDB (supported by StrongLoop)
MySQL (supported by StrongLoop)
PostgreSQL (supported by StrongLoop)
Oracle (supported by StrongLoop)
Microsoft SQL (supported by StrongLoop)
(注:海量数据库任你选择)

? Connection String url to override other settings
(注:根据不同的数据库设置不同的连接参数)

这里我们可以用Loopback官方提供的demo数据库作为示例

1
2
3
4
5
6
7
8
9
? Enter the datasource name: mysql
? Select the connector for mysql: MySQL (supported by StrongLoop)
? Connection String url to override other settings (eg: mysql://user:pass@host/db):
? host: demo.strongloop.com
? port: 3306
? user: demo
? password: L00pBack
? database: getting_started
? Install loopback-connector-mysql@^2.2 Yes

定义完之后的代码变化:

  • 修改了package.json。添加对loopback-connector-mysql的依赖,并自动安装。
    1
    "loopback-connector-mysql": "^2.4.1",
  • 修改了server/datasources.json。添加了对mysql数据源的配置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    "mysql": {
    "host": "demo.strongloop.com",
    "port": 3306,
    "url": "",
    "database": "getting_started",
    "password": "L00pBack",
    "name": "mysql",
    "user": "demo",
    "connector": "mysql"
    }
    在model-config.js中,将我们的CoffeShop的数据源修改为新增的mysql
    1
    2
    3
    4
    "CoffeeShop": {
    "dataSource": "mysql",
    "public": true
    }
    然后即可重启应用程序。如果可以正常连接数据源,我们可以查询到数据库的CoffeeShop数据,其他的API大家可以自己去体验。

ok,到这里我们已经成功地构建了一个LoopBack的应用,区区几行代码,就让我们成功地实现了一个REST服务,从API到数据库一条龙。更多关于Model的玩法,欢迎访问本系列的下一篇文章《面向Model编程》