准备工作

下载并安装Maven插件 https://maven.apache.org/install.html 下载并安装JDK1.8

安装开发IDE(例如IDEA、VSCode、Eclipse等)

申请开发者证书(目前先联系吴俊文申请)

  • 申请证书时需要给企业ID、员工ID,该证书会与租户以及员工进行绑定
  • 每次申请的证书有效期为30天
  • 证书绑定的员工如果停用、禁止登录或者修改密码,该证书都会立即失效

下载脚手架 https://a9.fspage.com/FSR/base/apl/template.zip

  • 解压脚手架,建议解压到企业帐号/企业信息目录下,例如D:\workspace\facishare, 得到以下目录结构
|-- lib
  apl-sdk-maven-plugin.jar maven插件
  fs-paas-function-api.jar 代码依赖的api包
|-- src
  |-- main
    |-- java
      |-- fx
        |-- custom
        |-- apl
            |-- jar
            代码示例
  |-- resources
      application.properties 租户开发证书
pom.xml 
README.md 本说明文件
  • 打开IDE导入项目

图片alt

环境准备工作

修改pom.xml中的 artifactId为Jar包ApiName

apiName 命名规则:

1.只允许英文字母开头

2.中间允许使用英文字母,数字,下划线

3.必须以__c结尾

4.除结尾的 __c 外下划线不允许连续出现

5.不能超过50个字符

图片alt

设置开发者证书

  • 将准备工作中的开发者证书,设置到application.properties中

图片alt

安装apl插件

  • IDE进入控制台
  • 在控制台输入以下命令

mvn install:install-file "-Dpackaging=maven-plugin" "-Dfile=lib/apl-sdk-maven-plugin.jar" "-DgroupId=com.facishare" "-DartifactId=apl-sdk-maven-plugin" "-Dversion=1.0-SNAPSHOT"

安装sdk

  • 在控制台输入以下命令

mvn install:install-file "-Dpackaging=jar" "-Dfile=lib/fs-paas-function-api.jar" "-DgroupId=com.facishare" "-DartifactId=fs-paas-function-api" "-Dversion=1.0-DEBUG-SNAPSHOT" "-Dsources=lib/fs-paas-function-api-sources.jar"

  • 命令执行成功,会看到下图

图片alt

开始开发

新建代码

在fx.custom.apl.jar下新建代码

图片alt

实现函数的命名空间对应的接口,所有已支持的接口在 com.fxiaoke.functions.template, 如下图

图片alt

一个新的APL代码新建就好了,如下图所示

图片alt

增加main函数,以方便进行代码调试

DebugHelper helper = new DebugHelper(); //构造一个调试器
helper.init(); //对调试器进行初始化
FunctionContext context = helper.context("AccountObj", "63100e7915d6a300017121cc"); //获取一个调试上下文,以方便写代码
Map argument = Maps.newHashMap(); //如果函数需要有其他参数,可以构造一个Map,进行参数传递
最后效果如下图

图片alt

开始开发

  • 在代码中,可以使用Fx进行对象的查询、修改、以及新增,例如 QueryResult ret = Fx.object.select(String.format("SELECT _id, name FROM AccountObj WHERE name = '%s'", search)).result();
  • 在代码需要按照接口的约定,进行参数返回,如下图所示

图片alt

调试

  • 点击main函数最左边绿色的箭头,可以对进行项目的编译以及调试
  • 可以通过IDE,对代码进行断点分析,如下图所示

图片alt

将代码发布到租户

发布

当代码开发完成,则需要对代码进行打包并上线
  • 打开IDE的Maven插件
  • 找到jar插件中的,jar:Jar进行打包,如图所示

图片alt

  • 找到apl-sdk插件,点击apl-sdk:pushJar,进行Jar包上传,如图所示

图片alt

启用Jar包

  • Jar包首次上传后,是未安装状态,需要登录管理后台,安装该Jar包
  • 登录管理后台,搜索《开发Jar包管理》
  • 根据artifactId,找到刚才开发Jar的ApiName
  • 点击安装,安装刚才上传的Jar

图片alt

关联场景

  • 找到需要执行代码的地方,新建函数

图片alt

  • 选择Jar包函数
  • ApiName输入 类名 + __c结尾,以便定位到具体类名
  • 新建函数的命名空间、返回值与类对应的接口必须一致,否则会执行失败

图片alt

  • 新建完成后,就可以进行验证

注意事项

  • 首次安装成功后,第二次推送Jar包,会直接更新Jar包内容,同时也会直接影响租户使用
  • 实施/用户按照标准代码管理规范,进行代码分支管理
  • Jar限制大小为10兆,切勿将第三方Jar包一并打包上传,如需上传第三方Jar包,请到管理后台进行上传
  • APL自带FastJson以及Guava等通用工具包,如果上传了通用工具包,会以APL优先
  • 用户证书30天有效,如果用户停用、禁止登录、修改密码会失效,需要重新申请

代码Demo

按钮前验证代码示例


package fx.custom.apl.jar;

import com.fxiaoke.functions.FunctionContext;
import com.fxiaoke.functions.Fx;
import com.fxiaoke.functions.client.DebugHelper;
import com.fxiaoke.functions.model.ButtonValidateResult;
import com.fxiaoke.functions.model.QueryResult;
import com.fxiaoke.functions.template.IButtonBeforeAction;
import com.fxiaoke.functions.utils.Maps;
import com.google.common.collect.ImmutableMap;
import com.mycompany.pkg.MyTest;

import java.io.IOException;
import java.util.Map;

import static com.fxiaoke.functions.Fx.log;

