# Java SDK

> 来源：https://help.gravity-engine.com/docs/server-integration/event-collection/java-sdk
> 介绍 Gravity Engine Java SDK 的环境要求、安装初始化、事件追踪和用户属性管理，并提供参数说明与代码示例。



## 概述 [#概述]

Gravity Engine Java SDK 是一个用于数据采集和上报的工具，帮助开发者轻松集成事件追踪和用户行为分析功能。本 SDK 兼容 JDK 8 及以上版本。在接入前，请先阅读 [接入前准备](/docs/getting-started)。服务端接入 Java SDK，完成事件的服务端报送功能，您需要注意以下几点：

* 服务端 SDK 仅负责事件的收集上报，不负责用户的注册，用户注册需要调用客户端 SDK 的 `initialize` 方法完成；
* 客户端和服务端 SDK 使用的用户 `client id` 需要保持一致；
* 在客户端完成 `initialize` 方法调用之后，服务端 SDK 才能开始做事件采集上报，否则上报不成功；
* 服务端 SDK 接入事件上报时，请参考 [元事件页面](https://web.gravity-engine.com/#/manage/metadata/metaEvent) 下关于事件的详情属性；
* 请尽量上报事件的公共属性，引力不做强制要求，但是上报足够多属性，可以方便您后续在引力平台使用数据分析功能（`$city`、`$province`、`$country`、`$browser`、`$browser_version` 属性可以不上报，引力后端会自动采集）；
* 关于属性的更多信息，请您参考 [事件属性页面](https://web.gravity-engine.com/#/manage/metadata/eventProperty)。

### 1. 环境要求 [#1-环境要求]

* JDK 8 或更高版本
* Maven 项目管理工具

### 2. 安装集成 [#2-安装集成]

#### Maven 集成 [#maven-集成]

* Maven 配置私有仓库：`https://nexus.gravity-engine.com/repository/maven-releases/`

```xml
<settings
    xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <profiles>
        <profile>
            <id>nexus-profile</id>
            <repositories>
                <repository>
                    <id>maven-nexus</id>
                    <url>https://nexus.gravity-engine.com/repository/maven-releases/</url>
                    <releases>
                        <enabled>true</enabled>
                    </releases>
                    <snapshots>
                        <enabled>true</enabled>
                    </snapshots>
                </repository>
            </repositories>
        </profile>
    </profiles>
    <activeProfiles>
        <activeProfile>nexus-profile</activeProfile>
    </activeProfiles>
</settings>
```

* 在项目的 `pom.xml` 文件中添加以下依赖：

```xml
<dependencies>
    <dependency>
        <groupId>cn.gravity.java</groupId>
        <artifactId>gedata</artifactId>
        <version>3.0.9</version>
    </dependency>
</dependencies>
```

#### 手动下载 [#手动下载]

下载 JAR 文件：[下载地址](https://nexus.gravity-engine.com/repository/maven-public/cn/gravity/java/gedata/3.0.8/gedata-3.0.8.jar)

### 3. 初始化配置 [#3-初始化配置]

#### 基础配置 [#基础配置]

```java
public final static String GE_SERVER_MAIN_URL = "https://backend.gravity-engine.com/event_center/api/v1/event/collect/";
public final static String GE_ACCESS_TOKEN = "你的ACCESS_TOKEN";

public static String getMainServerUri() {
    return GE_SERVER_MAIN_URL + "?access_token=" + GE_ACCESS_TOKEN;
}
```

#### 选择数据上报模式 [#选择数据上报模式]

**批量上报模式（推荐）**

```java
public static IGEConsumer generateBatchConsumer() {
    IGEConsumer consumer = null;
    try {
        GEBatchConsumer.Config config = new GEBatchConsumer.Config();
        config.setBatchSize(20);      // 批量大小
        config.setMaxCacheSize(10);   // 最大缓存数量
        String url = getMainServerUri();
        consumer = new GEBatchConsumer(url, config);
    } catch (Exception ignored) {
    }
    return consumer;
}

// 初始化
IGEConsumer consumer = generateBatchConsumer();
GEAnalytics ge = new GEAnalytics(consumer, false);
```

## 核心功能 [#核心功能]

### 1. 事件追踪 [#1-事件追踪]

> **如需上报自定义事件，您必须先在 [元事件](https://web.gravity-engine.com/#/manage/metadata/metaEvent) 中添加，否则会上报失败！**

您可以调用 `track` 方法，记录用户自定义事件。

您需要先在 [元事件](https://web.gravity-engine.com/#/manage/metadata/metaEvent) 中添加自定义事件，然后调用 `track` 方法上报自定义事件。

```java
// 设置事件属性
HashMap<String,Object> properties = new HashMap<>();

// 支持的数据类型
properties.put("#ip", "192.168.1.1");           // 字符串
properties.put("channel", "ge");                // 字符串
properties.put("age", 1);                       // 数字
properties.put("isSuccess", true);              // 布尔值
properties.put("birthday", new Date());         // 时间

// 对象类型
HashMap<String,Object> object = new HashMap<>();
object.put("key", "value");
properties.put("object", object);

// 对象数组
HashMap<String,Object> object1 = new HashMap<>();
object1.put("key", "value");
ArrayList<Object> arr = new ArrayList<>();
arr.add(object1);
properties.put("object_arr", arr);

// 普通数组
ArrayList<String> arr1 = new ArrayList<>();
arr1.add("value");
properties.put("arr", arr1);

// 发送事件
try {
    ge.track("client_id", "payment", properties);
} catch (Exception e) {
    System.out.println("异常:" + e);
}
```

* 事件名称是 `String` 类型，只能以字母开头，可包含数字、字母和下划线 `_`，长度最大为 50 个字符。
* 事件属性是 `Map<String, Object>` 类型，其中每个元素代表一个属性；
  * 事件属性 `Key` 为属性名称，类型为 `String`，规定只能以字母开头，包含数字、字母和下划线 `_`，长度最大为 50 个字符；
  * 属性 `Value` 支持 `String`、`int`、`float`、`boolean`、`Date`、`List<String>`；当事件属性为列表类型时，您需要使用 `JSONArray` 传入，不要使用 ArrayList，否则会校验失败！

### 2. 用户属性管理 [#2-用户属性管理]

#### 设置用户属性（覆盖） [#设置用户属性覆盖]

对于一般的用户属性，您可以调用 `userSet` 进行设置，使用该接口上传的属性将会覆盖原有的属性值。

```java
Map<String,Object> userProperties = new HashMap<>();
userProperties.put("user_name", "GE");
try {
    ge.userSet("client_id", userProperties);
} catch (Exception e) {
    System.out.println("异常:" + e);
}
```

#### 初始化用户属性（仅首次设置有效） [#初始化用户属性仅首次设置有效]

对于只在首次设置时有效的属性，我们可以使用 `userSetOnce` 记录这些属性。与 `userSet` 方法不同的是，如果被设置的用户属性已存在，则这条记录会被忽略而不会覆盖已有数据。因此，`userSetOnce` 适用于为用户设置首次激活时间、首次注册时间等属性。

```java
ge.userSetOnce("client_id", new HashMap<String, Object>() {{
    put("first_login_time", "2023-01-01");
}});
```

#### 累加用户属性 [#累加用户属性]

对于数值型的用户属性，可以使用 `userIncrement` 对属性值进行累加。常用于记录用户付费次数、付费额度、积分等属性。

```java
ge.userIncrement("client_id", new HashMap<String, Object>() {{
    put("login_count", 1);
}});
```

#### 用户属性取最大值 [#用户属性取最大值]

对于数值型的用户属性，可以使用 `userMax` 比较数值大小，保存较大的值。

```java
ge.userMax("client_id", new HashMap<String, Object>() {{
    put("max_score", 200);
}});
```

#### 用户属性取最小值 [#用户属性取最小值]

对于数值型的用户属性，可以使用 `userMin` 比较数值大小，保存较小的值。

```java
ge.userMin("client_id", new HashMap<String, Object>() {{
    put("min_score", 100);
}});
```

#### 用户属性追加 [#用户属性追加]

对用户喜爱的电影、用户点评过的餐厅等属性，可以调用 `userAppend` 记录列表型属性。

```java
ge.userAppend("client_id", new HashMap<String, Object>() {{
    ArrayList<String> tags = new ArrayList<>();
    tags.add("VIP");
    tags.add("Active");
    put("user_tags", tags);
}});
```

#### 用户属性去重追加 [#用户属性去重追加]

调用 `userUniqAppend` 对 Array 类型的用户数据去重追加元素。

```java
ge.userUniqAppend("client_id", new HashMap<String, Object>() {{
    ArrayList<String> tags = new ArrayList<>();
    tags.add("VIP");
    tags.add("Active");
    put("user_tags", tags);
}});
```

#### 重置用户属性 [#重置用户属性]

如果需要重置已设置的某个用户属性，可以调用 `userUnset` 进行重置。

```java
ge.userUnset("client_id", "unwanted_property");
```

#### 清空用户属性 [#清空用户属性]

调用 `userDelete` 方法，将把当前用户属性清空，您将无法再查询该名用户的用户属性，但该用户产生的事件仍然可以被查询到。

```java
ge.userDelete("client_id");
```

### 3. 数据管理 [#3-数据管理]

#### 立即上报数据 [#立即上报数据]

```java
ge.flush();
```

> **注意**：频繁调用 `flush()` 会影响性能，建议在重要操作后调用。

#### 关闭 SDK [#关闭-sdk]

```java
ge.close();
```

> 在应用关闭前调用，确保缓存数据不会丢失。

## 完整示例 [#完整示例]

```java
import cn.gravity.java.sdk.GEAnalytics;
import cn.gravity.java.sdk.GEBatchConsumer;
import cn.gravity.java.sdk.inter.IGEConsumer;

import java.util.HashMap;
import java.util.Map;

public class GravityEngineExample {
    private static final String ACCESS_TOKEN = "你的ACCESS_TOKEN";
    private static GEAnalytics ge;

public static void main(String[] args) {
    // 初始化
    initializeSDK();

    // 设置用户属性
    setUserProperties();

    // 发送事件
    trackEvents();

    // 清理资源
    cleanup();
}

private static void initializeSDK() {
    String url = "https://backend.gravity-engine.com/event_center/api/v1/event/collect/?access_token=" + ACCESS_TOKEN;

    GEBatchConsumer.Config config = new GEBatchConsumer.Config();
    config.setBatchSize(20);
    config.setMaxCacheSize(10);

    IGEConsumer consumer = new GEBatchConsumer(url, config);
    ge = new GEAnalytics(consumer, false);

    // 开启日志
    GEAnalytics.enableLog(true);
}

private static void setUserProperties() {
    String clientId = "user_123";

    // 设置基础属性
    Map<String, Object> properties = new HashMap<>();
    properties.put("user_name", "张三");
    properties.put("city", "北京");
    properties.put("age", 28);

    ge.userSet(clientId, properties);

    // 首次设置注册时间
    ge.userSetOnce(clientId, new HashMap<String, Object>() {{
        put("register_time", "2023-01-01");
    }});

    // 增加登录次数
    ge.userIncrement(clientId, new HashMap<String, Object>() {{
        put("login_count", 1);
    }});
}

private static void trackEvents() {
    String clientId = "user_123";

    Map<String, Object> properties = new HashMap<>();
    properties.put("#ip", "192.168.1.1");
    properties.put("product_id", "P001");
    properties.put("amount", 199.9);
    properties.put("currency", "CNY");

    try {
        ge.track(clientId, "purchase", properties);
    } catch (Exception e) {
        System.out.println("事件发送失败: " + e.getMessage());
    }
}

private static void cleanup() {
    // 确保数据上报
    ge.flush();

    // 关闭SDK
    ge.close();
}
}
```

## 最佳实践 [#最佳实践]

1. **批量上报**：生产环境推荐使用批量上报模式，平衡性能和实时性。
2. **异常处理**：对所有 SDK 调用进行异常捕获。
3. **资源清理**：在应用关闭前调用 `close()` 方法。
4. **属性命名**：使用有意义的属性名称，保持一致性。
5. **数据类型**：确保属性值类型符合预期，避免类型错误。

## 故障排除 [#故障排除]

### 常见问题 [#常见问题]

1. **初始化问题**：检查 `ACCESS_TOKEN` 和服务器地址是否正确
2. **数据格式**：验证事件属性数据类型是否符合要求
3. **性能问题**：避免频繁调用 `flush()` 方法
