Java SDK

在使用前,请先阅读数据模型的介绍。

Java SDK 主要用于服务端 Java 应用,对于 Android App,请使用 神策分析 Android SDK

1. 集成神策分析 SDK

在服务端 Java 应用中集成 神策分析 SDK,使用神策分析采集并分析用户行为。

我们推荐使用 Maven 管理 Java 项目,请在 pom.xml 文件中,添加以下依赖信息,Maven 将自动获取神策分析 SDK 并更新项目配置。

    <dependencies>
      // ...
      <dependency>
        <groupId>com.sensorsdata.analytics.javasdk</groupId>
        <artifactId>SensorsAnalyticsSDK</artifactId>
        <version>3.1.11</version>
      </dependency>
    </dependencies>

若出现依赖冲突的问题(例如运行时找不到类),可以使用 standalone 版本:将上面的 version 替换为 3.1.11-standalone

如果不使用 Maven,也可以用下面任意一种方式集成:

最新版本的神策 Java SDK 支持的 JDK 最低版本为 Java 7;神策 Java SDK 3.1.9 版支持 JDK 1.6。

2. 初始化神策分析 SDK

2.1 获取配置信息

首先从神策分析的主页中,获取数据接收的 URL 和 Token(Cloud 版)。

如果使用神策分析 Cloud 服务,需获取的配置信息为:

如果用户使用单机版私有部署的神策分析,默认的配置信息为:

如果用户使用集群版私有部署的神策分析,默认的配置信息为:

其中 {$host_name} 可以是集群中任意一台机器。

如果私有部署的过程中修改了 Nginx 的默认配置,或通过 CDN 等访问神策分析,则请咨询相关人员获得配置信息。

2.2 在程序中初始化 SDK

在程序启动时(如 public static void main(String[] args) 方法中),调用构造函数 new SensorsAnalytics(Consumer) 初始化 Java SDK 实例。

    // 从神策分析获取的数据接收的 URL
    final String SA_SERVER_URL = "YOUR_SERVER_URL";
    // 使用 Debug 模式,并且导入 Debug 模式下所发送的数据
    final boolean SA_WRITE_DATA = true;

    // 使用 DebugConsumer 初始化 SensorsAnalytics
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.DebugConsumer(SA_SERVER_URL, SA_WRITE_DATA));

    // 用户的 Distinct Id
    String distinctId = "ABCDEF123456789";

    // 记录用户登录事件
    sa.track(distinctId, true, "UserLogin");

    // 使用神策分析记录用户行为数据
    // ...

    // 程序结束前,停止神策分析 SDK 所有服务
    sa.shutdown();

其中 YOUR_SERVER_URL 是前文中从神策分析获取的数据接收的 URL。DebugConsumer 为发送选项, DebugConsumer 仅允许在程序调试时使用,在生产环境中我们建议使用 ConcurrentLoggingConsumer ,并结合 LogAgent 工具完成数据采集,具体信息请参考文档中 设置神策分析 SDK 一节 。

程序结束前需要使用 shutdown() 接口显式结束,该接口可能需要等待若干秒,直到本地缓存的数据都已发送到神策分析。

至此,我们已经可以正常使用神策分析 SDK 采集用户数据了。在开发多线程程序时,开发者可以在线程间复用神策分析实例用于记录数据。

3. 追踪事件

第一次接入神策分析时,建议先追踪 3~5 个关键的事件,只需要几行代码,便能体验神策分析的分析功能。例如:

  • 图片社交产品,可以追踪用户浏览图片和评论事件

  • 电商产品,可以追踪用户注册、浏览商品和下订单等事件

