ionic-基于angular-resource的restful开发

时间:2021-06-25 23:01:08
悟!
心有多大,梦想就有多大!
技术资本的积累,是为了等待合适时机的全能释放!

ionic用来开发跨平台的app,实现客户端和服务端的分离,他们之间的通信一般是通过XMLHTTPREQUEST的异步方式,由于angualrjs的双向绑定,我们可以非常容易在客户端实现数据处理。

我们知道由于js的'同源策略',XMLHTTPREQUES原则上是不能实现跨域请求的,但是在我们的实际应用场景中,特别是请求第三方api的时候,就必须要实现跨域请求。

当然,解决这个跨域的问题,有很多的方法,比如jsonp,服务端设置http请求头的Access-Control-Allow-Headers等,具体的方式这里不多说了,大家可以自行百度

那么在ionic开发app的时候,我们是通过restful的api与服务端进行数据交换,对于我们的接口设计分成有帮助,包括版本的升级,因为app会不断升级,增加功能,对应的rest的接口也是对应不同的版本。可以参考我之前写的关于yii2的restful的文章
http://blog.csdn.net/u012979009/article/details/52055794

下面我将根据项目的实际整理一下知识
客户端:ionic + angularjs + angualar-resource.js
服务端:yii2框架-restful api

客户端:
angualar-resource.js是一个封装好的功能和性能比$http表现好的模块,具体的一些基础知识可以百度,下面知识简单说一下。
https://docs.angularjs.org/api/ngResource/service/$resource
我们在使用之前需要引入
<script src="lib/ionic/js/angular/angular-resource.js"></script>

那么在我们的应用中
在我们的应用中需要将其当做依赖进行引用 
  angular.module('myApp', ['ngResource']);

使用 
$resource服务本身是一个创建资源对象的工厂,返回的$resource对象中包含了同后端服务器进行的交互的高层API.

var User=$resource(url,[defaultparams],[action],[options]);
上面这一句是创建一个资源的对象
url:请求的uri(必须设置)
defaultparame: 附带在url的query参数(可选设置)
比如:var User=$resource('/api/users/:userId',{userId:'@id','sex':'1'});
@id就是代表在具体请求的参数
User.get({'userId':1},successfn,failfn);
那么这个最终的请求会变成
/api/users/1?sex=1,
{'userId':1}相当于请求的data,那么@id的值等于data.userId这样子来获取的,如果没有找到对应的key键,则将忽略:userId这个值
如下面:
User.get({'id':1},successfn,failfn);
Id并不是在{userId:'@id','sex':'1'}对应的key,所以最终的请求变成
/api/users?id=1&sex=1,

其实userId是占位符,或者可以说是key,最终的会找到对应的值id,那么后面的其他key-value值将作为query参数附带在url后面。

action: 是一个对象,可以自定义action,并且设置不同请求方法的请求体等信息
https://docs.angularjs.org/api/ng/service/$http#usage
格式
{
action1: {method:?, params:?, isArray:?, headers:?, ...},
  action2: {method:?, params:?, isArray:?, headers:?, ...},

}

例如

{
query: {method: 'get', isArray: false},
save: {method: 'post', headers:{'Content-Type': 'application/x-www-form-urlencoded'}}
}
action: 就是我们为resource定义的方法,可以自定义,比如sendEmail。
method:get,post等http请求方法
params:请求参数
isArray :返回是否数组
headers :设置请求头信息
.....
具体方法可以认真看看,基本用到的也就是上面几个。
可以把User对象理解成同RESTful的后端服务进行交互的接口。


下面说一下关于angular-resource的actions.

anular-resource默认的已经定义好的http请求的action有以下:
A、get 查找单个数据
User.get(params,successFn,errrorFn);
params可以不设置
//GET /api/users 
   User.get(function(resp){ 
    //处理成功 
    
   },function(err){ 
    //处理错误 
    
  });
如果参数中传入了具名参数(我们例子中的参数是id),那么get()方法会向包含id的URL发送请求:    
    //发起一个请求:GET-->/api/users/123 
    User.get({userId:'1234'},function(resp){ 
       //success 
    },function(error){ 
       //fail 

    });


B、get 查找批量数据
User.query(params,successFn,errrorFn);
params可以不设置
query向指定URL发送一个GET请求,并期望返回一个JSON格式的资源对象集合。 
  //发起一个请求 
  User.query(function(users){ 
    //读取集合中的第一个用户 
    var user=users[0]; 
  });

如果设置paramms查找在一定区间的数据
User.query({'startId':10,'endId':500},successFn,errrorFn);
那么请求url变成GET-->/api/users?startId=10&endId=500
query()和get()方法之间唯一的区别是AngularJS期望query()方法返回数组

