服务开发框架

开发者在使用AbleCloud框架开发服务时,仅需简单的使用前文介绍的基础数据结构,将精力集中在实现应用的业务逻辑上,快速完成服务程序的开发/测试/发布。

ACService:UDS

AbleCloud定义了抽象基类ACService,开发者只需要继承该类,并实现各个handler即可。定义如下:

public abstract class ACService {
    // 开发者可以调用ac的相关接口直接调用AbleCloud提供的云服务。
    protected AC ac;

    // 以下信息可用于服务内部追踪问题等用,比如打印到日志中
    protected long developerId;         // 开发者id
    protected String majorDomain;       // 服务的主域名
    protected String subDomain;         // 服务的子域名
    protected int majorVersion;         // 服务的主版本号
    protected int minorVersion;         // 服务的副版本号
    protected int patchVersion;         // 服务的修订版本号

    /**
     * 开发者可根据自身需要,重载该方法,在该方法里做一些初始化工作,框架在启动服务时会调用该函数。
     *
     * @throws Exception
     */
    public void init() throws Exception {}

    /**
     * 处理APP-->Service,Service-->Service之间的交互消息
     * @param req   请求消息体
     * @param resp  响应消息体
     * @throws Exception
     */
    public abstract void handleMsg(ACMsg req, ACMsg resp) throws Exception;

    /**
     * 处理匿名请求
     *
     * @param req  请求消息体
     * @param resp 响应消息体
     * @throws Exception
     */
    public void handleAnonymousMsg(ACMsg req, ACMsg resp) throws Exception {}

    /**
     * 处理Device-->Service之间的交互消息
     * 如果服务不处理和设备之间的交互消息,则无须重载该方法。
     * <p/>
     * 该接口处理设备汇报的消息后不做响应处理。
     *
     * @param reportInfo 设备的信息,包括上下文/设备逻辑id/设备物理id/设备ip
     * @param req        请求消息体
     * @throws Exception
     */
    public abstract void handleDeviceMsg(ACDeviceReportInfo reportInfo, ACDeviceMsg req) throws Exception;

    /**
     * 处理Device-->Service之间的交互消息并做响应
     * 与以上方法对比,如果需要给上报的设备回复响应,则重载该方法
     * <p/>
     * 处理设备汇报的消息并做响应。
     *
     * @param reportInfo 设备的信息,包括上下文/设备逻辑id/设备物理id/设备ip
     * @param req        请求消息体
     * @param resp       回复消息体
     * @throws Exception
     */
     public void handleDeviceMsg(ACDeviceReportInfo reportInfo, ACDeviceMsg req, ACDeviceMsg resp) throws Exception {}

     /**
      * 异步处理Device-->Service之间的交互消息(需要在init方法中调用ACThreadPool.init()初始化才能生效)
      *
      * @param reportInfo 设备的信息,包括上下文/设备逻辑id/设备物理id/设备ip
      * @param req        请求消息体
      */
      public void handleAsyncDeviceMsg(ACDeviceReportInfo reportInfo, ACDeviceMsg req) {}

    /**
     * 处理JINDDONG-->Service之间的交互消息,收到Stream点数组,进行设备控制
     *
     * @param context          设备的上下文,其中uid字段为系统填充
     * @param physicalDeviceId 设备的物理id
     * @param req              请求消息体(Stream数组)
     * @param resp             响应消息体
     * @throws Exception
     */
    public void handleJDSetStatusMsg(ACContext context, String physicalDeviceId, List<ACJDMsg> req, ACMsg resp) throws Exception {}

    /**
     * 处理JINDDONG-->Service之间的交互消息,获取设备上所有Stream点
     *
     * @param context          设备的上下文,其中uid字段为系统填充
     * @param physicalDeviceId 设备的物理id
     * @param resp             响应消息体(Stream数组)
     * @throws Exception
     */
    public void handleJDGetStatusMsg(ACContext context, String physicalDeviceId, List<ACJDMsg> resp) throws Exception {}

    /**
     * 处理SUNING-->Service之间的交互消息,收到Stream点数组,进行设备控制
     *
     * @param physicalDeviceId 设备的物理id
     * @param req              请求消息体(Stream数组)
     * @param resp             响应消息体
     * @throws Exception
     */
    public void handleSNSetStatusMsg(ACContext context, String physicalDeviceId, List<ACSNMsg> req, ACMsg resp) throws Exception {
    }

    /**
     * 处理SUNING-->Service之间的交互消息,获取设备上所有Stream点
     *
     * @param physicalDeviceId 设备的物理id
     * @param resp             响应消息体(Stream数组)
     * @throws Exception
     */
    public void handleSNGetStatusMsg(ACContext context, String physicalDeviceId, List<ACSNMsg> resp) throws Exception {
    }

    /**
     * 处理设备强制解绑的消息(不需要调解绑接口,此时不能与设备进行交互)
     * 如果除了解绑设备之外没有任何其他的处理逻辑,则无需继承此方法
     *
     * @param context          设备的上下文,其中uid字段为系统填充
     * @param physicalDeviceId 设备的物理id
     */
    public void handleDeviceForceUnbind(ACContext context, String physicalDeviceId, ACMsg resp) throws Exception {
    }