神策分析 SDK 初始化成功后,可以通过 track() 记录事件,必须包含用户 ID(distinctId)、用户 ID 是否为登录 ID (isLoginId)、事件名(eventName)这三个参数,同时可以传入一个 Map<String, Object> 对象,为事件添加自定义事件属性。以电商产品为例,可以这样追踪一次购物行为:

    // 从神策分析获取的数据接收的 URL
    final String SA_SERVER_URL = "YOUR_SERVER_URL";
    // 使用 Debug 模式,并且导入 Debug 模式下所发送的数据
    final boolean SA_WRITE_DATA = true;

    // 使用 DebugConsumer 初始化 SensorsAnalytics
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.DebugConsumer(SA_SERVER_URL, SA_WRITE_DATA));

    // 用户的 Distinct Id
    String distinctId = "ABCDEF123456789";

    // 用户浏览商品
    {
      Map<String, Object> properties = new HashMap<String, Object>();

      // '$time' 属性是系统预置属性,表示事件发生的时间,如果不填入该属性,则默认使用系统当前时间
      properties.put("$time", new Date());
      // '$ip' 属性是系统预置属性,如果服务端中能获取用户 IP 地址,并填入该属性,神策分析会自动根据 IP 地址解析用户的省份、城市信息
      properties.put("$ip", "123.123.123.123");
      // 商品 ID
      properties.put("ProductId", "123456");
      // 商品类别
      properties.put("ProductCatalog", "Laptop Computer");
      // 是否加入收藏夹,Boolean 类型的属性
      properties.put("isAddedToFav", true);

      // 记录用户浏览商品事件
      sa.track(distinctId, true, "ViewProduct", properties);
    }

    // 用户订单付款
    {
      // 订单中的商品 ID 列表
      List<String> productIdList = new ArrayList<String>();
      productIdList.add("123456");
      productIdList.add("234567");
      productIdList.add("345678");

      Map<String, Object> properties = new HashMap<String, Object>();

      properties.put("$ip", "123.123.123.123");
      // 订单 ID
      properties.put("OrderId", "abcdefg");
      // 商品 ID 列表,List<String> 类型的属性
      properties.put("ProductIdList", productIdList);
      // 订单金额
      properties.put("OrderPaid", 12.10);

      // 记录用户订单付款事件
      sa.track(distinctId, true, "PaidOrder", properties);
    }

通过 Debug模式,可以校验追踪的事件及属性是否正确。普通模式下,数据导入后,在神策分析中稍等片刻,便能看到追踪结果。请注意,不要在生产环境中使用 Debug 模式

3.1 事件属性

如前文中的样例,追踪的事件可以设置自定义的事件属性,例如浏览商品事件中,将商品 ID、商品分类等信息作为事件属性。在后续的分析工作中,事件属性可以作为统计过滤条件使用,也可以作为维度进行多维分析。对于事件属性,神策分析有一些约束:

  • 事件属性是一个 Map<String, Object> 对象

  • Map<String, Object> 中每个元素描述一个属性,Key 为属性名称,必需是 String 类型

  • Map<String, Object> 中,每个元素的 Value 是属性的值,支持 StringNumberList<String>Date

对于神策分析中事件属性的更多约束,请参考 数据格式。在开发多线程程序时,开发者不能在线程间复用传入的属性对象。

3.1.1 系统预置属性

如前文中样例,事件属性中以 '$' 开头的属性为系统预置属性,在自定义事件属性中填入对应 '$' 开头的属性值可以覆盖这些预置属性:

  • $ip - 填入该属性,神策分析会自动根据 IP 地址解析用户的省份、城市信息,该属性值为 String 类型;

  • $time - 填入该属性,神策分析将事件时间设置为属性值的时间,该属性值必须为 Date 类型。请注意,神策分析默认会过滤忽略 2 年前或 1 小时后的数据,如需修改请联系我们;

  • $project - 填入该属性,神策分析某些导入工具例如 LogAgent (LogAgent 的配置中未指定 project 参数时)会将数据导入指定项目;

关于其他更多预置属性,请参考 数据格式 中 '预置属性' 一节。

3.1.2 事件公共属性

特别地,如果某个事件的属性,在所有事件中都会出现,可以通过 registerSuperProperties() 将该属性设置为事件公共属性。例如将服务器的应用版本及机房地址设置为事件的公共属性,设置方法如下:

    Map<String, Object> properties = new HashMap<String, Object>();
    // 服务器应用版本
    properties.put("ServerVersion", "1.2");
    // 服务器机房地址
    properties.put("Location", "BeiJing");
    // 设置事件公共属性
    sa.registerSuperProperties(properties);

成功设置事件公共属性后,再通过 track() 追踪事件时,事件公共属性会被添加进每个事件中,例如:

    Map<String, Object> properties = new HashMap<String, Object>();
    // 登录客户端 IP 地址
    properties.put("$ip", "123.123.123.123");
    // 追踪用户登录事件
    sa.track("ABCDEF123456789", true, "UserLogin", properties);

