前言
所有微服务的模型文件都必须继承于 MicroService 类,该类定义了一些常用的公共方法,便于在管理服务、调用服务时达到统一规范的目的。
在管理和使用服务时,会大量调用以下的方法,如果您需要更灵活的提供服务,可以在服务的模型文件重定义如下方法。
公共方法
getApis
该方法用于列出该服务支持的接口列表和外部说明文档,默认从描述文件获取数据,并按格式自动生成接口文档。当接口过多时,可以在服务端模型文件声明该方法,将完整的接口数据提供给继承的方法。
建议暂时使用外部接口文档。
源码详解
/*** 获取该服务的API接口* @param array|null $data 附加接口数据* @return array API接口*/public function getApis($data=array()){$apis = $this->service['apis'];$apis['schemas'] = array_merge($apis['schemas'], $data);return $apis;}//调用示例:其中identity为服务标识$apis = serv("identity")->getApis();
参数说明
- $data :附加接口数据,默认会从描述文件内读取,可以在模型文件内定义同名方法补充该变量。(注意:该参数的格式必须统一并严格安装说明文档的结构)
返回数据
array( "wiki"=>"", //接口外部说明文档,http或https开头 "schemas"=>[] //接口列表,其数组元素为接口的实例,具体结构请参考相关文档 );
getMethods
该方法用于列出该服务支持的内置方法,默认从描述文件读取,并按格式自动生成服务的方法调用详解。当内置方法过多时,可以在服务端模型文件声明该方法,将完整的内置方法数据提供给继承的方法。
源码详解
/**
* 获取该服务的内置方法
* @param array|null $data 附加内置方法
* @return array 内置方法数据
*/
public function getMethods($data=array()){
$methods = $this->service['methods'];
return array_merge($methods, $data);
}
//调用示例:其中identity为服务标识
$methods = serv("identity")->getMethods();
参数说明
- $data :附加内置方法数据,默认会从描述文件内读取,可以在模型文件内定义同名方法补充该变量。(注意:该参数的格式必须统一并严格安装说明文档的结构)
返回数据
array( "wiki"=>"", //内置方法的外部说明文档,http或https开头 "method1"=>[], //内置方法,结构请参考下方方法 "UpdateInfo"=>[ "name"=>"更新资料", "summary"=>"更新用户资料", "params"=>array( "uid"=>["UID","int"], "profile"=>["用户资料数组,字段一一对应","array"] ), "requires"=>["uid","profile"], "return"=>["更新结果","bool"] ] );
getEntry
该方法用于获取服务的后台管理入口,默认读取描述文件的entrance字段的值。当需要更灵活的方式访问入口时,可以在服务的模型文件重新定义方法。
当描述文件的entrance字段值为空,且不存在默认控制器 web/IndexController 时,表示该服务不需要后台管理,只需要通过接口和内置方法提供来服务。
源码详解
/**
* 获取该服务的后台入口
* @param string|null $entrance;
* @return string 后台入口URL
*/
public function getEntry($entrance=""){
if(empty($entrance)){
$entrance = $this->service['entrance'];
}
if (strpos($entrance,'http')===0) return $entrance;
if ($this->service['drive']=='php'){
if ($entrance=='' && file_exists($this->serverpath.$this->identity."/web/IndexController.php")){
$entrance = 'index';
}
if (!empty($entrance)){
return $this->url($entrance);
}
return $entrance;
}else{
return $entrance;
}
}
//调用示例:其中identity为服务标识
$weburl = serv("identity")->getEntry();
参数说明
- $entrance :入口路由名称,默认会从描述文件内读取。当需要更灵活的生成入口时,可以在模型文件内定义同名方法提供变量。
返回数据
$weburl = serv("ucenter")->getEntry("member"); //返回 "/serv/ucenter/member"
error
该方法返回统一的错误信息格式
/**
* 返回错误信息
* @param string $msg 说明
* @param int|null $code 状态码
* @param array 统一错误格式
*/
public function error($msg, $code=-1){
return error($code, $msg);
}
success
该方法返回统一的接口数据格式(一般是交互成功时)
/**
* 返回成功信息
* @param string|array|object $msg 说明或者数据内容
* @param string|null $redirect 成功后跳转地址
* @return array 返回成功输出
*/
public function success($msg, $redirect=""){
return array(
'message'=>$msg,
'redirect'=>trim($redirect),
'type'=>'success'
);
}
api
源码详解
/**
* 生成API URL
* @param string $route 路由名称
* @param array|null $query URL参数
* @param string|null $platform 接口通道
* @return string API接口
*/
public function api($route, $query=array(), $platform=""){
global $_W;
$query['i'] = $_W['uniacid'];
return "{$_W['siteroot']}/api/serv/". $this->identity . "/{$route}?" . http_build_query($query, '', '&');;
}
//调用示例:其中identity为服务标识
$api = serv("identity")->api("member", array("groupid"=>1));
参数说明
- $route:路由名称,默认情况下,访问该方法生成的URL,最终会运行下方的HttpRequest()方法,并将此参数传递给对应的 $route 参数,对应的 $platform 参数值为”api“
- $query:数组格式的URL参数,在系统内可以通过全局变量$_GPC获得
- $platform:接口通道,默认是API,可以自定义(例如app、web、wxapp等),不同管道对应不同的控制器文件夹。
返回数据
$api = serv("ucenter")->api("connect/register", array("from"=>'discuzx')); //返回:"https://yourdomain.com/api/serv/ucenter/connect/register?i=1&from=discuzx"
url
源码详解
/**
* 生成后台URL
* @param string|null $do 路由名称
* @param array|null $query URL参数
* @param bool|null $full 是否完整拼接
* @return string 后台URL
*/
public function url($route='', $query=array(), $full=false){
if(empty($query['do'])){
$query['do'] = 'server';
}
$query['server'] = $this->identity;
$ctrl = str_replace("/", ".", $route);
if (!empty($ctrl)) {
$query['ctrl'] = $ctrl;
}
$query['m'] = MODULE_IDENTIFIE;
$url = wurl('site/entry', $query);
if (!$full) return $url;
global $_W;
return $_W['siteroot'] . "web/" . substr($url, 2);
}
//调用示例:其中identity为服务标识
$weburl = serv("identity")->url("member", array("groupid"=>1));
参数说明
- $route :路由名称,默认情况下,访问该方法生成的URL,最终会运行下方的HttpRequest()方法,并将此参数传递给对应的 $route 参数,对应的 $platform 参数值为”web“
- $query:数组格式的URL参数,在系统内可以通过全局变量$_GPC获得
- $full:是否返回完整的网址(带http和域名),否则返回相对路径的URL
返回数据
$weburl = serv("ucenter")->url("member", array("groupid"=>1), true); //返回 "https://yourdomain.com/serv/ucenter/member?groupid=1"
HttpRequest
当通过HTTP方式访问的服务时,最终运行的是服务的该方法。
微服务提供者可以在该方法内定义自己的路由规则,来实现任何功能。
源码详解
/**
* 接管路由
* @param string|null $platform 路由通道,可选web、app、api及自定义通道
* @param string|null $route 路由名称
* @return array|error 返回接口数据或报错信息
*/
public function HttpRequest($platform="web", $route=""){
global $_GPC;
...
$route = str_replace(".","/",$route);
list($controller, $method) = explode("/", $route);
...
//定义运行目录
$basepath = $this->serverpath . $this->identity;
//定义控制器
$ctrl = "$basepath/$platform/".ucfirst($controller)."Controller.php";
...
//引用控制器
include_once $ctrl;
$class = ucfirst($controller)."Controller";
$instance = new $class();
return $instance->$method();
}
参数说明
- $platform:路由通道,可选web、app、api及自定义通道。正常情况下,通过url()方法获取的链接,访问时该参数值为”web“,通过api()方法获取的链接,访问时该参数值为”api“
- $route:自定义路由名称。默认情况下,该参数与上方的api()方法和url()方法的$route参数对应。
Event
微服务的内置方法可以声明要广播的事件名,当调用该方法时,会将特定数据广播给系统。如果在开发应用或其它插件需要监听这个事件并处理对应数据时,只需要按对应规范指定监听器来监听对应事件即可。
事件广播的更多说明请参考:https://www.yuque.com/shenwa/qingru/hng28f#C6hH5
源码详解
/**
* 事件广播
* @param string $listener 广播事件名
* @param array|null $data 广播数据
* @param array|null|mixed 服务构造参数
* @return bool 广播结果
*/
public function Event($listener, $data=array(), $param=null){
......
//发送事件广播,将会触发所有监听该事件的微服务
return true;
}
参数说明
- $listener:广播事件名
- $data:要广播给监听器的数据
- $param:微服务构造参数,部分微服务的实例化需要给定参数
Processor
当微服务需要监听其它微服务的事件时,需要在manifest.json文件指定需要监听的广播事件名。当该事件被触发时,会执行对应微服务的此方法,并传递事件名和对应参数。
注:
- 在处理器内请慎用exit()、die()等强制结束语句;
- 请务必严谨处理器内的事件广播逻辑,避免反复嵌套执行事件死循环。
{ "application":{ "name": "用户服务" ...... } ...... "events": ["storage.remove"], #监听的事件列表 ...... }/** * 事件处理器 * @param string $listener 事件名 * @param array|null $data 广播数据 * @return bool */ public function Processor($listener, $data=array()){ //Todo something return true; }参数说明
- $listener:广播事件名
- $data:传递的数据
View
微服务的视图编译方法,会自动将数据渲染到指定的HTML模板或Blade模板。
具体的使用方法与原理请参考视图View详解
源码详解
/**
* 视图编译
* @param array $data 模板数据
* @param string $template 模板名称
* @return bool
*/
public function View($data, $template=''){
global $_W,$_GPC;
......
//判断模板通道
$platform = defined('IN_SYS') ? 'web' : 'app';
if ($this->ComplieDrive=='smarty'){
//默认HTML模板
......
include $compile;
exit();
}else{
//Laravel Blade 模板
}
return true;
}
参数说明
- $data:需要动态渲染的数据
$template:模板名称。默认值是当前请求的路由名称,该名称与视图文件名一一对应。
$weburl = serv("ucenter")->url("member/post"); //该方法返回的URL是 "/serv/ucenter/member/post" //该URL路由名称为 "member/post" //该URL最终运行的是 web/MemberController 控制器的 post() 方法 //在该控制器的post()方法调用时,编译的视图文件是 /template/web/member/post.html /** * 当编译引擎为Blade模板引擎时 * 编译的视图文件是 /blade/web/member/post.blade.php */调用示例
```php class MemberController extends UcenterService {
public function post(){
$this->View(array( 'title'=>"调用示例" ));}
}
<a name="lM9bd"></a>
### Composer
通过类名判断第三方依赖包是否已安装
<a name="CsRjo"></a>
#### 源码详解
```php
/**
* composer检测
* @param string $className 第三方类名
* @return bool|void
*/
public function Composer($className){
if (!class_exists($className)){
//自动加载或者进入composer require 引导
}
return true;
}
参数说明
$className:第三方类名,该类是否存在代表这composer是否已加载。(注:了使用命名空间的类必须要加上对应的命名空间)
调用示例
```php class StorageService extends MicroService {
public function remoteUpload($file){
$this->Composer("JohnLui\AliyunOSS");}
} ```
