当前位置:首页 >时尚 >移动后端服务BaaS现状 后端还要开发服务端

移动后端服务BaaS现状 后端还要开发服务端

2024-06-30 20:37:22 [百科] 来源:避面尹邢网

移动后端服务BaaS现状

作者:佚名 移动开发 开发一个具有网络功能的移动移动应用,除了要开发客户端,后端还要开发服务端,服务还需要服务器。现状为了简化移动应用的移动开发和部署,让开发者只专注于客户端的后端开发,而将后端服务整合成API提供给开发者调用,服务这就是现状BaaS(Backend as a Service)。

 

移动后端服务BaaS现状 后端还要开发服务端

目前,移动国外至少已经有二十多家企业进入了这个领域,后端其中,服务提供的现状后端服务比较全面的有StackMob、Parse、移动Kinvey。后端而国内,服务和国外的概念比较接近的有Bmob、AMTBaaS,还有我们的Xone

移动后端服务BaaS现状 后端还要开发服务端

StackMob

StackMob算是最早进入该领域的,成立于2010年1月,去年5月份的时候,那时该团队还只有6个人,就获得了750万美元的投资。目前该团队有24个人,每月访问量已经超过300万,使用其服务的应用已经达到120万。支持的SDK已经涵盖了iOS、Android、JavaScript、 Ruby,还有Custom Code。其中,Custom Code是用于服务端开发的,可以用Java和Scala语言进行开发。通过Custom Code,开发者就可以在服务端处理一些无法在客户端处理的逻辑。StackMob提供的功能服务也挺全面的,大的方面,数据存储、推送服务、地理位置服务、社交等,再细入到支持角色管理、ACL、复杂和多层的数据模型、多种查询条件等等。

移动后端服务BaaS现状 后端还要开发服务端