    /**
     * 处理设备上下线通知
     *
     * @param event 设备上下线的信息
     */
    public void handleDeviceEvent(ACDeviceEvent event) throws Exception {}

    /**
     * 内部调用接口,开发者不用关注且不能修改。
     * 设置服务相关的信息,并将全局AC框架传给服务
     * 服务内部可以使用AC框架提供的各种功能,如
     * 帐号管理、设备管理、存储服务等。
     * @param ac
     * @param config
     */
    public final void setEnv(AC ac, ACConfiguration config) {}

    /**
     * 内部调用接口,开发者不用关注且不能修改。
     * @return
     */
    public final AC getAc() {}
}

ACDeviceReportInfo为设备上报的属性信息,包含如下:

public class ACDeviceReportInfo {
    //设备上下文
    private ACContext context;
    //设备逻辑id
    private Long deviceId;
    //设备物理id
    private String physicalDeviceId;
    //设备的ip地址
    private String ip;
}
public class ACDeviceEvent {
     //设备上下文,可以获取设备的主子域信息
     private ACContext context;
     //设备物理ID
     private String physicalDeviceId;
     //设备状态 0设备下线 1设备上线
     private int status;
     //设备状态发生变化的时间戳,自1970年UTC时间之后的相对毫秒数
     private long timestamp;
}

在上述抽象类中,对开发者来说,总共有七个公共接口,其中init提供了默认实现。如果开发者实现的某一服务不需要和设备直接交互,则直接重载handleDeviceMsg为空实现即可。开发者可以将精力集中在handleMsg接口的实现中,该接口处理客户端请求,并作出响应。下文会对该抽象类进行详细介绍。

注:通常情况下,开发者只需要重点实现handleMsg即可。当然如果需要处理复杂的设备上报数据,则还需要重点实现handleDeviceMsg并根据不同code做不同处理 。

ACCronJob:后台任务

ACCronJob

AbleCloud定义了云端定时任务的抽象基类ACCronJob。开发者需要继承该类,并实现其定义的抽象方法ACCronJob::run,即能完成定时任务的开发。ACCronJob的定义如下:

public abstract class ACCronJob {
    // 开发者可以调用ac的相关接口直接调用AbleCloud提供的云服务。
    protected AC ac;

    // 以下信息可用于任务内部追踪问题等用,比如打印到日志中等。
    protected long developerId;         // 开发者id
    protected String majorDomain;       // 服务的主域名
    protected String subDomain;         // 服务的子域名
    protected int majorVersion;         // 服务的主版本号
    protected int minorVersion;         // 服务的副版本号
    protected int patchVersion;         // 服务的修订版本号

    /**
     * 内部调用接口,开发者不用关注且不能修改。
     * 设置服务相关的信息,并将全局AC框架传给服务。服务内部可以使用AC框架提供的各种功能,如帐号管理、设备管理、存储服务等。
     * @param ac
     * @param config
     */
    public final void setEnv(AC ac, ACConfiguration config) {
        this.ac = ac;
        this.developerId = config.getDeveloperId();
        this.majorDomain = config.getServiceMajorDomain();
        this.subDomain = config.getServiceSubDomain();
        this.majorVersion = config.getServiceMajorVersion();
        this.minorVersion = config.getServiceMinorVersion();
        this.patchVersion = config.getServicePatchVersion();
    }

    /**
     * 用于获取AC框架。
     * @return AC对象。
     */
    public final AC getAc() {
        return ac;
    }

    /**
     * 定时任务的执行函数。
     * @return 返回任务的结束后,进程退出时所使用的状态码。
     * @throws Exception
     */
    public abstract int run() throws Exception;
}

上述抽象类共定义了三个公共方法:ACCronJob::setEnv,ACCronJob::getAC,以及ACCronJob::run。其中,ACCronJob::run是定时任务的执行函数,要求开发者提供具体实现。

Crontab

Crontab定时规则由五部分组成,由左至右分别表示分、时、日、月、周。每个部分之间以空格字符分隔。如“30 12 * * *”表示“每天的12:30”。其中,第一个部分的“30”表示30分,第二个部分的“12”表示12点,后面三个部分的“*”分别表示每天、每月及一星期内的每一天。 规则中各部分的取值范围如下(参考http://linux.vbird.org/linux_basic/0430cron.php):

代表意义 分钟 小时 日期 月份
数字范围 0-59 0-23 1-31 1-12 0-7

其中,“周”的取值为0或7时都表示“星期天”。除此之外,还有如下辅助字符可用于定义时间规则。

辅助字符 代表意义
*(星号) 代表任何时刻。例如“30 12 * * *”中日、月、周都是*, 表示“不论何月、何日、星期几的 12:30”。
,(英文逗号) 用于指定确定的多个值。如果要定义“每天的3:10及6:10”可使用如下规则:“10 3,6 * * *”。
-(连字符) 用于指定时间范围。如果定义“每天的8点至12点之间每小时的20分钟”可使用如下规则:“20 8-12 * * *”。
/n(斜杠后跟数字) 表示每个n个单位。例如定义“每5分钟”时可使用如下规则:“*/5 * * * *”。

AbleCloud API

访问AbleCloud云端服务的API请参考云端应用开发Java SDK API文档

Java API示例可参考《云对接开发-Java》部分。