在设置事件公共属性后,实际发送的事件中会被加入 ServerVersionLocation 属性,等价于

    Map<String, Object> properties = new HashMap<String, Object>();
    // 事件公共属性
    properties.put("ServerVersion", "1.2");
    properties.put("Location", "BeiJing");
    // 登录客户端 IP 地址
    properties.put("$ip", "123.123.123.123");
    // 追踪用户登录事件
    sa.track("ABCDEF123456789", true, "UserLogin", properties);

使用 clearSuperProperties() 会删除所有已设置的事件公共属性。

当事件公共属性和事件属性的 Key 冲突时,事件属性优先级最高,它会覆盖事件公共属性。

4. 用户识别

在服务端应用中,神策分析也要求为每个事件设置用户的 Distinct Id,这有助于神策分析提供更准确的留存率等数据。

对于注册用户,推荐使用系统中的用户 ID 作为 Distinct Id,不建议使用用户名、Email、手机号码等可以被修改的信息;

对于未注册的匿名用户:

  1. 后端获取前端 JavaScript SDK 生成的匿名 id 的方式: 可以在 Cookie 里面找到 key 为 sensorsdata2015jssdkcross 的 value 值然后进行 decodeURIComponent 解码,最后通过 JSON.parse 方法得到一个对象,对象里面的 distinctid 的值即为所需要的 ID (_注意,如果前端已经调用过 login 方法,那么此时 distinct_id 为登录 ID,所以需要先获取 first_id 字段的值,如果获取不到,就去获取 distinct_id 的值)。

  2. 如果 App 中嵌入了 iOS SDKAndroid SDK,需要客户端将匿名 ID 传给服务器端,然后获取到传过来的匿名 ID 。

所有的 track 和 profile 系列方法都必须同时指定用户 ID用户 ID 是否为登录 ID 这两个参数,以便明确告知神策分析用户 ID 的类型。

4.1 用户注册/登录

通过 trackSignUp() 将匿名 ID 和 登录 ID 关联,以保证用户分析的准确性。例如:

    //  前端的匿名 ID
    String anonymousId = "9771C579-71F0-4650-8EE8-8999FA717761";

    String registerId = "0012345678";
    // 用户注册/登录时,将用户登录 ID 与 匿名 ID 关联
    sa.trackSignUp(registerId, anonymousId);

注意,trackSignUp() 建议在用户 注册/登录 时调用。在神策分析 1.13 版本之前,多次调用 trackSignUp() 时,只有第一次关联行为是有效的。神策分析 1.13 版本之后提供了多设备 ID 关联的方法。更详细的说明请参考 如何准确的标识用户,并在必要时联系我们的技术支持人员。

5. 设置用户属性

为了更准确地提供针对人群的分析服务,神策分析 SDK 可以设置用户属性,如年龄、性别等。用户可以在留存分析、分布分析等功能中,使用用户属性作为过滤条件或以用户属性作为维度进行多维分析。

使用 profileSet() 设置用户属性:

    String distinctId = "ABCDEF123456789";

    // 设置用户性别属性(Sex)为男性
    sa.profileSet(distinctId, true, "Sex", "Male");

    Map<String, Object> properties = new HashMap<String, Object>();
    // 设置用户等级属性(Level)为 VIP
    properties.put("UserLv", "Elite VIP");

    sa.profileSet(distinctId, true, properties);

对于不再需要的用户属性,可以通过 profileUnset() 接口将属性删除。

用户属性中,属性名称与属性值的约束条件与事件属性相同,详细说明请参考 数据格式

5.1 记录初次设定的属性

对于只在首次设置时有效的属性,我们可以使用 profileSetOnce() 记录这些属性。与 profileSet() 接口不同的是,如果被设置的用户属性已存在,则这条记录会被忽略而不会覆盖已有数据>,如果属性不存在则会自动创建。因此,profileSetOnce() 比较适用于为用户设置首次激活时间、首次注册时间等属性。例如:

    String distinctId = "ABCDEF123456789";

    // 设置用户渠道属性(AdSource)为 "App Store"
    sa.profileSetOnce(distinctId, true, "AdSource", "App Store");

    // 再次设置用户渠道属性(AdSource),设定无效,属性 "AdSource" 的值仍为 "App Store"
    sa.profileSetOnce(distinctId, true, "AdSource", "Search Engine");

5.2 数值类型的属性

