You need to enable JavaScript to run this app.
导航
Java SDK
最近更新时间:2024.09.27 10:24:10首次发布时间:2023.03.15 11:07:10

1. 安装 SDK

1.1 下载 SDK

当前 SDK 版本:v2.0.18

datatester-java-sdk-2.0.18.jar
未知大小

1.2 添加 jar 包

  1. java 版本需求:Java 8 及更高版本。
  2. 导入方式:将 jar 文件添加至项目 Modules。

以主流 IDE(IntelliJ IDEA)为例,jar 包添加示例:
图片
图片

1.3 Maven 依赖导入

在成功添加 jar 包后,您需要通过 maven 管理添加必要依赖。
添加依赖方式:将以下代码添加至项目 pom.xml 中

注意

  1. 请务必添加所有必要依赖项。
  2. 请确保您使用的依赖版本大于或等于 Tester 官方默认版本。
  3. 请使用当前最新版本,默认修复已有安全漏洞
<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.9</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.11.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.11.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.4</version>
    </dependency>

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>27.0.1-jre</version>
    </dependency>
    
    <dependency>
        <groupId>com.github.zafarkhaja</groupId>
        <artifactId>java-semver</artifactId>
        <version>0.9.0</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.15.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.15.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.15.0</version>
    </dependency>
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.4.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.0.1</version>
    </dependency>

    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>com.googlecode.protobuf-java-format</groupId>
        <artifactId>protobuf-java-format</artifactId>
        <version>1.4</version>
    </dependency>

</dependencies>

2. 使用示例

2.1 SaaS-云原生

import com.bytedance.tester.AbClient;
import com.bytedance.tester.model.User;
import com.bytedance.tester.model.common.Variable;
import com.bytedance.tester.abInfo.UserAbInfoHandler;
import com.bytedance.tester.abInfo.MemoryHandler;
import java.util.HashMap;
    
public class Example {
    public static void main(String[] args) {
        /** 初始化ABTest分流类,appKey获取方式详见接口描述AbClient
         初始化环境信息,其中:
         1. appid,appkey为应用的标识,需要替换为真实的appkey和appid
         2. meta_host: 获取meta信息的地址,需要指定为https://tab.volces.com,私有化用户需修改为您私有化环境的域名;
         3. track_host: 事件上报地址,需要指定为https://gator.volces.com,私有化用户需修改为您私有化环境的域名;
         4. setNewEnv(true):  true: 代表SaaS-云原生环境, false: 代表SaaS-非云原生环境
        **/
        AbClient abClient = new AbClient.Builder("appkey", appid).setMetaHost("https://tab.volces.com").setTrackHost("https://gator.volces.com").setNewEnv(true).build();
        // 开启debug模式,默认打印未命中实验的用户信息
        abClient.setDebugMode(true); 
        // 声明一个用户,decisionID用于分流,trackID用于事件上报
        // decisionID: 本地分流用户标识,不用于事件上报,请替换为客户的真实用户标识
        // trackID:  事件上报用户标识,用于事件上报,请替换为客户的真实用户标识
        // add: 添加用户属性,仅用于分流,不随埋点上报
        // build: 生成User对象
        User user = new User.UserBuilder().create("decisionID", "trackID")
                .setDeviceId(6981329701821561868L) // 可选,非必要
                .add("gender", "male")
                .add("phone", null)
                .add("is_vip", false)
                .add("version", "1.2.2")
                .add("age", 18)
                .build();
        
        // 进组不出组内存实现接口,若用户不配置下列代码,则默认不开启“进组不出组”功能
        // 持久化存储进组信息,请自行实现 UserAbInfoHandler 接口(推荐)
        // MemoryHandler为内存存储,仅用于测试,请勿在生产环境使用
        UserAbInfoHandler memoryHandler = MemoryHandler.getInstance(); 
        abClient.setUserAbInfoHandler(memoryHandler);
        // 推荐接口
        String defaultValue = null; // 默认版本值,当分流未命中时返回该值,注意:返回值为包装后的对象,并非defaultValue本身,依然需要使用get方法获取
        Variable variable1 = abClient.activate("variantKey", user, defaultValue);
        if(null == variable1) {
            return;
        }
        Object value1 = variable1.getValue();
        if(null == value1) {
            return;
        }
        if(value1.equals("a")){
        }
        else if(value1.equals("b")){
        }
    }
}