C、post
User.save(params, payload, successFn, errorFn);保存数据
params: 默认附带在url后面的参数,如果没有数据,需要设置{}对象

payload: 请求体信息,{'name':'bing','sex':1}的json格式

可以这样子使用:

.save({},$httpParamSerializer({'name':'bing','sex':1}),function(resp){ 
       console.log(resp);
    },function(error){ 
       //fail 
  });
在这里大家一定要注意一个angularjs的post请求的请求头的Content-Type是application/json,并不是表单post数据时的application/x-www-form-urlencoded,而且post的数据{'name':'bing','sex':1}并不会自动转为符合x-www-form-urlencoded的name=bing&sex=1。而表单post数据的时候,请求体会变成name=bing&sex=1这种格式的,在服务端才能够正确地通过$_POST来获取数据。
大家可以看一下我之前的博客

点击打开链接


所以用了$httpParamSerializer将{'name':'bing','sex':1}转成name=bing&sex=1这种格式,同时请求头也必须设置成
save: {method: 'post', headers:{'Content-Type': 'application/x-www-form-urlencoded'}}
只有设置这两个地方,post的数据才能在服务端通过$_POST获取。

D、delete 
delete(params, payload, successFn, errorFn)    
 delete方法会向指定URL发送一个DELETE请求,并用数据体来生成请求体。它被用来在服务器上删除一个实例:     
    // DELETE /api/users/123 
    User.delete({}, { 
        id: '123' 
    }, function(response) { 
    // 处理成功的删除响应 
    }, function(response) { 
    // 处理非成功的删除响应 
    }); 

remove(params, payload, successFn, errorFn) 
    remove方法和delete()方法的作用是完全相同的,它存在的意义是因为delete是JavaScript的保留字,在IE浏览器中会导致额外的问题。      
    // 发起一个请求: 
    // DELETE /api/users/123 
    User.remove({}, { 
     id: '123' 
    }, function(response) { 
    // 处理成功的删除响应 
    }, function(response) { 
    // 处理非成功的删除响应 
   });

服务端:
服务端使用yii2的restful的API接口
为了实现可以接受跨域请求,可以使用yii\filters\Cors
跨域资源共享 CORS 机制允许一个网页的许多资源(例如字体、JavaScript等) 这些资源可以通过其他域名访问获取。 特别是JavaScript's AJAX 调用可使用 XMLHttpRequest 机制, 由于同源安全策略该跨域请求会被网页浏览器禁止. CORS定义浏览器和服务器交互时哪些跨域请求允许和禁止。
yii\filters\Cors 应在 授权 / 认证 过滤器之前定义, 以保证CORS头部被发送。

use yii\filters\Cors;
use yii\helpers\ArrayHelper;

public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
        ],
    ], parent::behaviors());
}
Cors 可转为使用 cors 属性。

cors['Origin']: 定义允许来源的数组,可为['*'] (任何用户) 或 ['http://www.myserver.net', 'http://www.myotherserver.com']. 默认为 ['*'].


cors['Access-Control-Request-Method']: 允许动作数组如 ['GET', 'OPTIONS', 'HEAD']. 默认为 ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'].


cors['Access-Control-Request-Headers']: 允许请求头部数组,可为 ['*'] 所有类型头部 或 ['X-Request-With'] 指定类型头部. 默认为 ['*'].


cors['Access-Control-Allow-Credentials']: 定义当前请求是否使用证书,可为 true, false 或 null (不设置). 默认为 null.

cors['Access-Control-Max-Age']: 定义请求的有效时间,默认为 86400.


例如,允许来源为 http://www.myserver.net 和方式为 GET, HEAD 和 OPTIONS 的CORS如下:
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['http://www.myserver.net'],
                'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
            ],
        ],
    ], parent::behaviors());
}
可以覆盖默认参数为每个动作调整CORS 头部。例如, 为login动作增加Access-Control-Allow-Credentials参数如下所示:

use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['http://www.myserver.net'],
                'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
            ],
            'actions' => [
                'login' => [
                    'Access-Control-Allow-Credentials' => true,
                ]
            ]
        ],
    ], parent::behaviors());

}

所以在服务端的Controller的必须要设置,当然事先的完成restful的API先

下面是我测试的例子
public function behaviors() {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => QueryParamAuth::className(),
        ];

        return ArrayHelper::merge([
            [
                'class' => Cors::className(),
                'cors' => [
                    'Origin' => ['http://192.168.1.101:8100'],
                    'Access-Control-Request-Headers' => ['Origin', 'X-Requested-With', 'Content-Type', 'Accept'],
                    'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
                ],
            ],
        ], $behaviors);
      
    }

根据实际的需求和功能设置cors数组的属性。