基于Start快速构建一个Web应用

Start 是一个 BaaS 产品的雏形,它提供了基本的服务器端 RESTful 风格的 API (包括 HTTP APISocket API) 、基于 MongoDB 的数据库存储和实时推送功能。基于 Start ,你可以快速构建一个 Web 应用,你需要做的工作只是完成Web应用的前端开发和数据库(表)的设置。

Start 使用以下技术和库进行开发:

  • Node.js
  • Express
  • Mongoose
  • AngularJS
  • Bootstrap 3
  • Socket.io

创建数据库

首先,你需要创建一个数据库,用于为你的应用提供数据存储服务。点击 New DB 按钮,在数据库创建页面,输入数据库名称,然后点击 Create DB 按钮,数据库即创建完成。

数据库创建完成后,会跳转到 DB List 页面,点击 DB 后面的文件图标,即可查看该 DB 的 APP ID,此 ID 用于配置 Web 应用的数据库。

创建数据表

在 DB List 页面,点击某一个 DB 名称,即跳转到该 DB 的配置页面。

一个新的数据库创建完成后,会默认生成三张表(Collection)用来表示用户信息、用户关注者和用户粉丝(系统自动生成的表以下划线开头),分别为:

  • _users
  • _followings
  • _followers

点击表名,即可查看该表中的数据,并进行增删改查操作。点击表名后面的文件图标,即可查看、修改表的结构,或者删除表。

在为你的应用设计好所需的数据表后,点击 New Schema 按钮,在数据表结构创建页面,输入表名 (Schema Name,请使用名词复数形式)和各个字段名称(Field)、类型(Type)、默认值(Default)及是否必须(Required)等值,然后点击 Create Schema 按钮,即可创建一个数据表。

开发Web应用

在完成前面两步数据库和数据表的设置后,只需要在你的 Web 应用中配置 APP ID,即可使用数据存储服务。后面只需要完成 Web 应用的前端开发即可。下面以使用 AngularJS 开发一个简易的类似 Weibo 的应用来描述如何配置数据库以及调用服务器端 API 。

配置数据库

使用 angular.ModuleConstant 方法,可以定义一个常量,在需要用到数据存储的地方,注入该常量即可。

1
2
angular.module('myApp.config', [])
.constant('APP_ID', 'wbsapp');

调用针对默认表的服务器端 API

如上文所述,在创建一个新的数据库后,系统会默认生成三张表,分别存储用户信息(_user)、用户关注者( _followings )和用户粉丝( _followers )。下面简单描述如何调用操作这三张表的 API 。

用户注册和用户登录(使用 _user 表)