2.2 SaaS-非云原生(老客)

import com.bytedance.tester.AbClient;
import com.bytedance.tester.model.User;
import com.bytedance.tester.model.common.Variable;
import com.bytedance.tester.abInfo.UserAbInfoHandler;
import com.bytedance.tester.abInfo.MemoryHandler;
import java.util.HashMap;
    
public class Example {
    public static void main(String[] args) {
        // 初始化ABTest分流类,appKey获取方式详见接口描述AbClient
        AbClient abClient = new AbClient.Builder("2b47a1f318d78fd71854815*********").build();
        // 开启debug模式,默认打印未命中实验的用户信息
        abClient.setDebugMode(true); 
        // 声明一个用户,decisionID用于分流,trackID用于事件上报
        // decisionID: 本地分流用户标识,不用于事件上报,请替换为客户的真实用户标识
        // trackID:  事件上报用户标识,用于事件上报,请替换为客户的真实用户标识
        // add: 添加用户属性,仅用于分流,不随埋点上报
        // build: 生成User对象
        User user = new User.UserBuilder().create("decisionID", "trackID")
                .setDeviceId(6981329701821561868L) // 可选,非必要
                .add("gender", "male")
                .add("phone", null)
                .add("is_vip", false)
                .add("version", "1.2.2")
                .add("age", 18)
                .build();
        
        // 进组不出组内存实现接口,若用户不配置下列代码,则默认不开启“进组不出组”功能
        // 持久化存储进组信息,请自行实现 UserAbInfoHandler 接口(推荐)
        // MemoryHandler为内存存储,仅用于测试,请勿在生产环境使用
        UserAbInfoHandler memoryHandler = MemoryHandler.getInstance(); 
        abClient.setUserAbInfoHandler(memoryHandler);
        // 推荐接口
        String defaultValue = null; // 默认版本值,当分流未命中时返回该值,注意:返回值为包装后的对象,并非defaultValue本身,依然需要使用get方法获取
        Variable variable1 = abClient.activate("variantKey", user, defaultValue);
        if(null == variable1) {
            return;
        }
        Object value1 = variable1.getValue();
        if(null == value1) {
            return;
        }
        if(value1.equals("a")){
        }
        else if(value1.equals("b")){
        }
    }
}

2.3 私有化

import com.bytedance.tester.AbClient;
import com.bytedance.tester.model.User;
import com.bytedance.tester.model.common.Variable;
import com.bytedance.tester.abInfo.UserAbInfoHandler;
import com.bytedance.tester.abInfo.MemoryHandler;
import java.util.HashMap;
    