对于数值型的用户属性,可以使用 profileIncrement() 对属性值进行累加。常用于记录用户付费次数、付费额度、积分等属性。例如:

    String distinctId = "ABCDEF123456789";

    // 设置用户游戏次数属性(GamePlayed),将次数累加1次
    sa.profileIncrement(distinctId, true, "GamePlayed", 1);

5.3 列表类型的属性

对于用户喜爱的电影、用户点评过的餐厅等属性,可以记录列表型属性。需要注意的是,列表型属性中的元素必须为 String 类型,且元素的值会自动去重。关于列表类型限制请见 数据格式 7.4 属性长度限制

    String distinctId = "ABCDEF123456789";

    // 电影列表
    List<String> movies = new ArrayList<String>();
    movies.add("Sicario");
    movies.add("Love Letter");

    // 游戏列表
    List<String> games = new ArrayList<String>();
    games.add("Call of Duty");
    games.add("Halo");

    // 用户属性
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put("movies", movies);
    properties.put("games", games);

    // 传入properties,设置用户喜欢的电影属性(movies)和喜欢的游戏属性(games)
    // 设置成功后,"movies" 属性值为 ["Sicario", "Love Letter"];"games" 属性值为 ["Call of Duty", "Halo"]
    sa.profileAppend(distinctId, true, properties);

    // 传入属性名称和需要插入属性的值,设置用户喜欢的电影属性(movies)
    // 设置成功后 "movies" 属性值为 ["Sicario", "Love Letter", "Dead Poets Society"]
    sa.profileAppend(distinctId, true, "movies", "Dead Poets Society");

    // 传入属性名称和需要插入属性的值,设置用户喜欢的电影属性(movies),
    // 但属性值 "Love Letter" 与已列表中已有元素重复,操作无效,
    // "movies" 属性值仍然为 ["Sicario", "Love Letter", "Dead Poets Society"]
    sa.profileAppend(distinctId, true, "movies", "Love Letter");

6. 物品元数据上报

在神策推荐项目中,客户需要将物品元数据上报,以开展后续推荐业务的开发与维护。神策分析 SDK 提供了设置与删除物品元数据的方法。

item_id(物品 ID )item_type (物品所属类型)共同组成了一个物品的唯一标识。所有的 item 系列方法都必须同时指定物品 ID物品所属类型这两个参数,来完成对物品的操作。

6.1 设置物品

直接设置一个物品,如果已存在则覆盖。除物品 ID 与 物品所属类型外,其他物品属性需在 properties 中定义。

物品属性中,属性名称与属性值的约束条件与事件属性相同,详细说明请参考 数据格式

public void itemSet(String itemType, String itemId, Map<String, Object> properties);

// 例如
Map<String, Object> properties = new LinkedHashMap<>();
properties.put("name", "C++ Primer");
properties.put("price", 31.54);
sensorsAnalytics.itemSet("book", "0321714113", properties);

6.2 删除一个物品

如果物品不可被推荐需要下线,删除该物品即可,如不存在则忽略。

除物品 ID 与 物品所属类型外,不解析其他物品属性。

public void itemDelete(String itemType, String itemId);

// 例如
sensorsAnalytics.itemDelete("book", "0321714113");

7. 设置神策分析 SDK

以下内容说明如何更精细地控制神策分析 SDK 的行为。

7.1. 数据采集

Java SDK 主要由以下两个组件构成:

  • SensorsAnalytics: 用于发送数据的接口对象,构造函数需要传入一个 Consumer 实例。

  • Consumer: Consumer 会进行实际的数据发送