而那么多SDK中,我只看了Android的。其SDK也挺简单易用的,应用程序自身的数据模型只要继承StackMobModel即可,而用户类则继承StackMobUser,然后可以直接定义自己的属性。另外,它也支持嵌套的数据模型,最多支持3层嵌套。比如下面的代码:

  1. public class Task extends StackMobModel {  
  2.                                                                    
  3.     private String name; 
  4.     private Date dueDate; 
  5.     private int priority; 
  6.     private boolean done; 
  7.     private Task prerequisite; 
  8.                                                         
  9.     public Task(String name, Date dueDate) {  
  10.         super(Task.class); 
  11.         this.name = name; 
  12.         this.dueDate = dueDate; 
  13.         this.priority = 0; 
  14.         this.done = false; 
  15.     } 
  16.                                        
  17.     public void setPrerequisite(Task prereq) {  
  18.         this.prerequisite = prereq; 
  19.     } 
  20.                                    
  21. public class TaskList extends StackMobModel {  
  22.                                
  23.     private String name; 
  24.     private List<Task> tasks; 
  25.     private Task topTask; 
  26.     private TaskList parentList; 
  27.                                                                                                                                       
  28.     public TaskList(String name) {  
  29.         super(TaskList.class); 
  30.         tasks = new ArrayList<Task>(); 
  31.         this.name = name; 
  32.     } 
  33.                                                                                                                                             
  34.     public String getName() {  
  35.         return name; 
  36.     } 
  37.                                                                                                                                                           
  38.     public List<Task> getTasks() {  
  39.         return tasks; 
  40.     } 

保存数据时,代码就可以如下:

  1. TaskList taskList = new TaskList("StackMob Tasks"); 
  2. taskList.getTasks().add(new Task("Learn about relations", new Date())); 
  3. taskList.getTasks().add(new Task("Learn about queries", new Date())); 
  4. taskList.save(StackMobOptions.depthOf(1)); 

StackMob的这种模式,简单易懂,操作上也很方便,数据模型的扩展性也很好。

不过,文件存储就没这么方便了,StackMob不提供将文件上传到它自己的平台服务器,只提供接口,让你将文件上传到开发者自己的S3上面。也就是说,开发者必须自己先申请AWS的S3,才可以使用StackMob提供的文件存储服务。

还有,StackMob的推送服务是使用Google的GCM服务的,所以,开发者还需要拥有Google的GCM账号才能注册使用StackMob的推送服务。

另外,其Model和Controller的分离也还不够好。例如,对于用户操作的方法,在StackMobUser里提供了很多方法,但在StackMob里也提供了不少方法。如果将数据操作的部分可以统一接口就更好了。

再看看StackMob提供的Custom Code,它也提供了操作后台数据很全面的各种方法和类。使用起来也挺简单,比如写个hello_world的例子,后台服务类需要实现CustomCodeMethod接口,比如下面代码:

  1. public class HelloWorldExample implements CustomCodeMethod {  
  2.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
  3.   /** 
  4.    * This method simply returns the name of your method that we'll expose over REST for 
  5.    * this class. Although this name can be anything you want, we recommend replacing the 
  6.    * camel case convention in your class name with underscores, as shown here. 
  7.    * 
  8.    * @return the name of the method that should be exposed over REST 
  9.    */ 
  10.   @Override 
  11.   public String getMethodName() {  
  12.     return "hello_world"; 
  13.   } 
  14.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
  15.   /** 
  16.    * This method returns the parameters that your method should expect in its query string. 
  17.    * Here we are using no parameters, so we just return an empty list. 
  18.    * 
  19.    * @return a list of the parameters to expect for this REST method 
  20.    */ 
  21.   @Override 
  22.   public List<String> getParams() {  
  23.     return Arrays.asList(); 
  24.   } 
  25.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
  26.   /** 
  27.    * This method contains the code that you want to execute. 
  28.    * 
  29.    * @return the response 
  30.    */ 
  31.   @Override 
  32.   public ResponseToProcess execute(ProcessedAPIRequest request, SDKServiceProvider serviceProvider) {  
  33.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  34.     //Send push messages... 
  35.     //Query the datastore... 
  36.     //Run complex server side operations.. 
  37.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  38.     //Then prepare your custom JSON to send back to the mobile client 
  39.     Map<String, String> args = new HashMap<String, String>(); 
  40.     args.put("msg", "hello world!"); 
  41.     return new ResponseToProcess(HttpURLConnection.HTTP_OK, args); 
  42.   } 
  43.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

然后,在Android端这样调用:

  1. StackMob.getStackMob().getDatastore().get("hello_world", new StackMobCallback() {  
  2.     @Override public void success(String responseBody) {  
  3.         //responseBody is "{  \"msg\": \"Hello, world!\" }" 
  4.     } 
  5.     @Override public void failure(StackMobException e) {  
  6.     } 
  7. }); 

StackMob教程指南:https://developer.stackmob.com/tutorials

#p#

Parse

Parse比StackMob晚成立一年,近期也得到了700万美元的注资,目前团队20人,有2万名开发者使用其平台,40万款应用使用其服务。 支持的API有iOS、Android、JavaScript、Windows 8,以及提供了REST API和Cloud Code JS API。Cloud Code JS API和StackMob的Custom Code一样用于服务端开发,处理自己的逻辑,不同的是,StackMob用Java或Scala开发,而Parse提供JS的接口。Parse提供的功 能服务也算是比较全面的,StackMob提供的大部分功能服务,它也提供了。而支持Windows8,这点还比StackMob领先了一步。另外,它对 ACL的设置也比StackMob灵活。StackMob只能在后台管理页面对角色设置ACL,而Parse可以在代码中设置全局的ACL,也可以对每个 对象设置ACL。文件存储方面,Parse虽然也是保存在S3,但它将用户的文件保存在自己的平台,而不是开发者自己的S3,这一点也比StackMob 要方便得多。

不过,Parse的SDK使用起来就没StackMob那么方便了。Parse保存和查询对象的代码如下:

  1. ParseObject gameScore = new ParseObject("GameScore"); 
  2. gameScore.put("score", 1337); 
  3. gameScore.put("playerName", "Sean Plott"); 
  4. gameScore.put("cheatMode", false); 
  5. gameScore.saveInBackground(); 
  6.                                                                          
  7. ParseQuery query = new ParseQuery("GameScore"); 
  8. query.getInBackground("xWMyZ4YEGZ", new GetCallback() {  
  9.   public void done(ParseObject object, ParseException e) {  
  10.     if (e == null) {  
  11.       int score = object.getInt("score"); 
  12.       String playerName = object.getString("playerName"); 
  13.       boolean cheatMode = object.getBoolean("cheatMode"); 
  14.     } else {  
  15.       // something went wrong 
  16.     } 
  17.   } 

这样子,开发者就很难定义自己的数据模型,全部操作都只能通过ParseObject了。Model和Controller完全耦合在一起,应用与Parse的耦合性非常强,如果开发者想要移植到其他平台就会很麻烦。而且,这种模式,对于开发比较复杂的应用也将变得麻烦。

再看看Parse的Cloud Code。使用Parse的Cloud Code,需要下载Parse提供的命令行工具,然后需要用parse new命令创建一个存放代码的目录,还需要输入邮箱和密码登录开发者的账号,选择一个应用,并用cd命令进入创建的目录:

$ parse new MyCloudCodeEmail: ninja@gmail.comPassword:1:MyAppSelect an App: 1$ cd MyCloudCode

MyCloudCode目录会自动生成几个文件:

-config/  global.json-cloud/  main.js

其中,main.js就是保存开发者自己所有Cloud Code的地方。写个最简单的例子:

  1. Parse.Cloud.define("hello", function(request, response) {  
  2.   response.success("Hello world!"); 
  3. }); 

然后用parse deploy命令部署到Parse平台上:

$ parse deploy

然后,在Android端就可以用以下代码调用:

  1. ParseCloud.callFunction("hello", new HashMap<Object, Object>(), new FunctionCallback<String>() {  
  2.    void done(String result, ParseException e) {  
  3.        if (e == null) {  
  4.           // result is "Hello world!" 
  5.        } 
  6.    } 
  7. }); 

Parse文档:https://parse.com/docs

#p#

Kinvey

Kinvey则是TechStars下的一家创业公司,也是去年成立,到目前为止也已经得到了700万美元的投资,目前团队19人,而使用其平台的 应用数则没有公布。前端支持的API有iOS、Android、JavaScript和REST,后端同样提供了Backend Logic接口供开发者处理后台逻辑。相较于StackMob和Parse,Kinvey提供的功能就没那么全面了,缺少了角色管理,也缺少了地理位置服 务。

Kinvey的SDK有一点我比较喜欢,那就是Model和Controller有了较好的分离,Model提供了接口 MappedEntity,Controller则用KCSClient做入口。不过,数据模型的定义却不如StackMob那样方便,多了一步属性与后 台表字段的映射。代码如下:

  1. public class MyEntity implements MappedEntity {  
  2.     private String uname; 
  3.     private String id; 
  4.                                                                                  
  5.     @Override 
  6.     public List<MappedField> getMapping() {  
  7.         return Arrays.asList(new MappedField[] {  new MappedField("uname", "name"), 
  8.                                                 new MappedField ("id", "_id") }); 
  9.     } 
  10.                                                                                    
  11.     // Getters and setters for all fields are required 
  12.     public String getUname() {  return uname; } 
  13.     public void setUname(String n) {  uname = n; } 
  14.     public String getId() {  return id; } 
  15.     public void setId(String i) {  id = i; } 
  16.                                                                                       

其中,getMapping方法就是处理映射关系。然后保存数据就可以通过以下代码:

  1. MyEntity item = ...; 
  2.                                                                      
  3. item.setName("Idle Blue"); 
  4.                                                                             
  5. mKinveyClient.mappeddata("collectionName").save(item, new ScalarCallback<MyEntity>() {  
  6.                                                                                   
  7.   @Override 
  8.   public void onFailure(Throwable e) {  ... } 
  9.                                                                      
  10.   @Override 
  11.   public void onSuccess(MyEntity r) {  ... } 
  12.                                                           
  13. }); 

其中,mKinveyClient.mappeddata("collectionName")方法得到MappedAppData,该类封装了 MappedEntity相关的各种操作。另外,通过mKinveyClient.resource("name")方法则得到 KinveyResource,该类封装了文件相关的各种操作。

Kinvey另外还提供了和ParseObject类似的方式,代码如下:

  1. EntityDict album = mKinveyClient.entity("albums"); 
  2. album.putProperty("title", "Idle Blue"); 
  3. album.save(new ScalarCallback<EntityDict>() {  
  4.                                                     
  5.     @Override 
  6.     public void onFailure(Throwable e) {  ... } 
  7.                                                                     
  8.     @Override 
  9.     public void onSuccess(EntityDict r) {  ... } 
  10.                                                                
  11. }); 

Kinvey的Backend Logic与StackMob和Parse有着很大不同。StackMob和Parse虽然处理方式不同,但基本思路都是前端传送指定的方法(如 hello_world),后台写相应的代码处理这个方法。而Kinvey的Backend Logic则是在对数据库操作的前后分别提供接口处理。如下图:

PreProcess提供了几个方法:

  1. function onPreSave(request,response,modules){  
  2.                                                                                                
  3.  
  4. function onPreDelete(request,response,modules){  
  5.      
  6.  
  7. function onPreFetch(request,response,modules){  
  8.                                                                                                                  

PostProcess也提供了几个方法:

  1. function onPostSave(request,response,modules){  
  2.                                                                                                           
  3.     
  4. function onPostDelete(request,response,modules){  
  5.     
  6.     
  7. function onPostFetch(request,response,modules){  
  8.  

Kinvey文档:http://docs.kinvey.com/overview.html

#p#

Bmob

Bmob不是一家公司的名字,只是广州一家叫鹏锐的IT公司的其中一个产品。Bmob应该算是国内第一个BaaS平台,今年4月份的时候上线的。而 到目前为止,Bmob还只有Android的SDK,而且还是山寨Parse的,但功能比Parse少了很多,没有角色管理,没有ACL,也没有关系查 询,更没有后端的Cloud Code,跟Parse的SDK比较一下,就会知道相比Parse少了非常多的东西,基本上就是Parse的一个简化版。版本升级过一次,在第二版加入了 支付功能,而支付卡基本上都是些游戏卡,很明显,这是为付费游戏提供的服务。

看看Bmob的代码,和Parse一样的吧:

  1. BmobObject gameScore = new BmobObject("GameScore"); 
  2. gameScore.put("score", 1200); 
  3. gameScore.put("playerName", "张小明"); 
  4. gameScore.put("cheatMode", false); 
  5. try {  
  6.     gameScore.save(); 
  7. } catch (BmobException e) {  
  8.     // e.getMessage() 捕获的异常信息 

Bmob第一版的时候,就出现过很多问题,如经常断线,数据丢失等,逐渐失去开发者的信任,基本功能也还很不完善。而第二版没有去完善那些重要的功 能,提高开发者的信任度,反而推出了支付功能,我觉得这是个错误的策略。首先,重点应该放在完善基本功能和提高开发者对平台的信任度;其次,支付功能这种 安全性要求非常高的服务,只有在平台已经非常成熟,用户对其已经非常信任的前提下提供才会有效用,在经常断线,数据会出现丢失的情况下,有谁敢去用支付功 能呢?

另外,Bmob还提供了很多应用分析的功能,这一点,我也觉得多余了。专业的应用分析,已经有友盟平台了,没必要自己再做一套。

Bmob还存在很多不成熟的地方,第一版上线到目前也已经半年多了,改善的东西很少,发展速度较慢,给我的感觉就是他们没有抓到真正的重点,或者他们将精力移到了广告平台——他们的另一个产品,毕竟那是实实在在可以赚到钱的产品。

Bmob官网:http://bmob.cn/

#p#

AMTBaaS

AMTBaaS是诚迈科技最近推出的BaaS平台,9月中旬发布了iOS的SDK,10月中旬又发布了Android的SDK。目前,处于内测阶 段。提供的文档,除了API,也只有一个用户手册提供下载。网站和文档的用户体验都比较差,其SDK的体验也是很差,就说一个用户注册的方法:

  1. register(Context context, java.lang.String useremail, java.lang.String passWord, java.lang.String confirmPwd, boolean ischeckCode, java.lang.String checkcode, AmtUserCallback amtUserCallback) 

再看看用户注册的操作:

  1. // 注册消息 
  2. public static final int MESSAGE_REGISTER = 1001; 
  3. // 构造AmtUser对象 
  4. private AmtUser amtUser = new AmtUser(); 
  5. // 注册 
  6. amtUser.register(UserActivity.this, “user@qq.com”, “123456”, “123456”, true, “53Fe”, new AmtUserCallback() {  
  7.     @Override 
  8.     public void onSuccess(Object object) {  
  9.         if (object != null) {  
  10.             // 回调方法中不可直接操作UI控件 
  11.             mhandler.sendMessage(mhandler.obtainMessage( 
  12.                 MESSAGE_REGISTER, object)); 
  13.         } 
  14.     } 
  15.                                                                                                                                                                                                                         
  16.     @Override 
  17.     public void onFailure(AmtException amtException) {  
  18.         if (amtException != null) {  
  19.             // 回调方法中不可直接操作UI控件 
  20.             mhandler.sendMessage(mhandler.obtainMessage( 
  21.                 MESSAGE_REGISTER, amtException)); 
  22.         } 
  23.     } 
  24. }); 
  25. /** 
  26. * 注册回调句柄 
  27. */ 
  28. Handler handler = new Handler() {  
  29.     @Override 
  30.     public void handleMessage(Message msg) {  
  31.         super.handleMessage(msg); 
  32.         switch (msg.what) {  
  33.             case MessageTypes.MESSAGE_REGISTER: 
  34.             // 注册失败 
  35.             if (msg.obj instanceof AmtException) {  
  36.              AmtException amtException = (AmtException)msg.obj; 
  37.              AmtUtil.log("UserActivity", "注册失败:"+ 
  38.                         amtException.getMessage(), "i"); 
  39.             } 
  40.             // 注册成功 
  41.             else if (msg.obj instanceof String) {  
  42.              String result = (String)msg.obj; 
  43.              If (AmtConstants.SUCCESS.equals(result) {  
  44.                  AmtUtil.log("UserActivity", "注册成功", "i"); 
  45.              } 
  46.             } 
  47.             break; 
  48.         } 
  49.     } 
  50. }; 

一个注册就这么麻烦,完全不懂用户体验。对于其前景不看好。

AMTBaaS官网:http://amtbaas.com/

#p#

Xone

Xone则是我们公司现在的核心产品,目前开发了两个月左右,前端只支持 Android,目前的SDK提供的功能有版本管理、数据存储、用户管理、文件存储、地理信息服务,推送服务还没开发出来。后端也提供JS的 Backend Logic服务,刚开发完。网站也只是搭了个雏形,现在正在重新设计和完善之中。

为了将Model和Controller较好地分离并能简单的使用SDK,我们采用了这样的结构:

1. 数据模型我们定义了一个基类XoneEntity,类里只定义了几个基本属性,不带任何数据操作的方法。另外定义了继承它的两个子 类,XoneGeoEntity和XoneUser,XoneGeoEntity用于带有地理信息的数据模型,XoneUser则是用户数据模型。应用程 序自身的数据模型则继承XoneEntity,然后定义自己的属性即可,不需要像Kinvey那样还要做映射。如果应用程序自身的数据模型需要包含地理信 息,则继承XoneGeoEntity,用户模型则继承XoneUser。

2. 对各种服务分类提供了接口,每个接口里定义了相应的数据操作的方法。服务接口有:

  • AppService:应用程序和平台相关的服务接口
  • CollectionService<T extends XoneEntity>:集合相关的服务接口
  • UserService<T extends XoneUser>:用户相关的服务接口
  • FileService:文件相关的服务接口

3. XoneClient是Controller的入口,通过XoneClient实例的getXXXService()的各种方法调用各种服务接口,再通过服务接口调用具体的数据操作方法。比如,用户注册:

  1. UserService<XoneUser> userService = xoneClient.getUserService(); 
  2. userService.signUp(user, callback); 

一切都还在完善之中,各种功能服务,以及网站。后续,当我们的平台正式上线时,我们的SDK还将会开源。

Xone官网:http://xone.im/

责任编辑:徐川 来源: diandian BaaS后端即服务云存储云推送

(责任编辑:焦点)

    推荐文章
    热点阅读