public class Example {
    public static void main(String[] args) {
        /** 初始化ABTest分流类,appKey获取方式详见接口描述
         AbClient初始化环境信息,其中:
         1. meta_host: 获取meta信息的地址,私有化用户按需修改;
         2. track_host: 事件上报地址,私有化用户按需修改;
         3.setOnpremise(true): 是否指定上述两个域名,如果指定设为true
         **/
         AbClient abClient = new AbClient.Builder("2b47a1f318d78fd71854815*********").setMetaHost("xxx").setTrackHost("xxxx").setOnpremise(true).build();
        // 开启debug模式,默认打印未命中实验的用户信息
        abClient.setDebugMode(true); 
        // 声明一个用户,decisionID用于分流,trackID用于事件上报
        // decisionID: 本地分流用户标识,不用于事件上报,请替换为客户的真实用户标识
        // trackID:  事件上报用户标识,用于事件上报,请替换为客户的真实用户标识
        // add: 添加用户属性,仅用于分流,不随埋点上报
        // build: 生成User对象
        User user = new User.UserBuilder().create("decisionID", "trackID")
                .setDeviceId(6981329701821561868L) // 可选,非必要
                .add("gender", "male")
                .add("phone", null)
                .add("is_vip", false)
                .add("version", "1.2.2")
                .add("age", 18)
                .build();
        // 进组不出组内存实现接口,若用户不配置下列代码,则默认不开启“进组不出组”功能
        // 持久化存储进组信息,请自行实现 UserAbInfoHandler 接口(推荐)
        // MemoryHandler为内存存储,仅用于测试,请勿在生产环境使用
        UserAbInfoHandler memoryHandler = MemoryHandler.getInstance(); 
        abClient.setUserAbInfoHandler(memoryHandler);
        // 推荐接口
        String defaultValue = null; // 默认版本值,当分流未命中时返回该值,注意:返回值为包装后的对象,并非defaultValue本身,依然需要使用get方法获取
        Variable variable1 = abClient.activate("variantKey", user, defaultValue);
        if(null == variable1) {
            return;
        }
        Object value1 = variable1.getValue();
        if(null == value1) {
            return;
        }
        if(value1.equals("a")){
        }
        else if(value1.equals("b")){
        }
    }
}

3. 核心类介绍

3.1 User

描述: 用户对象,用于表明分流用户的详细属性
使用方式: 用分流接口时作为入参,使用方式如下所示

// 首先通过Builder类创建用户对象,trackId为缺省值,允许为空
User.UserBuilder userBuilder = new User.UserBuilder().create("decisionId", "trackId");
// 填充deviceid,用于绑定尚未生成uuid的用户(可选)
userBuilder.setDeviceId(6981329701821561868L);
// 向Builder中填充用户属性
userBuilder.add("age", 18);
userBuilder.add("name", "小明");
userBuilder.add("is_vip", true);
// 生成User对象
User user = userBuilder.build();

3.2 Variable

描述: 变体对象,用于表明分流结果的详细属性
使用方式: 分流接口的返回对象基本类,使用方式如下所示

String vid = variable.vid; // 变体的ID
String type = variable.type; // 变体值的数据类型,与Tester平台配置保持一致
// 通用方法,获取Object对象,具体数据类型需要用户自行判断
Object o = variable.getValue();
// 精确数据类型
String vStr = variable.getString(); // 非字符串类型默认返回null
int vInt = variable.getInteger(); // 非int类型默认返回0
double vDouble = variable.getDouble(); // 非double类型默认返回0.0
boolean vBoolean = variable.getBoolean(); // 非boolean类型默认返回false

3.3 UserAbInfoHandler

描述:进组不出组接口
接口内容:

public interface UserAbInfoHandler {
    /**
          * 获取进组信息
          *  @param decisionId 用户分流ID
          *  @return key:实验ID  value:进组的变体ID
          */
    HashMap<String, String> query(String decisionId);

    /**
          * 更新进组信息
          *  @param decisionId 用户分流ID
          *  @param abInfo 用户进组信息,<experimentID, versionID>
          *  @return 是否成功更新
          */
    boolean createOrUpdate(String decisionId, HashMap<String, String> abInfo);
}

使用方式:

  1. 初始化AbClient 时 不指定UserAbInfoHandler,则默认使用空实现,不启用“进组不出组”功能。
  2. 初始化AbClient时 执行setUserAbInfoHandler,使用默认提供的内存实现MemoryHandler(使用方式见代码示例)。
  3. 继承UserAbInfoHandler接口,自行实现持久化存储;初始化A bClient时 通过setUserAbInfoHandler传 入。

3.4 性能参数(私有化专用)

AbClient.eventDispatcher.properties

AbClient abClient = new AbClient.Builder("appKey").setMetaHost("MetaHost").setTrackHost("TrackHost").setOnpremise(true).build();
abClient.setThreadCount(4);
abClient.setQueueSize(102400);

4. 接口说明

4.1 AbClient

