1. 工具(Tools)
- Postman
[圖片上傳失敗...(image-af870d-1608111192578)] - heidisql
[圖片上傳失敗...(image-d858e-1608111192578)]
2. 安裝
驗(yàn)證是否已安裝依賴項(xiàng)
python --version 應(yīng)該是2.7.x
node --version 應(yīng)該是v0.10.x或v0.12.x。
npm --version 應(yīng)該是1.x或2.x。
安裝LoopBack 4 CLI
npm i -g @loopback/cli
安裝StrongLoop
npm install -g strongloop
驗(yàn)證安裝
slc -v
3. 創(chuàng)建一個(gè)簡(jiǎn)單的API
3.1 . 建立新的應(yīng)用程式
如果使用的是IBM API Connect工具,則命令為:
$ apic loopback
如果使用StrongLoop工具:
cd loopback //進(jìn)入項(xiàng)目文件的存放目錄
$ slc loopback
//? 您的應(yīng)用程序的名稱是什么? loopback_test2
//? 輸入目錄名稱以包含項(xiàng)目: (loopback_test2) Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.
//? 輸入目錄名稱以包含項(xiàng)目: loopback_test2
// create loopback_test2/
// info 將工作目錄更改為 loopback_test2
//? 您想要使用哪個(gè)版本的 LoopBack? 2.x (長(zhǎng)期支持)
//? 您想要什么種類的應(yīng)用程序? api-server (A LoopBack API server with local User auth)
//正在生成 .yo-rc.json
//I'm all done. Running npm install for you to install the required dependencies. If this //fails, try running the command yourself.
// create .editorconfig
// create .eslintignore
// create .eslintrc
// create server\boot\root.js
// create server\middleware.development.json
// create server\middleware.json
// create server\server.js
// create README.md
// create server\boot\authentication.js
// create .gitignore
// create client\README.md
LoopBack生成器將以友好的ASCII藝術(shù)歡迎您,并提示您輸入應(yīng)用程序的名稱
cd loopback_test2
3.2. 建立模型Create models
現(xiàn)在,您已經(jīng)完成了初始項(xiàng)目的腳手架,接下來將創(chuàng)建一個(gè) Coffeeshop 模型,該模型將自動(dòng)具有REST API端點(diǎn)。
$ cd loopback_test2
然后,使用IBM API Connect開發(fā)人員工具箱:
$ apic create --type model
或者,使用StrongLoop工具:
$ slc loopback:model
//? 請(qǐng)輸入模型名稱: CoffeeShop
//? 選擇要向其附加 CoffeeShop 的數(shù)據(jù)源: db (memory)
//? 選擇模型的基類 PersistedModel
//? 通過 REST API 公開 CoffeeShop? Yes
//? 定制復(fù)數(shù)形式(用于構(gòu)建 REST URL): Y
//? 公共模型或僅服務(wù)器? 公共
//現(xiàn)在添加一些 CoffeeShop 屬性。
//在完成時(shí)輸入空的屬性名稱。
//? 屬性名稱: Run-async wrapped function (sync) returned a promise but async() callback must //be executed to resolve.
//? 屬性名稱: name
// invoke loopback:property
//? 屬性類型: string
//? 是否為必需? No
//? 缺省值[對(duì)于無,保留為空白]: Y
//下面添加另一個(gè) CoffeeShop2 屬性。
//Run-async async() called outside a valid run-async context, callback will be ignored.
//在完成時(shí)輸入空的屬性名稱。
//? 屬性名稱: city
// invoke loopback:property
//? 屬性類型: string
//? 是否為必需? No
//? 缺省值[對(duì)于無,保留為空白]:
//下面添加另一個(gè) CoffeeShop2 屬性。
//Run-async async() called outside a valid run-async context, callback will be ignored.
//在完成時(shí)輸入空的屬性名稱。
//? 屬性名稱:
//D:\loopback\loopback_test2>
3.3. 運(yùn)行
$ node .
...
Browse your REST API at http://0.0.0.0:3000/explorer
Web server listening at: http://0.0.0.0:3000/
4. 使用API資源管理器
https://loopback.io/doc/en/lb2/Use-API-Explorer.html
用get、post等方法操作數(shù)據(jù)
設(shè)置數(shù)據(jù)不可見
server/model-config.json
"public": true // true不公開fale公開
5. Data Source
將API連接到數(shù)據(jù)源
安裝MySQL連接器
現(xiàn)在添加loopback-connector-mysql模塊并安裝依賴項(xiàng):
$ npm install loopback-connector-mysql --save
添加數(shù)據(jù)源
npm i loopback-connector-mysql@^2.2
現(xiàn)在,您將使用數(shù)據(jù)源生成器來定義數(shù)據(jù)源 :
slc loopback:datasource
輸入 mysqlDs 并點(diǎn)擊 Enter。
? 請(qǐng)輸入數(shù)據(jù)源名稱: mariaD
? 為 mariaD 選擇連接器: MySQL (StrongLoop 支持)
特定于連接器的配置:
? Connection String url to override other settings (eg: mysql://user:pass@host/db):
? host: 127.0.0.1
? port: 3306
? user: root
? password: ****
? database: dason
? 安裝 loopback-connector-mysql@^2.2 (Y/n) Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.
? 安裝 loopback-connector-mysql@^2.2 Yes
+ loopback-connector-mysql@2.4.1
added 5 packages from 12 contributors in 6.643s
11 packages are looking for funding
run `npm fund` for details
D:\loopback\loopback_test2>
將CoffeeShop模型連接到MySQL
現(xiàn)在,您已經(jīng)創(chuàng)建了一個(gè)MySQL數(shù)據(jù)源,并且有一個(gè)CoffeeShop模型。您只需要連接它們。LoopBack應(yīng)用程序使用 model-config.json 文件將模型鏈接到數(shù)據(jù)源。編輯 /server/model-config.json 并查找CoffeeShop條目:
/server/model-config.json
...
"CoffeeShop": {
"dataSource": "db",
"public": true
}
...
將dataSource 屬性從 更改 db 為 mysqlDs。這會(huì)將CoffeeShop模型附加到您剛剛創(chuàng)建和配置的MySQL數(shù)據(jù)源:
/server/model-config.json
...
"CoffeeShop": {
"dataSource": "mysqlDs",
"public": true
}
...
添加一些測(cè)試數(shù)據(jù)并查看
server/boot/create-sample-models.js
module.exports = function(app) {
app.dataSources.mariaDs.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);
});
});
};
這會(huì)將一些測(cè)試數(shù)據(jù)保存到數(shù)據(jù)源。
注意: 但如果重新運(yùn)行,create-sample-models.js數(shù)據(jù)會(huì)重新覆蓋而重置數(shù)據(jù)
6. 擴(kuò)展您的API
coffee-shop.js 添加
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'
}
}
);
};
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: 'string', http: { source: 'query' } },
returns: {arg: 'name', type: 'string'}
}
);
}
添加遠(yuǎn)程方法
-
coffee-shop.js在您喜歡的編輯器中打開 。默認(rèn)情況下,它包含一個(gè)空函數(shù):module.exports = function(CoffeeShop) {}; -
向此函數(shù)添加以下代碼,以使用遠(yuǎn)程方法擴(kuò)展模型的行為,因此看起來如下所示:
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' } } ); }; 保存文件
嘗試遠(yuǎn)程方法
-
返回應(yīng)用程序的根目錄,運(yùn)行該應(yīng)用程序:
$ node . -
轉(zhuǎn)到
http:// localhost:3000 / explorer
查看API Explorer。然后單擊CoffeeShops,您將看到有一個(gè)新的REST端點(diǎn),
GET/CoffeeShop/status該端點(diǎn) 調(diào)用遠(yuǎn)程方法。
[圖片上傳失敗...(image-63046b-1608111192578)]</ figure>
-
單擊
嘗試!
您將看到調(diào)用遠(yuǎn)程方法的結(jié)果:
{ "status": "Open for business." }
這就是使用LoopBack添加遠(yuǎn)程方法非常容易!
有關(guān)更多信息,請(qǐng)參見 遠(yuǎn)程方法。
7. 添加靜態(tài)網(wǎng)頁
https://loopback.io/doc/en/lb2/Add-a-static-web-page.html
定義靜態(tài)中間件
接下來,您需要定義靜態(tài)中間件來提供目錄中的 /client 文件。 添加以下內(nèi)容:
server / middleware.json
...
"files": {
"loopback#static": {
"params": "$!../client"
}
},
...
這些行定義了 靜態(tài)中間件 ,該中間件使應(yīng)用程序?qū)⒛夸浿械?/client 文件作為靜態(tài)內(nèi)容提供。該 $! 字符表示該路徑是相對(duì)的位置 middleware.json。
添加一個(gè)HTML文件
現(xiàn)在,該應(yīng)用程序?qū)涯湃?code>/client 目錄中的任何文件 作為靜態(tài)(客戶端)內(nèi)容。因此,要查看實(shí)際效果,請(qǐng)向中添加一個(gè)HTML文件 /client。例如,添加一個(gè)index.html 具有以下內(nèi)容的文件 :
/client/index.html
<head><title>LoopBack</title></head>
<body>
<h1>LoopBack Rocks!</h1>
<p>Hello World... </p>
</body>
當(dāng)然,您可以添加任何喜歡的靜態(tài)HTML –這只是一個(gè)示例。
運(yùn)行…
現(xiàn)在再次運(yùn)行該應(yīng)用程序:
$ node .
立即加載 http://0.0.0.0:3000/ index而不是狀態(tài)JSON時(shí),您將看到以下內(nèi)容:
[圖片上傳失敗...(image-8f65b1-1608111192578)]</ figure>
8. 模型關(guān)系
? HasMany
? BelongsTo
? HasOne
? HasManyThrough
HasMany
建立在與其他模型「一對(duì)多」的連結(jié),此關(guān)係表示模型的每個(gè)實(shí)例都具有零個(gè)或多個(gè)對(duì)應(yīng)的模型實(shí)例。Ex. 每位會(huì)員可有多筆留言。
9. 創(chuàng)建新模型
該應(yīng)用程序具有三個(gè)模型:
- CoffeeShop(在LoopBack入門中定義 )
- 評(píng)論
- 審稿人
它們之間的關(guān)系如下:
- 一個(gè)CoffeeShop有很多評(píng)論
- 一個(gè)CoffeeShop有很多評(píng)論者
- 評(píng)論屬于CoffeeShop
- 評(píng)論屬于評(píng)論者
- 評(píng)論者有很多評(píng)論
定義審閱模型
輸入:
$ slc loopback:model
出現(xiàn)提示時(shí),輸入或選擇以下內(nèi)容:
? 請(qǐng)輸入模型名稱: Review
? 選擇要向其附加 Review 的數(shù)據(jù)源: mariaDs (mysql)
? 選擇模型的基類 PersistedModel
? 通過 REST API 公開 Review? Yes
? 定制復(fù)數(shù)形式(用于構(gòu)建 REST URL):
? 公共模型或僅服務(wù)器? 公共
現(xiàn)在添加一些 Review 屬性。
在完成時(shí)輸入空的屬性名稱。
? 屬性名稱: Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.
? 屬性名稱: date
invoke loopback:property
? 屬性類型: date
? 是否為必需? Yes
? 缺省值[對(duì)于無,保留為空白]:
//下面添加另一個(gè) Review 屬性。
//Run-async async() called outside a valid run-async //context, callback will be ignored.
在完成時(shí)輸入空的屬性名稱。
? 屬性名稱: rating
invoke loopback:property
? 屬性類型: number
? 是否為必需? No
? 缺省值[對(duì)于無,保留為空白]:
//下面添加另一個(gè) Review 屬性。
//Run-async async() called outside a valid run-async //context, callback will be ignored.
在完成時(shí)輸入空的屬性名稱。
? 屬性名稱: comments
invoke loopback:property
? 屬性類型: string
? 是否為必需? Yes
? 缺省值[對(duì)于無,保留為空白]:
下面添加另一個(gè) Review 屬性。
Run-async async() called outside a valid run-async context, callback will be ignored.
在完成時(shí)輸入空的屬性名稱。
? 屬性名稱:
D:\loopback\loopback_test1>
查看模型JSON文件
現(xiàn)在,看common/models/review.json
然后,按照提示添加這些屬性:
| Property name | Property type | Required? |
|---|---|---|
| date | date | y |
| rating | number | n |
| comments | string | y |
要退出模型生成器,請(qǐng)?jiān)谔崾据斎雽傩悦Q時(shí)按RETURN。
輸入:
slc loopback:model
出現(xiàn)提示時(shí),輸入或選擇以下內(nèi)容:
? 請(qǐng)輸入模型名稱: Reviewer
? 選擇要向其附加 Reviewer 的數(shù)據(jù)源: mariaDs (mysql)
? 選擇模型的基類 User
? 通過 REST API 公開 Reviewer? Yes
? 定制復(fù)數(shù)形式(用于構(gòu)建 REST URL):
? 公共模型或僅服務(wù)器? 公共
現(xiàn)在添加一些 Reviewer 屬性。
在完成時(shí)輸入空的屬性名稱。
? 屬性名稱: Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.
? 屬性名稱:無
安裝異步 async
npm install --save async
服務(wù)器/啟動(dòng)/創(chuàng)建樣本模型.js
var async = require('async');
module.exports = function(app) {
//data sources
var mariaDs = app.dataSources.mariaDs;
//var mysqlDs = app.dataSources.mysqlDs;
//create all models
async.parallel({
reviewers: async.apply(createReviewers),
coffeeShops: async.apply(createCoffeeShops),
}, function(err, results) {
if (err) throw err;
createReviews(results.reviewers, results.coffeeShops, function(err) {
console.log('> models created sucessfully');
});
});
//create reviewers
function createReviewers(cb) {
mariaDs.automigrate('Reviewer', function(err) {
if (err) return cb(err);
var Reviewer = app.models.Reviewer;
Reviewer.create([{
email: 'foo@bar.com',
password: 'foobar'
}, {
email: 'john@doe.com',
password: 'johndoe'
}, {
email: 'jane@doe.com',
password: 'janedoe'
}], cb);
});
}
//create coffee shops
function createCoffeeShops(cb) {
mariaDs.automigrate('CoffeeShop', function(err) {
if (err) return cb(err);
var CoffeeShop = app.models.CoffeeShop;
CoffeeShop.create([{
name: 'Bel Cafe',
city: 'Vancouver'
}, {
name: 'Three Bees Coffee House',
city: 'San Mateo'
}, {
name: 'Caffe Artigiano',
city: 'Vancouver'
}, ], cb);
});
}
//create reviews
function createReviews(reviewers, coffeeShops, cb) {
mariaDs.automigrate('Review', function(err) {
if (err) return cb(err);
var Review = app.models.Review;
var DAY_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
Review.create([{
date: Date.now() - (DAY_IN_MILLISECONDS * 4),
rating: 5,
comments: 'A very good coffee shop.',
publisherId: reviewers[0].id,
coffeeShopId: coffeeShops[0].id,
}, {
date: Date.now() - (DAY_IN_MILLISECONDS * 3),
rating: 5,
comments: 'Quite pleasant.',
publisherId: reviewers[1].id,
coffeeShopId: coffeeShops[0].id,
}, {
date: Date.now() - (DAY_IN_MILLISECONDS * 2),
rating: 4,
comments: 'It was ok.',
publisherId: reviewers[1].id,
coffeeShopId: coffeeShops[1].id,
}, {
date: Date.now() - (DAY_IN_MILLISECONDS),
rating: 4,
comments: 'I go here everyday.',
publisherId: reviewers[2].id,
coffeeShopId: coffeeShops[2].id,
}], cb);
});
}
};
10. 定義模型關(guān)系
引入模型關(guān)系
環(huán)回支持許多不同類型的模型關(guān)系,包括:屬于關(guān)聯(lián),的hasMany,HasManyThrough和HasAndBelongsToMany,等等。有關(guān)更多信息,請(qǐng)參見 創(chuàng)建模型關(guān)系。
在“ Coffee Shop評(píng)論”應(yīng)用程序中,模型之間的關(guān)系如下:
- 一個(gè)咖啡店有很多評(píng)論。
- 一個(gè)咖啡店有很多評(píng)論者。
- 評(píng)論屬于一家咖啡店。
- 評(píng)論屬于評(píng)論者。
- 評(píng)論者有很多評(píng)論。
定義關(guān)系
slc loopback:relation
選擇
? 選擇從中創(chuàng)建關(guān)系的模型: CoffeeShop
? 關(guān)系類型: has many
? 選擇與之創(chuàng)建關(guān)系的模型: Review
? 輸入關(guān)系的屬性名稱: reviews
? (可選)輸入定制外鍵:
? 需要直通模型? No
? 選擇從中創(chuàng)建關(guān)系的模型: Review
? 關(guān)系類型: belongs to
? 選擇與之創(chuàng)建關(guān)系的模型: CoffeeShop
? 輸入關(guān)系的屬性名稱: coffeeShop
? (可選)輸入定制外鍵:
? 選擇從中創(chuàng)建關(guān)系的模型: Review
? 關(guān)系類型: belongs to
? 選擇與之創(chuàng)建關(guān)系的模型: Reviewer
? 輸入關(guān)系的屬性名稱: reviewer
? (可選)輸入定制外鍵:
? 選擇從中創(chuàng)建關(guān)系的模型: Reviewer
? 關(guān)系類型: has many
? 選擇與之創(chuàng)建關(guān)系的模型: Review
? 輸入關(guān)系的屬性名稱: reviews
? (可選)輸入定制外鍵:
? 需要直通模型? No
? 選擇從中創(chuàng)建關(guān)系的模型: CoffeeShop
? 關(guān)系類型: has many
? 選擇與之創(chuàng)建關(guān)系的模型: Reviewer
? 輸入關(guān)系的屬性名稱: reviewers
? (可選)輸入定制外鍵:
? 需要直通模型? No
11. 定義訪問控制
$ slc loopback:acl
? 選擇要應(yīng)用 ACL 條目的模型: Review
? 選擇 ACL 作用域: 所有方法和屬性
? 選擇訪問類型: All (match all types)
? 選擇角色 All users
? 選擇要應(yīng)用的許可權(quán) Explicitly deny access
所有人都可以看,不可以改
? 選擇要應(yīng)用 ACL 條目的模型: Review
? 選擇 ACL 作用域: 所有方法和屬性
? 選擇訪問類型: All (match all types)
? 選擇角色 All users
? 選擇要應(yīng)用的許可權(quán) Explicitly grant access
授權(quán)的可以
? 選擇要應(yīng)用 ACL 條目的模型: Review
? 選擇 ACL 作用域: 單個(gè)方法
? 輸入方法名稱 create
? 選擇角色 Any authenticated user
? 選擇要應(yīng)用的許可權(quán) Explicitly grant access
物件所有者可修改
? 選擇要應(yīng)用 ACL 條目的模型: Review
? 選擇 ACL 作用域: 所有方法和屬性
? 選擇訪問類型: Write
? 選擇角色 The user owning the object
? 選擇要應(yīng)用的許可權(quán) Explicitly grant access