首先,在 Service 中定义方法调用 RESTful API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
angular.module('myApp.services',  ['ngResource']).
factory('AppDataService', function($resource) {
var urlPrefix = 'http://localhost\\:3333/';
return $resource(urlPrefix + 'api/:path1/:path2/:path3', {}, {
register: {
method: 'POST',
params: {
path2: 'register'
}
},
login: {
method: 'POST',
params: {
path2: 'login'
}
}
}
})

然后,在 Controller 中调用 Service 层定义的方法,注册时调用 register 方法

1
2
3
AppDataService.register({path1: APP_ID}, registerModel, function (data) {
...
});

登录时调用 login 方法

1
2
3
AppDataService.login({path1: APP_ID}, loginModel, function (data) {
...
});

关注和取消关注,获取关注者和粉丝(使用 _followings 表和 _followers 表)

在 Service 中添加以下方法

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
29
30
follow: {
method: 'POST',
params: {
path1: '',
path2: 'follow'
}
},
cancelFollow: {
method: 'POST',
params: {
path1: '',
path2: 'cancelFollow'
}
},
getFollowers: {
method: 'GET',
params: {
path1: '',
path3: 'getFollowers'
},
isArray: true
},
getFollowings: {
method: 'GET',
params: {
path1: '',
path3: 'getFollowings'
},
isArray: true
}

关注某一用户时,调用 follow 方法

1
2
3
AppDataService.follow({path1: APP_ID}, followingMap, function (data) {
...
})

取消关注某一用户时,调用 cancelFollow 方法

1
2
3
4
AppDataService.cancelFollow({path1: APP_ID}, followingMap,
function (data) {
...
})

获取用户所有关注者时,调用 getFollowings 方法

1
2
3
4
AppDataService.getFollowings({path1: APP_ID, path2: username},              
function (followings) {
...
})

获取用户所有粉丝时,调用 getFollowers 方法

1
2
3
4
AppDataService.getFollowers({path1: APP_ID, path2: username},               
function (followers) {
...
})

以 HTTP 方式调用 API

前面对默认表进行操作的 API 是以 HTTP 方式进行的调用,下面再以微博的发布、获取来举例说明如何以 HTTP 方式调用 API 。

在 Service 中添加以下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create: {
method: 'POST',
params: {
path1: '',
path3: 'create'
}
},
list: {
method: 'GET',
params: {
path1: '',
path3: 'list'
},
isArray: true
}

当执行所有 新增 操作时,都可以调用 create 方法,然后传入不同数据表参数即可。发布微博显然属于新增操作,实现如下。

1
2
3
4
AppDataService.create({path1: APP_ID, path2: 'wbs'}, wbModel,
function (data) {
...
})

当执行所有 获取所有项 操作时,都可以调用 list 方法,同样只需要传入不同数据表参数即可。获取所有微博的实现如下。

1
2
3
4
AppDataService.list({path1: APP_ID, path2: 'wbs'}, 
function (wbs) {
...
})

如需要获取某一用户(author)发布的所有微博,可以添加 options 查询参数。

1
2
3
4
5
var options = {author: 'jason'};
AppDataService.list({path1: APP_ID, path2: 'wbs', options: options,
function (wbs) {
...
})

更多 API 的使用请参考 HTTP API 文档

以 Socket 方式调用 API

在使用 HTTP 方式调用 API 发布和获取微博的同时,可以使用 Socket 方式调用 API 进行实时通信,下面以微博好友间即时聊天为例来说明如何使用 Socket API 。

为使浏览器与服务器间建立连接,首先,需要在Web应用的主页面 index.html 引入 socket.io.js

1
<script src="http://localhost:3333/socket.io/socket.io.js"></script>

定义 Service,与服务器建立连接,并提供通信方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
factory('socket', function ($rootScope) {
var socket = io.connect('http://localhost:3333/');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
}

在 Controller 中注入 Socket 服务,即可与服务器实时通信

1
2
3
4
5
.controller('WbListCtrl', ['$scope', 'socket',
function ($scope, socket) {
...
}]
)

为使服务器能够区分建立的是与哪一个Web应用的连接,首先,应该在连接建立时,将应用的 APP_ID 发送给服务器

1
socket.emit('connect', {dbName: APP_ID});

当执行所有 新增 操作时,都可以发出(emit) create 事件,当想实时接收到其他用户新增的数据时,都应该监听(on) dataCreated 事件。显然,用户给好友发即时消息时,属于新增操作,实现如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
var reqData = {
dbName: APP_ID,
schemaName: 'msgs',
data: {
from: 'aa',
to: 'bb',
msg: 'hello'
}
}
socket.emit('create', reqData);
socket.on('dataCreated', function (resData) {
...
})

当执行所有 获取所有数据 操作时,都可以发出(emit) list 事件,并监听(on) dataListed 事件。用户获取所有通信内容的代码实现如下。

1
2
3
4
5
6
7
8
var reqData = {
dbName: APP_ID,
schemaName: 'msgs'
}
socket.emit('list', reqData);
socket.on('dataListed', function (resData) {
...
})

要获取特定两个好友(比如aa和bb)之间的通信内容,可以添加 options 查询参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var reqData = {
dbName: APP_ID,
schemaName: 'msgs',
options: {
$or: [
{
"from": "aa",
"to": "bb"
},
{
"from": "bb",
"to": "aa"
}
]
}
}
socket.emit('list', reqData);
socket.on('dataListed', function (resData) {
...
})

更多 API 的使用请参考 Socket API 文档

坚持原创技术分享,您的支持将鼓励我继续创作!