接口:
new AbClient.Builder(String appKey).setMetaHost(String metaHost).setTrackHost(String trackHost).setOnpremise(boolean isOnpremise).build();
描述:初始化ABTest分流类。
参数:

  • appKey:表明您的Tester应用。出于安全考虑,此处请使用appKey而非appID表明您的应用。
    在集团中接入一个应用后,您可以在集团相关页面查看应用的AppKey等信息,详情请参考:如何创建应用

    • SaaS-云原生
      图片
    • SaaS-非云原生
      图片
  • metaHost :填写获取实验元信息的地址,默认为SaaS-非云原生国内线上地址,其他环境参考上文2 .1~2.3。海外Saas域 名:MetaHost.SG

  • trackHost :填写事件上报的地址,默认为SaaS-非云原生国内线上地址,其他环境参考上文2 .1~2.3。海外Saas域 名:TrackHost.SG

  • isOnpremise(default=false):表明您的应用是否需要额外配置metaHost和 trackHost

说明

1、请尽早初始化 AbClient,以免影响您的分流服务和埋点上报服务。
2、每个应用有且仅有一个分流类 AbClient,请确保它在所有线程中的唯一性。


Meta 元信息服务默认使用火山引擎 A/B 平台国内线上地址,请谨慎修改。saas 合法地址请参考代码中 MetaHost 枚举类。私有化客户需修改为部署时 AB 服务的挂载域名。


埋点上报服务默认使用火山引擎 A/B 平台国内线上地址,请谨慎修改。saas 合法地址请参考代码中 TrackHost 枚举类。私有化客户需修改为部署时 AppLog 服务的挂载域名。

4.2 activate

接口: Variable activate(String variantKey, User user, Object defaultValue)
描述: 获取特定key的分流结果,并上报曝光事件
参数:
variantKey:变体的key
user:用户对象
defaultValue:变体默认值
返回值: 该数返回命中变体对象,未命中时返回默认值对象

public class Variable {
    String vid; // 变体id
    Object val; // 变体值
    String type; // 变体值的数据类型
}

说明

  1. 该接口与所有含有“WithImpression”字样的接口均会自动上报曝光事件,用户可在 AbClient 初始化时指定 trackHost,调整事件上报地址。
  2. 事件上报接口请务必填写User中trackID字段,否则上报失效。

4.3 getABInfo

接口: HashMap<String, Variable> getABInfo(User user)
描述: 获取实验和feature的分流结果
参数:
user:用户对象
返回值: 该数返回命中变体的Map对象 ,具体格式如下所示

{
  "key1": {
    "vid": "123",
    "value": "v1",
    "type": "string"
  },
  "key2": {
    "vid": "456",
    "value": false,
    "type": "boolean" 
  },
  "key3": {
    "vid": "789",
    "value": 123.45,
    "type": "double" 
  }   
}

4.4 getExperimentVariantName

接口: String getExperimentVariantName(String experimentId, User user)
描述: 获取用户命中的实验版本名称
参数:
experimentId:指定分流的实验ID
user:用户对象
返回值: 该数返回用户命中的实验版本名称

4.5 getExperimentConfigs

接口: HashMap<String, Variable> getExperimentConfigs(String experimentId, User user)
描述: 获取用户命中的特定实验的变体详情
参数:
experimentId:指定分流的实验ID
user:用户对象
返回值:
该数返回命中变体的Ma p对象 ,表明用户命中某个实验的变体详情,通常仅能命中一个变体。

4.6 getAllExperimentConfigs

接口: HashMap<String, Variable> getAllExperimentConfigs(User user)
描述: 获取用户命中的所有实验的变体详情
参数:
user:用户对象
返回值:
该数返回命中变体的Ma p对象 ,表明用户命中所有实验的变体详情,通常命中多个变体。

4.7 getFeatureConfigs

接口: HashMap<String, Variable> getFeatureConfigs(String featureId, User user)
描述: 获取用户命中的特定feature的变体详情
参数:
featureId:feature ID
user:用户对象
返回值:
返回命中变体的Map对象 ,表明用户命中某个f ature的变体详情,通常仅能命中一个变体。

4.8 getAllFeatureConfigs

