当前 SDK 版本:v2.0.18
以主流 IDE(IntelliJ IDEA)为例,jar 包添加示例:
在成功添加 jar 包后,您需要通过 maven 管理添加必要依赖。
添加依赖方式:将以下代码添加至项目 pom.xml 中
注意
<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>
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")){ } } }
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")){ } } }
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")){ } } }
描述: 用户对象,用于表明分流用户的详细属性
使用方式: 用分流接口时作为入参,使用方式如下所示
// 首先通过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();
描述: 变体对象,用于表明分流结果的详细属性
使用方式: 分流接口的返回对象基本类,使用方式如下所示
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
描述:进组不出组接口
接口内容:
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); }
使用方式:
AbClient.eventDispatcher.properties
AbClient abClient = new AbClient.Builder("appKey").setMetaHost("MetaHost").setTrackHost("TrackHost").setOnpremise(true).build(); abClient.setThreadCount(4); abClient.setQueueSize(102400);
接口:
new AbClient.Builder(String appKey).setMetaHost(String metaHost).setTrackHost(String trackHost).setOnpremise(boolean isOnpremise).build();
描述:初始化ABTest分流类。
参数:
appKey:表明您的Tester应用。出于安全考虑,此处请使用appKey而非appID表明您的应用。
在集团中接入一个应用后,您可以在集团相关页面查看应用的AppKey等信息,详情请参考:如何创建应用。
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 服务的挂载域名。
接口: Variable activate(String variantKey, User user, Object defaultValue)
描述: 获取特定key的分流结果,并上报曝光事件
参数:
variantKey:变体的key
user:用户对象
defaultValue:变体默认值
返回值: 该数返回命中变体对象,未命中时返回默认值对象
public class Variable { String vid; // 变体id Object val; // 变体值 String type; // 变体值的数据类型 }
说明
接口: 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" } }
接口: String getExperimentVariantName(String experimentId, User user)
描述: 获取用户命中的实验版本名称
参数:
experimentId:指定分流的实验ID
user:用户对象
返回值: 该数返回用户命中的实验版本名称
接口: HashMap<String, Variable> getExperimentConfigs(String experimentId, User user)
描述: 获取用户命中的特定实验的变体详情
参数:
experimentId:指定分流的实验ID
user:用户对象
返回值:
该数返回命中变体的Ma p对象 ,表明用户命中某个实验的变体详情,通常仅能命中一个变体。
接口: HashMap<String, Variable> getAllExperimentConfigs(User user)
描述: 获取用户命中的所有实验的变体详情
参数:
user:用户对象
返回值:
该数返回命中变体的Ma p对象 ,表明用户命中所有实验的变体详情,通常命中多个变体。
接口: HashMap<String, Variable> getFeatureConfigs(String featureId, User user)
描述: 获取用户命中的特定feature的变体详情
参数:
featureId:feature ID
user:用户对象
返回值:
返回命中变体的Map对象 ,表明用户命中某个f ature的变体详情,通常仅能命中一个变体。
接口: HashMap<String, Variable> getAllFeatureConfigs(User user)
描述: 获用户命中的所有feature的变体详情
参数:
user:用户对象
返回值: 返回命中变体的Map对象 ,表明用户命中所有feature的变体详情,通常命中多个变体。
功能同接口“getExperimentVariantName”(此接口上报曝光事件)
功能同接口“getExperimentConfigs”(此接口上报曝光事件)
功能同接口“getFeatureConfigs”(此接口上报曝光事件)
接口: void setInterval(int n)
描述: 设置meta元信息更新的时间间隔
参数:
n:元信息自动更新时间间隔(单位:秒)
接口: void setThreadCount(int n)
描述: 设置埋点上报服务的最大线程数
参数:
n:最大线程数(默认为4)
接口: int getSuccessEvents()
描述: 获上报成功的事件数,用于监测事件上报回调结果
返回值: 上成功的事件数
注意: 私化版本不支持回调函数
接口: int getFailEvents()
描述: 获上报失败的事件数,用于监测事件上报回调结果
返回值: 上报失败的事件数
接口: int getQueueEvents()
描述: 获线程池中剩余事件数,用于监测尚未上报的事件数量
返回值: 尚未上报的事件数
ABTest服务端SDK使用文件记录log日志 。如果您希望修改日志配置,请编辑文件log4j2.xml,默认的log地址 为./logs
请参考集成示例,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);
用户类中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();