为了让开发者更灵活的接入数据,神策分析 SDK 实现了以下 Consumer:

  • DebugConsumer: 用于校验数据导入是否正确,关于 Debug 模式 的详细信息,请进入相关页面查看。请注意,不要在生产环境中使用 Debug 模式

    // 从神策分析获取的数据接收的 URL
    final String SA_SERVER_URL = "YOUR_SERVER_URL";
    // 使用 Debug 模式,并且导入 Debug 模式下所发送的数据
    final boolean SA_WRITE_DATA = true;

    // 使用 DebugConsumer 初始化 SensorsAnalytics
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.DebugConsumer(SA_SERVER_URL, SA_WRITE_DATA));

    // 使用神策分析记录用户行为数据
    // ...

    // 程序结束前,停止神策分析 SDK 所有服务
    sa.shutdown();
  • ConcurrentLoggingConsumer: 用于将数据输出到指定目录并按天切割生成日志,并使用 LogAgent 等工具导入,该工具能保证导入不重复、不遗漏。ConcurrentLoggingConsumer 内部有一个缓存队列,当缓存队列写满时落盘写入磁盘日志文件中。缓存队列的长度可在构造函数中设置,也可以调用 flush() 方法强制落盘。推荐在生产环境中使用 ConcurrentLoggingConsumer 导入数据。支持多个进程写同一个目录(目录不能是 nas、nfs 类文件系统),生成的文件始终是带日期后缀的,每天一个。 注意: LogAgent 配置文件中一定要注释掉 real_time_file_name 参数,否则无法正常导入数据。 Windows 环境中使用请参考下面关于文件锁的描述。

    // 使用 ConcurrentLoggingConsumer 初始化 SensorsAnalytics
    // 将数据输出到 /data/sa 下的 access.log.2017-01-11 文件中,每天一个文件
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.ConcurrentLoggingConsumer("/data/sa/access.log"));

    // !! 注意 !! 如果是在 Windows 环境下使用 ConcurrentLoggingConsumer 并使用 LogAgent 发送数据,
    // 需要额外通过构造函数的第二个参数指定一个文件地址用于文件锁,例如:
    // SensorsAnalytics sa = new SensorsAnalytics(
    //      new SensorsAnalytics.ConcurrentLoggingConsumer("D:\\data\\service", "D:\\var\\sa.lock"));
    // 若该文件与数据文件同目录,配置 LogAgent 的 pattern 时请不要匹配到这个文件。

    // 使用神策分析记录用户行为数据
    // ...

    // 程序结束前,停止神策分析 SDK 所有服务
    sa.shutdown();
  • LoggingConsumer: 已不推荐在生产环境中使用,因为在多进程下文件切分可能有问题。已使用 LoggingConsumer 的客户建议按照如下步骤切换到 ConcurrentLoggingConsumer:

    第 1 步 停掉 LogAgent,并注释掉 LogAgent 配置中的 real_time_file_name 参数。

    第 2 步 将日志目录下的 real_time_file_name 的文件加上当前时间的后缀。

    第 3 步 后端程序升级切换到 ConcurrentLoggingConsumer。

    第 4 步 重新启动 LogAgent。

    关于 LogAgent 操作请参见 LogAgent 使用说明

  • BatchConsumer: 通常用于导入小规模历史数据,或者离线 / 旁路导入数据的场景。由于是同步发送数据,因此不要用在任何线上的服务中。批量发送数据的 Consumer,当数据达到指定的量(默认50条)时,才将数据进行发送。也可以调用 flush() 方法去强制发送。

    // 从神策分析获取的数据接收的 URL
    final String SA_SERVER_URL = "YOUR_SERVER_URL";
    // 当缓存的数据量达到50条时,批量发送数据
    final int SA_BULK_SIZE = 50

    // 使用 BatchConsumer 初始化 SensorsAnalytics
    // 不要在任何线上的服务中使用此 Consumer
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.BatchConsumer(SA_SERVER_URL, SA_BULK_SIZE));

    // 使用神策分析记录用户行为数据
    // ...

    // 程序结束前,停止神策分析 SDK 所有服务
    sa.shutdown();
  • ConsoleConsumer: 用于将数据输出到特定 Writer,一般用于在生产环境的 Java 程序中处理历史数据,生成日志文件并使用 BatchImporter 等工具导入

    // 将数据输出到标准输出
    final Writer writer = new PrintWriter(System.out);

    // 使用 ConsoleConsumer 初始化 SensorsAnalytics
    final SensorsAnalytics sa = new SensorsAnalytics(
            new SensorsAnalytics.ConsoleConsumer(writer));

    // 使用神策分析记录用户行为数据
    // ...

    // 程序结束前,停止神策分析 SDK 所有服务
    sa.shutdown();
    // Flush the writer
    writer.flush();

7.2. 其它设置

  • 导入历史数据:默认情况下,神策会过滤发生时间比较久远数据(例如 10 天之前,具体取决于服务端设置),如果想导入历史数据,可以通过开启 Time Free 选项来绕过这个限制。

    // 初始化 SensorsAnalytics
    final SensorsAnalytics sa = new SensorsAnalytics(...);
    // 开启 Time Free 以便导入历史数据
    sa.setEnableTimeFree(true);

Last updated

Was this helpful?