接口: HashMap<String, Variable> getAllFeatureConfigs(User user)
描述: 获用户命中的所有feature的变体详情
参数:
user:用户对象
返回值: 返回命中变体的Map对象 ,表明用户命中所有feature的变体详情,通常命中多个变体。

4.9 getExperimentVariantNameWithImpression

功能同接口“getExperimentVariantName”(此接口上报曝光事件)

4.10 getExperimentConfigsWithImpression

功能同接口“getExperimentConfigs”(此接口上报曝光事件)

4.11 getFeatureConfigsWithImpression

功能同接口“getFeatureConfigs”(此接口上报曝光事件)

4.12 setInterval

接口: void setInterval(int n)
描述: 设置meta元信息更新的时间间隔
参数:
n:元信息自动更新时间间隔(单位:秒)

4.13 setThreadCount

接口: void setThreadCount(int n)
描述: 设置埋点上报服务的最大线程数
参数:
n:最大线程数(默认为4)

4.14 getSuccessEvents

接口: int getSuccessEvents()
描述: 获上报成功的事件数,用于监测事件上报回调结果
返回值: 上成功的事件数
注意: 私化版本不支持回调函数

4.15 getFailEvents

接口: int getFailEvents()
描述: 获上报失败的事件数,用于监测事件上报回调结果
返回值: 上报失败的事件数

4.16 getQueueEvents

接口: int getQueueEvents()
描述: 获线程池中剩余事件数,用于监测尚未上报的事件数量
返回值: 尚未上报的事件数

4.17 Logger

ABTest服务端SDK使用文件记录log日志 。如果您希望修改日志配置,请编辑文件log4j2.xml,默认的log地址 为./logs

5. 常见问题处理

如何使用Redis实现 进组不出组逻辑?

请参考集成示例,redis实现

/**
  * 实现 UserAbInfoHandler接口,并实现接口中声明的方法
  * 进组不出组,Redis实现。
  */
public class NotOutGroupRedisImplement implements UserAbInfoHandler {
    /**
          * 存储分流结果
          *  @param userId   用户ID
          *  @param hashMap  分流结果参数和值,key=分流参数,value=对应版本的标识
          *  @return
     */
    @Override
    public boolean createOrUpdate(String userId, HashMap<String, String> hashMap) {
        long res = 0 ;
        for (Map.Entry<String, String> entry : hashMap.entrySet()) {
             res = JedisUtils.getJedis().hset(userId, entry.getKey(), entry.getValue());
        }
        return res > 0 ;
    }
    /**
          * 查询用户对应的分组
          *  @param userId
          *  @return 用户对应的分流结果  key=分流参数,value=对应版本的标识
          */
    @Override
    public HashMap<String, String> query(String userId) {
        Map<String, String> resMap = JedisUtils.getJedis().hgetAll(userId);
        return (HashMap<String, String>) resMap;
    }
}

在AB分流代码中配置进组不出组的逻辑

AbClient abClient = new AbClient.Builder(appKey).build();
NotOutGroupRedisImplement notOutGroupHandler = new NotOutGroupRedisImplement();
abClient.setUserAbInfoHandler(notOutGroupHandler);
Variable variable1 = abClient.activate("variantKey", user, defaultValue);

如果获取不到uuid,或者想做匿名用户的服务端实验,如何设置?

用户类中decisionid需要使用用户唯一标识,比如客户端设备id ,ssid,trackid 如果名就设置对应的实名用户id ,如果是匿名,就为空字符串,并且需要通过setDeviceId或者 setWebId方法,设置设备id 。
注意:saas需要使用setBdDid方法

User user = new User.UserBuilder().create("decisionID", "") // trackId有值设置对应的值,没有值设置空字符串
        .setDeviceId(6981329701821561868L) //私有部署使用此方法
        .setWebId(7018215618686981329L) //Web及小程序使用此方法
        .setBdDid("H5PPHTEHXLMEGCGROGLY2343242M2LMFIMQE4VIRW76HKYWH4Q01") //saas使用此方法
        .build();