/**
 * 1. 根据命名空间以及返回,选择对应的Action
 * 2. 这个Action是函数触发入口,对象勾子触发时,会到Jar包中查找这个类并且检查接口以及接口提供的方法
 * <p>
 * <p>
 * 全部已支持的action详见以下package
 *
 * @author APL
 * @see com.fxiaoke.functions.template
 */
public class ButtonBlockAction implements IButtonBeforeAction {

    MyTest test = new MyTest();

    @Override
    public ButtonValidateResult validate(FunctionContext context, Map<String, Object> map) {
        //从模拟的上下文获取到调试的name字段
        String name = (String) context.getData().get("name");

        //可以自定义包名以及类名,执行逻辑
        String testName = test.DemoFunc(name);

        //使用APL平台提供的 log.info 进行日志输出
        //切勿使用 System.out.println(); 或者其他日志组件进行打印日志
        log.info(testName);

        //假设我们需要从代码里查询名字为test的客户
        String search = "test";

        QueryResult ret = Fx.object.select(String.format("SELECT _id, name FROM AccountObj WHERE name = '%s'", search)).result();

        Map<String, Object> obj = (Map<String, Object>) ret
                .getDataList()
                .stream()
                .findFirst()
                .orElseGet(() -> ImmutableMap.of("name", "测试"));

        return new ButtonValidateResult(
                true,
                "客户名字是:" + obj.get("name"),
                true);
    }

    /**
     * 调试入口
     */
    public static void main(String[] args) throws IOException {
        //调试器
        DebugHelper helper = new DebugHelper();
        //调试器初始化,包括身份以及服务器的地址
        //身份信息联系APL平台获取,具体查看application.properties配置
        helper.init();

        //构造当前执行类
        ButtonBlockAction example = new ButtonBlockAction();
        //模拟调试的上下文,例如开发时想模拟一个客户对象的上下文,以方便开发
        FunctionContext context = helper.context("AccountObj", "63100e7915d6a300017121cc");

        //构造被触发时的参数
        Map<String, Object> argument = Maps.newHashMap();

        //执行函数
        example.validate(context, argument);
    }
}

按钮前验证代码示例


package fx.custom.apl.jar;

import com.fxiaoke.functions.FunctionContext;
import com.fxiaoke.functions.Fx;
import com.fxiaoke.functions.client.DebugHelper;
import com.fxiaoke.functions.model.APIResult;
import com.fxiaoke.functions.template.IFlowAction;
import com.fxiaoke.functions.tools.ActionAttribute;
import com.fxiaoke.functions.utils.Maps;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.fxiaoke.functions.Fx.log;

public class FlowActionExample implements IFlowAction {

    public static void main(String[] args) throws IOException {
        //调试器
        DebugHelper helper = new DebugHelper();
        //调试器初始化,包括身份以及服务器的地址
        //身份信息联系APL平台获取,具体查看application.properties配置
        helper.init();

        //构造当前执行类
        FlowActionExample example = new FlowActionExample();
        //模拟调试的上下文,例如开发时想模拟一个客户对象的上下文,以方便开发
        FunctionContext context = helper.context("AccountObj", "63100e7915d6a300017121cc");

        //构造被触发时的参数
        Map<String, Object> argument = Maps.newHashMap();

        //执行函数
        example.execute(context, argument);
    }

    @Override
    public void execute(FunctionContext functionContext, Map<String, Object> map) {
        ActionAttribute attribute = ActionAttribute.create();

        //使用APL平台提供的 log.info 进行日志输出
        //切勿使用 System.out.println(); 或者其他日志组件进行打印日志
        log.info(functionContext);


        HashMap<Object, Object> account = new HashMap<>();
        account.put("name", System.currentTimeMillis());

        APIResult result = Fx.object.create("AccountObj", account, Maps.newHashMap(), attribute);
        log.info(result);
    }
}

范围规则代码示例


package fx.custom.apl.jar;

import com.fxiaoke.functions.FunctionContext;
import com.fxiaoke.functions.client.DebugHelper;
import com.fxiaoke.functions.model.QueryTemplate;
import com.fxiaoke.functions.template.IRangeRuleTemplateAction;
import com.fxiaoke.functions.tools.QueryOperator;
import com.fxiaoke.functions.utils.Lists;
import com.fxiaoke.functions.utils.Maps;

import java.io.IOException;
import java.util.Map;

import static com.fxiaoke.functions.Fx.log;

/**
 * 返回规则的Demo,注意返回值选择的是QueryTemplate
 */
public class RangeRuleExample implements IRangeRuleTemplateAction {
    public static void main(String[] args) throws IOException {
        //调试器
        DebugHelper helper = new DebugHelper();
        //调试器初始化,包括身份以及服务器的地址
        //身份信息联系APL平台获取,具体查看application.properties配置
        helper.init();

        //构造当前执行类
        RangeRuleExample example = new RangeRuleExample();
        //模拟调试的上下文,例如开发时想模拟一个客户对象的上下文,以方便开发
        FunctionContext context = helper.context("AccountObj", "63100e7915d6a300017121cc");

        //构造被触发时的参数
        Map<String, Object> argument = Maps.newHashMap();

        //执行函数
        example.execute(context, argument);
    }

    @Override
    public QueryTemplate execute(FunctionContext context, Map<String, Object> args) {

        //使用APL平台提供的 log.info 进行日志输出
        //切勿使用 System.out.println(); 或者其他日志组件进行打印日志
        log.info(context);

        return QueryTemplate.AND(
                Maps.of("life_status", QueryOperator.NE(Lists.newArrayList("invalid"))
                ));
    }
}

results matching ""

    No results matching ""