业务场景示例
本文档提供真实业务场景的完整代码示例,帮助您快速理解如何在实际项目中使用 Lovrabet Java OpenSDK。
目录
场景 1: 客户数据同步服务
业务需求
您的 Java CRM 系统需要将新增客户信息同步到 Lovrabet 云兔平台,用于数据分析和报表生成。
技术方案
- 监听 CRM 系统的客户创建事件
- 将客户数据转换为 Lovrabet 数据格式
- 调用 OpenSDK 创建客户记录
- 记录同步日志,处理异常情况
完整代码
package com.example.crm.sync;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import com.lovrabet.runtime.opensdk.model.LovrabetRequest;
import com.lovrabet.runtime.opensdk.model.LovrabetResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* 客户数据同步服务
* 将 CRM 系统的客户数据同步到 Lovrabet 云兔平台
*/
public class CustomerSyncService {
private static final Logger logger = LoggerFactory.getLogger(CustomerSyncService.class);
private final LovrabetSDKClient sdkClient;
private final String appCode = "app-c2dd52a2";
private final String customerDatasetCode = "b460abdbb0fb49e1865110d9dfbbc9b4";
public CustomerSyncService(String accessKey, String baseUrl) {
this.sdkClient = new LovrabetSDKClient(accessKey, baseUrl);
}
/**
* 同步单个客户数据
*/
public boolean syncCustomer(Customer customer) {
logger.info("开始同步客户数据: {}", customer.getName());
try {
// 构建请求参数
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(customerDatasetCode);
// 转换客户数据为 Lovrabet 格式
Map<String, Object> paramMap = convertCustomerData(customer);
request.setParamMap(paramMap);
// 调用 API 创建记录
LovrabetResult<String> result = sdkClient.create(request);
if (result.isSuccess()) {
String lovrabetId = result.getData();
logger.info("客户同步成功 - 客户: {}, Lovrabet ID: {}",
customer.getName(), lovrabetId);
// 保存 Lovrabet ID 到本地数据库(可选)
updateCustomerLovrabetId(customer.getId(), lovrabetId);
return true;
} else {
logger.error("客户同步失败 - 客户: {}, 错误: {}",
customer.getName(), result.getResultMsg());
return false;
}
} catch (Exception e) {
logger.error("客户同步异常 - 客户: {}", customer.getName(), e);
return false;
}
}
/**
* 批量同步客户数据
*/
public SyncResult batchSyncCustomers(List<Customer> customers) {
logger.info("开始批量同步客户数据, 总数: {}", customers.size());
int successCount = 0;
int failCount = 0;
List<String> failedCustomers = new ArrayList<>();
for (Customer customer : customers) {
boolean success = syncCustomer(customer);
if (success) {
successCount++;
} else {
failCount++;
failedCustomers.add(customer.getName());
}
}
logger.info("批量同步完成 - 成功: {}, 失败: {}", successCount, failCount);
return new SyncResult(successCount, failCount, failedCustomers);
}
/**
* 更新客户数据
*/
public boolean updateCustomer(Customer customer, String lovrabetId) {
logger.info("开始更新客户数据: {}", customer.getName());
try {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(customerDatasetCode);
request.setId(Long.parseLong(lovrabetId));
// 只更新变化的字段
Map<String, Object> paramMap = convertCustomerData(customer);
request.setParamMap(paramMap);
LovrabetResult<String> result = sdkClient.update(request);
if (result.isSuccess()) {
logger.info("客户更新成功 - 客户: {}", customer.getName());
return true;
} else {
logger.error("客户更新失败 - 客户: {}, 错误: {}",
customer.getName(), result.getResultMsg());
return false;
}
} catch (Exception e) {
logger.error("客户更新异常 - 客户: {}", customer.getName(), e);
return false;
}
}
/**
* 将 CRM 客户对象转换为 Lovrabet 数据格式
*/
private Map<String, Object> convertCustomerData(Customer customer) {
Map<String, Object> paramMap = new HashMap<>();
// 客户名称
paramMap.put("TEXT_1", customer.getName());
// 联系电话
if (customer.getPhone() != null) {
paramMap.put("TEXT_2", customer.getPhone());
}
// 电子邮箱
if (customer.getEmail() != null) {
paramMap.put("TEXT_3", customer.getEmail());
}
// 公司名称
if (customer.getCompany() != null) {
paramMap.put("TEXT_4", customer.getCompany());
}
// 客户级别 (1-普通, 2-重要, 3-VIP)
paramMap.put("SELECT_1", customer.getLevel());
// 客户来源
if (customer.getSource() != null) {
paramMap.put("SELECT_2", customer.getSource());
}
// 预估年消费金额
if (customer.getEstimatedAnnualValue() != null) {
paramMap.put("NUMBER_1", customer.getEstimatedAnnualValue());
}
// 创建时间
paramMap.put("DATETIME_1", customer.getCreateTime().getTime());
return paramMap;
}
/**
* 保存 Lovrabet ID 到本地数据库
*/
private void updateCustomerLovrabetId(Long customerId, String lovrabetId) {
// 实际项目中这里应该更新数据库
logger.debug("保存客户 {} 的 Lovrabet ID: {}", customerId, lovrabetId);
}
}
/**
* 客户实体类 (示例)
*/
class Customer {
private Long id;
private String name;
private String phone;
private String email;
private String company;
private Integer level; // 1-普通, 2-重要, 3-VIP
private String source; // online, offline, referral
private Double estimatedAnnualValue;
private Date createTime;
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getCompany() { return company; }
public void setCompany(String company) { this.company = company; }
public Integer getLevel() { return level; }
public void setLevel(Integer level) { this.level = level; }
public String getSource() { return source; }
public void setSource(String source) { this.source = source; }
public Double getEstimatedAnnualValue() { return estimatedAnnualValue; }
public void setEstimatedAnnualValue(Double estimatedAnnualValue) {
this.estimatedAnnualValue = estimatedAnnualValue;
}
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
}
/**
* 同步结果类
*/
class SyncResult {
private int successCount;
private int failCount;
private List<String> failedItems;
public SyncResult(int successCount, int failCount, List<String> failedItems) {
this.successCount = successCount;
this.failCount = failCount;
this.failedItems = failedItems;
}
// Getters
public int getSuccessCount() { return successCount; }
public int getFailCount() { return failCount; }
public List<String> getFailedItems() { return failedItems; }
}
使用示例
public class CustomerSyncDemo {
public static void main(String[] args) {
// 初始化同步服务
String accessKey = System.getenv("LOVRABET_ACCESS_KEY");
String baseUrl = "https://runtime.lovrabet.com/openapi";
CustomerSyncService syncService = new CustomerSyncService(accessKey, baseUrl);
// 创建客户对象
Customer customer = new Customer();
customer.setId(1001L);
customer.setName("阿里巴巴科技有限公司");
customer.setPhone("138-0000-1234");
customer.setEmail("contact@alibaba.com");
customer.setCompany("阿里巴巴");
customer.setLevel(3); // VIP 客户
customer.setSource("referral");
customer.setEstimatedAnnualValue(500000.0);
customer.setCreateTime(new Date());
// 同步单个客户
boolean success = syncService.syncCustomer(customer);
if (success) {
System.out.println("客户同步成功");
}
// 批量同步客户
List<Customer> customers = getCustomersFromDatabase();
SyncResult result = syncService.batchSyncCustomers(customers);
System.out.println("同步完成 - 成功: " + result.getSuccessCount()
+ ", 失败: " + result.getFailCount());
}
private static List<Customer> getCustomersFromDatabase() {
// 从数据库获取客户列表
return new ArrayList<>();
}
}
场景 2: 销售漏斗分析看板
业务需求
从 Lovrabet 云兔平台获取销售机会数据,按阶段统计数量和金额,生成销售漏斗分析报告。
技术方案
- 查询所有销售机会数据
- 按销售阶段分组统计
- 计算转化率和金额汇总
- 生成可视化报表数据
完整代码
package com.example.sales.analysis;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import com.lovrabet.runtime.opensdk.model.LovrabetRequest;
import com.lovrabet.runtime.opensdk.model.LovrabetResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;
/**
* 销售漏斗分析服务
* 从 Lovrabet 获取销售数据并进行漏斗分析
*/
public class SalesFunnelAnalysisService {
private static final Logger logger = LoggerFactory.getLogger(SalesFunnelAnalysisService.class);
private final LovrabetSDKClient sdkClient;
private final String appCode = "app-c2dd52a2";
private final String opportunityDatasetCode = "32c036010c504757b80d438e3c0ec8b7";
public SalesFunnelAnalysisService(String accessKey, String baseUrl) {
this.sdkClient = new LovrabetSDKClient(accessKey, baseUrl);
}
/**
* 获取销售漏斗分析报告
*/
public FunnelReport generateFunnelReport() {
logger.info("开始生成销售漏斗分析报告");
// 1. 获取所有销售机会数据
List<Map<String, Object>> opportunities = getAllOpportunities();
if (opportunities.isEmpty()) {
logger.warn("未查询到销售机会数据");
return new FunnelReport();
}
logger.info("查询到销售机会数量: {}", opportunities.size());
// 2. 按阶段分组统计
Map<String, FunnelStage> stageMap = analyzeByStage(opportunities);
// 3. 计算总体指标
FunnelReport report = new FunnelReport();
report.setTotalCount(opportunities.size());
report.setTotalAmount(calculateTotalAmount(opportunities));
report.setStages(sortStages(stageMap));
report.setGenerateTime(new Date());
logger.info("销售漏斗分析完成 - 总机会数: {}, 总金额: {}",
report.getTotalCount(), report.getTotalAmount());
return report;
}
/**
* 获取所有销售机会数据
*/
private List<Map<String, Object>> getAllOpportunities() {
List<Map<String, Object>> allData = new ArrayList<>();
int currentPage = 1;
int pageSize = 100;
boolean hasMore = true;
while (hasMore) {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(opportunityDatasetCode);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("currentPage", currentPage);
paramMap.put("pageSize", pageSize);
request.setParamMap(paramMap);
LovrabetResult<?> result = sdkClient.getList(request);
if (result.isSuccess()) {
List<Map<String, Object>> pageData =
(List<Map<String, Object>>) result.getData();
if (pageData.isEmpty()) {
hasMore = false;
} else {
allData.addAll(pageData);
if (pageData.size() < pageSize) {
hasMore = false;
} else {
currentPage++;
}
}
} else {
logger.error("查询销售机会失败: {}", result.getResultMsg());
hasMore = false;
}
}
return allData;
}
/**
* 按销售阶段分析数据
*/
private Map<String, FunnelStage> analyzeByStage(List<Map<String, Object>> opportunities) {
Map<String, FunnelStage> stageMap = new HashMap<>();
for (Map<String, Object> opportunity : opportunities) {
// 获取销售阶段 (SELECT_4 字段)
String stage = (String) opportunity.get("SELECT_4");
if (stage == null) {
stage = "未知";
}
// 获取金额 (NUMBER_3 字段)
Number amountObj = (Number) opportunity.get("NUMBER_3");
double amount = amountObj != null ? amountObj.doubleValue() : 0.0;
// 累加该阶段的数据
FunnelStage funnelStage = stageMap.computeIfAbsent(stage, k -> new FunnelStage(k));
funnelStage.addOpportunity(amount);
}
return stageMap;
}
/**
* 计算总金额
*/
private double calculateTotalAmount(List<Map<String, Object>> opportunities) {
return opportunities.stream()
.map(opp -> (Number) opp.get("NUMBER_3"))
.filter(Objects::nonNull)
.mapToDouble(Number::doubleValue)
.sum();
}
/**
* 对阶段进行排序(按销售流程顺序)
*/
private List<FunnelStage> sortStages(Map<String, FunnelStage> stageMap) {
// 定义销售阶段顺序
List<String> stageOrder = Arrays.asList(
"线索", "初次接触", "需求分析", "方案提报",
"商务谈判", "合同签订", "已成交", "已失败"
);
return stageOrder.stream()
.filter(stageMap::containsKey)
.map(stageMap::get)
.collect(Collectors.toList());
}
/**
* 获取某个销售人员的业绩数据
*/
public SalesPersonPerformance getSalesPersonPerformance(String salespersonName) {
logger.info("查询销售人员业绩: {}", salespersonName);
List<Map<String, Object>> allOpportunities = getAllOpportunities();
// 筛选该销售人员的机会 (TEXT_1 字段存储销售人员名称)
List<Map<String, Object>> personOpportunities = allOpportunities.stream()
.filter(opp -> salespersonName.equals(opp.get("TEXT_1")))
.collect(Collectors.toList());
SalesPersonPerformance performance = new SalesPersonPerformance();
performance.setSalespersonName(salespersonName);
performance.setTotalOpportunities(personOpportunities.size());
// 计算已成交金额
double closedAmount = personOpportunities.stream()
.filter(opp -> "已成交".equals(opp.get("SELECT_4")))
.map(opp -> (Number) opp.get("NUMBER_3"))
.filter(Objects::nonNull)
.mapToDouble(Number::doubleValue)
.sum();
performance.setClosedAmount(closedAmount);
// 计算在谈金额
double pipelineAmount = personOpportunities.stream()
.filter(opp -> {
String stage = (String) opp.get("SELECT_4");
return stage != null && !stage.equals("已成交") && !stage.equals("已失败");
})
.map(opp -> (Number) opp.get("NUMBER_3"))
.filter(Objects::nonNull)
.mapToDouble(Number::doubleValue)
.sum();
performance.setPipelineAmount(pipelineAmount);
logger.info("销售人员 {} 业绩 - 总机会: {}, 已成交金额: {}, 在谈金额: {}",
salespersonName, performance.getTotalOpportunities(),
closedAmount, pipelineAmount);
return performance;
}
}
/**
* 销售漏斗阶段数据
*/
class FunnelStage {
private String stageName;
private int count;
private double totalAmount;
public FunnelStage(String stageName) {
this.stageName = stageName;
this.count = 0;
this.totalAmount = 0.0;
}
public void addOpportunity(double amount) {
this.count++;
this.totalAmount += amount;
}
// Getters
public String getStageName() { return stageName; }
public int getCount() { return count; }
public double getTotalAmount() { return totalAmount; }
public double getAverageAmount() {
return count > 0 ? totalAmount / count : 0.0;
}
}
/**
* 销售漏斗报告
*/
class FunnelReport {
private int totalCount;
private double totalAmount;
private List<FunnelStage> stages;
private Date generateTime;
public FunnelReport() {
this.stages = new ArrayList<>();
}
// Getters and Setters
public int getTotalCount() { return totalCount; }
public void setTotalCount(int totalCount) { this.totalCount = totalCount; }
public double getTotalAmount() { return totalAmount; }
public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; }
public List<FunnelStage> getStages() { return stages; }
public void setStages(List<FunnelStage> stages) { this.stages = stages; }
public Date getGenerateTime() { return generateTime; }
public void setGenerateTime(Date generateTime) { this.generateTime = generateTime; }
}
/**
* 销售人员业绩数据
*/
class SalesPersonPerformance {
private String salespersonName;
private int totalOpportunities;
private double closedAmount;
private double pipelineAmount;
// Getters and Setters
public String getSalespersonName() { return salespersonName; }
public void setSalespersonName(String salespersonName) {
this.salespersonName = salespersonName;
}
public int getTotalOpportunities() { return totalOpportunities; }
public void setTotalOpportunities(int totalOpportunities) {
this.totalOpportunities = totalOpportunities;
}
public double getClosedAmount() { return closedAmount; }
public void setClosedAmount(double closedAmount) {
this.closedAmount = closedAmount;
}
public double getPipelineAmount() { return pipelineAmount; }
public void setPipelineAmount(double pipelineAmount) {
this.pipelineAmount = pipelineAmount;
}
}
使用示例
public class SalesFunnelDemo {
public static void main(String[] args) {
String accessKey = System.getenv("LOVRABET_ACCESS_KEY");
String baseUrl = "https://runtime.lovrabet.com/openapi";
SalesFunnelAnalysisService analysisService =
new SalesFunnelAnalysisService(accessKey, baseUrl);
// 生成销售漏斗报告
FunnelReport report = analysisService.generateFunnelReport();
System.out.println("===== 销售漏斗分析报告 =====");
System.out.println("生成时间: " + report.getGenerateTime());
System.out.println("总机会数: " + report.getTotalCount());
System.out.println("总金额: " + String.format("%.2f", report.getTotalAmount()));
System.out.println("\n各阶段详情:");
for (FunnelStage stage : report.getStages()) {
System.out.println(String.format("%s: %d 个机会, 总金额 %.2f, 平均金额 %.2f",
stage.getStageName(),
stage.getCount(),
stage.getTotalAmount(),
stage.getAverageAmount()));
}
// 查询特定销售人员业绩
SalesPersonPerformance performance =
analysisService.getSalesPersonPerformance("张三");
System.out.println("\n===== 销售人员业绩 =====");
System.out.println("销售人员: " + performance.getSalespersonName());
System.out.println("总机会数: " + performance.getTotalOpportunities());
System.out.println("已成交金额: " + String.format("%.2f", performance.getClosedAmount()));
System.out.println("在谈金额: " + String.format("%.2f", performance.getPipelineAmount()));
}
}
场景 3: 订单管理系统
业务需求
电商系统需要将订单数据同步到 Lovrabet,并支持订单状态更新、查询订单详情等操作。
完整代码
package com.example.order;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import com.lovrabet.runtime.opensdk.model.LovrabetRequest;
import com.lovrabet.runtime.opensdk.model.LovrabetResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* 订单管理服务
* 将电商订单同步到 Lovrabet 并管理订单状态
*/
public class OrderManagementService {
private static final Logger logger = LoggerFactory.getLogger(OrderManagementService.class);
private final LovrabetSDKClient sdkClient;
private final String appCode = "app-c2dd52a2";
private final String orderDatasetCode = "b460abdbb0fb49e1865110d9dfbbc9b4";
public OrderManagementService(String accessKey, String baseUrl) {
this.sdkClient = new LovrabetSDKClient(accessKey, baseUrl);
}
/**
* 创建订单
*/
public String createOrder(Order order) {
logger.info("创建订单: {}", order.getOrderNo());
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(orderDatasetCode);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("TEXT_1", order.getOrderNo()); // 订单号
paramMap.put("TEXT_2", order.getCustomerName()); // 客户姓名
paramMap.put("TEXT_3", order.getCustomerPhone()); // 联系电话
paramMap.put("TEXT_4", order.getShippingAddress()); // 收货地址
paramMap.put("NUMBER_1", order.getTotalAmount()); // 订单金额
paramMap.put("NUMBER_2", order.getItemCount()); // 商品数量
paramMap.put("SELECT_1", order.getStatus()); // 订单状态
paramMap.put("SELECT_2", order.getPaymentMethod()); // 支付方式
paramMap.put("DATETIME_1", order.getCreateTime().getTime()); // 创建时间
LovrabetResult<String> result = sdkClient.create(request);
if (result.isSuccess()) {
String lovrabetId = result.getData();
logger.info("订单创建成功 - 订单号: {}, Lovrabet ID: {}",
order.getOrderNo(), lovrabetId);
return lovrabetId;
} else {
logger.error("订单创建失败 - 订单号: {}, 错误: {}",
order.getOrderNo(), result.getResultMsg());
return null;
}
}
/**
* 更新订单状态
*/
public boolean updateOrderStatus(String lovrabetId, String newStatus) {
logger.info("更新订单状态 - ID: {}, 新状态: {}", lovrabetId, newStatus);
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(orderDatasetCode);
request.setId(Long.parseLong(lovrabetId));
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("SELECT_1", newStatus); // 更新状态字段
// 如果是发货状态,添加发货时间
if ("已发货".equals(newStatus)) {
paramMap.put("DATETIME_2", System.currentTimeMillis());
}
// 如果是完成状态,添加完成时间
if ("已完成".equals(newStatus)) {
paramMap.put("DATETIME_3", System.currentTimeMillis());
}
request.setParamMap(paramMap);
LovrabetResult<String> result = sdkClient.update(request);
if (result.isSuccess()) {
logger.info("订单状态更新成功 - ID: {}", lovrabetId);
return true;
} else {
logger.error("订单状态更新失败 - ID: {}, 错误: {}",
lovrabetId, result.getResultMsg());
return false;
}
}
/**
* 查询订单详情
*/
public Map<String, Object> getOrderDetail(String lovrabetId) {
logger.info("查询订单详情 - ID: {}", lovrabetId);
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(orderDatasetCode);
request.setId(Long.parseLong(lovrabetId));
LovrabetResult<?> result = sdkClient.getOne(request);
if (result.isSuccess()) {
Map<String, Object> orderData = (Map<String, Object>) result.getData();
logger.info("订单查询成功 - ID: {}, 订单号: {}",
lovrabetId, orderData.get("TEXT_1"));
return orderData;
} else {
logger.error("订单查询失败 - ID: {}, 错误: {}",
lovrabetId, result.getResultMsg());
return null;
}
}
/**
* 查询指定时间段的订单
*/
public List<Map<String, Object>> getOrdersByDateRange(Date startDate, Date endDate) {
logger.info("查询时间段订单 - 开始: {}, 结束: {}", startDate, endDate);
List<Map<String, Object>> allOrders = new ArrayList<>();
int currentPage = 1;
int pageSize = 50;
boolean hasMore = true;
while (hasMore) {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(orderDatasetCode);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("currentPage", currentPage);
paramMap.put("pageSize", pageSize);
request.setParamMap(paramMap);
LovrabetResult<?> result = sdkClient.getList(request);
if (result.isSuccess()) {
List<Map<String, Object>> pageData =
(List<Map<String, Object>>) result.getData();
if (pageData.isEmpty()) {
hasMore = false;
} else {
// 筛选时间范围内的订单
for (Map<String, Object> order : pageData) {
Number createTimeMs = (Number) order.get("DATETIME_1");
if (createTimeMs != null) {
Date createTime = new Date(createTimeMs.longValue());
if (!createTime.before(startDate) && !createTime.after(endDate)) {
allOrders.add(order);
}
}
}
if (pageData.size() < pageSize) {
hasMore = false;
} else {
currentPage++;
}
}
} else {
logger.error("查询订单列表失败: {}", result.getResultMsg());
hasMore = false;
}
}
logger.info("时间段订单查询完成 - 共 {} 条", allOrders.size());
return allOrders;
}
/**
* 统计订单数据
*/
public OrderStatistics getOrderStatistics() {
logger.info("开始统计订单数据");
List<Map<String, Object>> allOrders = getAllOrders();
OrderStatistics stats = new OrderStatistics();
stats.setTotalOrders(allOrders.size());
// 统计总金额
double totalAmount = allOrders.stream()
.map(order -> (Number) order.get("NUMBER_1"))
.filter(Objects::nonNull)
.mapToDouble(Number::doubleValue)
.sum();
stats.setTotalAmount(totalAmount);
// 统计各状态订单数
Map<String, Long> statusCount = allOrders.stream()
.collect(Collectors.groupingBy(
order -> (String) order.getOrDefault("SELECT_1", "未知"),
Collectors.counting()
));
stats.setStatusCount(statusCount);
logger.info("订单统计完成 - 总订单: {}, 总金额: {}",
stats.getTotalOrders(), stats.getTotalAmount());
return stats;
}
/**
* 获取所有订单
*/
private List<Map<String, Object>> getAllOrders() {
List<Map<String, Object>> allOrders = new ArrayList<>();
int currentPage = 1;
int pageSize = 100;
boolean hasMore = true;
while (hasMore) {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(orderDatasetCode);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("currentPage", currentPage);
paramMap.put("pageSize", pageSize);
request.setParamMap(paramMap);
LovrabetResult<?> result = sdkClient.getList(request);
if (result.isSuccess()) {
List<Map<String, Object>> pageData =
(List<Map<String, Object>>) result.getData();
if (pageData.isEmpty()) {
hasMore = false;
} else {
allOrders.addAll(pageData);
if (pageData.size() < pageSize) {
hasMore = false;
} else {
currentPage++;
}
}
} else {
logger.error("查询订单列表失败: {}", result.getResultMsg());
hasMore = false;
}
}
return allOrders;
}
}
/**
* 订单实体类
*/
class Order {
private String orderNo;
private String customerName;
private String customerPhone;
private String shippingAddress;
private Double totalAmount;
private Integer itemCount;
private String status; // 待支付、已支付、已发货、已完成、已取消
private String paymentMethod; // 支付宝、微信、银行卡
private Date createTime;
// Getters and Setters
public String getOrderNo() { return orderNo; }
public void setOrderNo(String orderNo) { this.orderNo = orderNo; }
public String getCustomerName() { return customerName; }
public void setCustomerName(String customerName) { this.customerName = customerName; }
public String getCustomerPhone() { return customerPhone; }
public void setCustomerPhone(String customerPhone) { this.customerPhone = customerPhone; }
public String getShippingAddress() { return shippingAddress; }
public void setShippingAddress(String shippingAddress) {
this.shippingAddress = shippingAddress;
}
public Double getTotalAmount() { return totalAmount; }
public void setTotalAmount(Double totalAmount) { this.totalAmount = totalAmount; }
public Integer getItemCount() { return itemCount; }
public void setItemCount(Integer itemCount) { this.itemCount = itemCount; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getPaymentMethod() { return paymentMethod; }
public void setPaymentMethod(String paymentMethod) { this.paymentMethod = paymentMethod; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
}
/**
* 订单统计数据
*/
class OrderStatistics {
private int totalOrders;
private double totalAmount;
private Map<String, Long> statusCount;
// Getters and Setters
public int getTotalOrders() { return totalOrders; }
public void setTotalOrders(int totalOrders) { this.totalOrders = totalOrders; }
public double getTotalAmount() { return totalAmount; }
public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; }
public Map<String, Long> getStatusCount() { return statusCount; }
public void setStatusCount(Map<String, Long> statusCount) {
this.statusCount = statusCount;
}
}
使用示例
public class OrderManagementDemo {
public static void main(String[] args) {
String accessKey = System.getenv("LOVRABET_ACCESS_KEY");
String baseUrl = "https://runtime.lovrabet.com/openapi";
OrderManagementService orderService =
new OrderManagementService(accessKey, baseUrl);
// 1. 创建订单
Order order = new Order();
order.setOrderNo("ORD20250112001");
order.setCustomerName("李明");
order.setCustomerPhone("138-1234-5678");
order.setShippingAddress("北京市朝阳区xx路xx号");
order.setTotalAmount(299.00);
order.setItemCount(2);
order.setStatus("待支付");
order.setPaymentMethod("支付宝");
order.setCreateTime(new Date());
String lovrabetId = orderService.createOrder(order);
System.out.println("订单创建成功, ID: " + lovrabetId);
// 2. 更新订单状态
boolean updated = orderService.updateOrderStatus(lovrabetId, "已支付");
System.out.println("订单状态更新: " + (updated ? "成功" : "失败"));
// 3. 查询订单详情
Map<String, Object> orderDetail = orderService.getOrderDetail(lovrabetId);
System.out.println("订单详情: " + orderDetail);
// 4. 统计订单数据
OrderStatistics stats = orderService.getOrderStatistics();
System.out.println("\n===== 订单统计 =====");
System.out.println("总订单数: " + stats.getTotalOrders());
System.out.println("总金额: " + String.format("%.2f", stats.getTotalAmount()));
System.out.println("各状态订单数:");
stats.getStatusCount().forEach((status, count) ->
System.out.println(" " + status + ": " + count + " 个"));
}
}
场景 4: 定时数据同步任务
业务需求
每天定时将本地数据库的客户数据同步到 Lovrabet,保持数据一致性。
完整代码
package com.example.scheduler;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import com.lovrabet.runtime.opensdk.model.LovrabetRequest;
import com.lovrabet.runtime.opensdk.model.LovrabetResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.*;
/**
* 定时数据同步任务
* 每天定时将本地数据同步到 Lovrabet
*/
public class DataSyncScheduler {
private static final Logger logger = LoggerFactory.getLogger(DataSyncScheduler.class);
private final LovrabetSDKClient sdkClient;
private final ScheduledExecutorService scheduler;
private final String appCode = "app-c2dd52a2";
private final String datasetCode = "b460abdbb0fb49e1865110d9dfbbc9b4";
public DataSyncScheduler(String accessKey, String baseUrl) {
this.sdkClient = new LovrabetSDKClient(accessKey, baseUrl);
this.scheduler = Executors.newScheduledThreadPool(1);
}
/**
* 启动定时同步任务
* 每天凌晨 2:00 执行
*/
public void startScheduledSync() {
logger.info("启动定时同步任务");
// 计算到下一个凌晨 2:00 的延迟时间
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 2);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
long initialDelay = calendar.getTimeInMillis() - System.currentTimeMillis();
long period = TimeUnit.DAYS.toMillis(1); // 24 小时
scheduler.scheduleAtFixedRate(
this::performSync,
initialDelay,
period,
TimeUnit.MILLISECONDS
);
logger.info("定时同步任务已启动, 首次执行时间: {}", calendar.getTime());
}
/**
* 执行同步操作
*/
public void performSync() {
logger.info("========== 开始执行数据同步 ==========");
long startTime = System.currentTimeMillis();
try {
// 1. 从本地数据库获取需要同步的数据
List<Map<String, Object>> localData = fetchDataFromLocalDatabase();
logger.info("从本地数据库获取到 {} 条待同步数据", localData.size());
if (localData.isEmpty()) {
logger.info("没有待同步数据,任务结束");
return;
}
// 2. 批量同步数据
SyncResult result = batchSyncData(localData);
// 3. 记录同步结果
long duration = System.currentTimeMillis() - startTime;
logger.info("========== 数据同步完成 ==========");
logger.info("总数据量: {}", localData.size());
logger.info("成功: {}, 失败: {}", result.getSuccessCount(), result.getFailCount());
logger.info("耗时: {} 秒", duration / 1000);
// 4. 更新本地数据库的同步状态
updateSyncStatus(result);
// 5. 发送同步报告
sendSyncReport(result, duration);
} catch (Exception e) {
logger.error("数据同步过程中发生异常", e);
sendErrorAlert(e);
}
}
/**
* 批量同步数据
*/
private SyncResult batchSyncData(List<Map<String, Object>> dataList) {
int successCount = 0;
int failCount = 0;
List<String> failedIds = new ArrayList<>();
// 使用线程池并发同步
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Boolean>> futures = new ArrayList<>();
for (Map<String, Object> data : dataList) {
Future<Boolean> future = executor.submit(() -> syncSingleRecord(data));
futures.add(future);
}
// 等待所有任务完成并统计结果
for (int i = 0; i < futures.size(); i++) {
try {
Boolean success = futures.get(i).get();
if (success) {
successCount++;
} else {
failCount++;
failedIds.add(String.valueOf(dataList.get(i).get("id")));
}
} catch (Exception e) {
failCount++;
failedIds.add(String.valueOf(dataList.get(i).get("id")));
logger.error("获取同步结果失败", e);
}
}
executor.shutdown();
return new SyncResult(successCount, failCount, failedIds);
}
/**
* 同步单条记录
*/
private boolean syncSingleRecord(Map<String, Object> data) {
try {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(appCode);
request.setModelCode(datasetCode);
// 转换数据格式
Map<String, Object> paramMap = convertToLovrabetFormat(data);
request.setParamMap(paramMap);
// 检查是否已存在(通过本地ID映射)
String lovrabetId = getExistingLovrabetId(data.get("id"));
LovrabetResult<String> result;
if (lovrabetId != null) {
// 更新已存在的记录
request.setId(Long.parseLong(lovrabetId));
result = sdkClient.update(request);
} else {
// 创建新记录
result = sdkClient.create(request);
if (result.isSuccess()) {
// 保存新记录的 Lovrabet ID
saveIdMapping(data.get("id"), result.getData());
}
}
return result.isSuccess();
} catch (Exception e) {
logger.error("同步记录失败: {}", data.get("id"), e);
return false;
}
}
/**
* 从本地数据库获取待同步数据
*/
private List<Map<String, Object>> fetchDataFromLocalDatabase() {
// 实际项目中这里应该查询数据库
// 这里返回示例数据
logger.debug("从本地数据库获取数据...");
return new ArrayList<>();
}
/**
* 转换为 Lovrabet 数据格式
*/
private Map<String, Object> convertToLovrabetFormat(Map<String, Object> localData) {
Map<String, Object> lovrabetData = new HashMap<>();
// 根据字段映射关系转换
lovrabetData.put("TEXT_1", localData.get("name"));
lovrabetData.put("TEXT_2", localData.get("phone"));
lovrabetData.put("NUMBER_1", localData.get("amount"));
lovrabetData.put("DATETIME_1", localData.get("createTime"));
return lovrabetData;
}
/**
* 获取已存在的 Lovrabet ID
*/
private String getExistingLovrabetId(Object localId) {
// 实际项目中这里应该查询映射表
logger.debug("查询本地ID {} 对应的 Lovrabet ID", localId);
return null;
}
/**
* 保存 ID 映射关系
*/
private void saveIdMapping(Object localId, String lovrabetId) {
// 实际项目中这里应该保存到映射表
logger.debug("保存ID映射: {} -> {}", localId, lovrabetId);
}
/**
* 更新同步状态
*/
private void updateSyncStatus(SyncResult result) {
// 更新本地数据库的同步状态
logger.debug("更新同步状态");
}
/**
* 发送同步报告
*/
private void sendSyncReport(SyncResult result, long duration) {
logger.info("发送同步报告");
// 实际项目中可以发送邮件或消息通知
}
/**
* 发送错误告警
*/
private void sendErrorAlert(Exception e) {
logger.error("发送错误告警");
// 实际项目中可以发送告警消息
}
/**
* 停止定时任务
*/
public void shutdown() {
logger.info("停止定时同步任务");
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
使用示例
public class SchedulerDemo {
public static void main(String[] args) {
String accessKey = System.getenv("LOVRABET_ACCESS_KEY");
String baseUrl = "https://runtime.lovrabet.com/openapi";
DataSyncScheduler scheduler = new DataSyncScheduler(accessKey, baseUrl);
// 启动定时同步任务(每天凌晨 2:00)
scheduler.startScheduledSync();
// 或者立即执行一次同步
scheduler.performSync();
// 程序退出时停止调度器
Runtime.getRuntime().addShutdownHook(new Thread(scheduler::shutdown));
}
}
场景 5: Spring Boot 集成
业务需求
在 Spring Boot 应用中集成 Lovrabet OpenSDK,实现依赖注入和自动配置。
完整代码
1. 配置类
package com.example.config;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Lovrabet SDK 配置类
*/
@Configuration
public class LovrabetConfig {
@Bean
@ConfigurationProperties(prefix = "lovrabet")
public LovrabetProperties lovrabetProperties() {
return new LovrabetProperties();
}
@Bean
public LovrabetSDKClient lovrabetSDKClient(LovrabetProperties properties) {
return new LovrabetSDKClient(
properties.getAccessKey(),
properties.getBaseUrl()
);
}
}
/**
* Lovrabet 配置属性
*/
class LovrabetProperties {
private String accessKey;
private String baseUrl;
private String appCode;
// Getters and Setters
public String getAccessKey() { return accessKey; }
public void setAccessKey(String accessKey) { this.accessKey = accessKey; }
public String getBaseUrl() { return baseUrl; }
public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
public String getAppCode() { return appCode; }
public void setAppCode(String appCode) { this.appCode = appCode; }
}
2. 配置文件 (application.yml)
lovrabet:
access-key: ${LOVRABET_ACCESS_KEY}
base-url: https://runtime.lovrabet.com/openapi
app-code: app-c2dd52a2
3. Service 层
package com.example.service;
import com.lovrabet.runtime.opensdk.client.LovrabetSDKClient;
import com.lovrabet.runtime.opensdk.model.LovrabetRequest;
import com.lovrabet.runtime.opensdk.model.LovrabetResult;
import com.example.config.LovrabetProperties;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class CustomerDataService {
private final LovrabetSDKClient sdkClient;
private final LovrabetProperties properties;
public CustomerDataService(LovrabetSDKClient sdkClient,
LovrabetProperties properties) {
this.sdkClient = sdkClient;
this.properties = properties;
}
/**
* 获取客户列表
*/
public List<Map<String, Object>> getCustomers(int page, int size) {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(properties.getAppCode());
request.setModelCode("b460abdbb0fb49e1865110d9dfbbc9b4");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("currentPage", page);
paramMap.put("pageSize", size);
request.setParamMap(paramMap);
LovrabetResult<?> result = sdkClient.getList(request);
if (result.isSuccess()) {
return (List<Map<String, Object>>) result.getData();
} else {
throw new RuntimeException("查询客户列表失败: " + result.getResultMsg());
}
}
/**
* 创建客户
*/
public String createCustomer(Map<String, Object> customerData) {
LovrabetRequest request = new LovrabetRequest();
request.setAppCode(properties.getAppCode());
request.setModelCode("b460abdbb0fb49e1865110d9dfbbc9b4");
request.setParamMap(customerData);
LovrabetResult<String> result = sdkClient.create(request);
if (result.isSuccess()) {
return result.getData();
} else {
throw new RuntimeException("创建客户失败: " + result.getResultMsg());
}
}
}
4. Controller 层
package com.example.controller;
import com.example.service.CustomerDataService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
private final CustomerDataService customerDataService;
public CustomerController(CustomerDataService customerDataService) {
this.customerDataService = customerDataService;
}
/**
* 获取客户列表
*/
@GetMapping
public List<Map<String, Object>> getCustomers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size
) {
return customerDataService.getCustomers(page, size);
}
/**
* 创建客户
*/
@PostMapping
public String createCustomer(@RequestBody Map<String, Object> customerData) {
return customerDataService.createCustomer(customerData);
}
}
使用示例
启动 Spring Boot 应用后,可以通过 HTTP 接口访问:
# 获取客户列表
curl http://localhost:8080/api/customers?page=1&size=10
# 创建客户
curl -X POST http://localhost:8080/api/customers \
-H "Content-Type: application/json" \
-d '{
"TEXT_1": "客户名称",
"TEXT_2": "138-0000-1234",
"NUMBER_1": 100000
}'
总结
本文档提供了 5 个真实业务场景的完整示例:
- 客户数据同步服务 - 将 CRM 数据同步到 Lovrabet
- 销售漏斗分析看板 - 从 Lovrabet 获取数据并进行分析
- 订单管理系统 - 完整的订单 CRUD 操作
- 定时数据同步任务 - 使用定时任务保持数据一致性
- Spring Boot 集成 - 在现代 Java 框架中使用 SDK
所有示例代码都是完整可运行的,您可以根据实际业务需求进行调整和扩展。
下一步
学习完这些业务场景后,建议按以下顺序继续学习:
-
📖 快速开始 5 分钟完成第一个 CRUD 程序
-
📚 核心概念 深入理解 SDK 工作原理
-
📋 API 参考 查阅完整的接口文档
-
💡 业务示例 ← 当前位置 学习 5 个真实场景的实现
-
🚀 最佳实践 ← 推荐下一步 掌握生产环境优化技巧
-
❓ 常见问题 解决使用中的疑问
需要帮助? 访问 常见问题 或联系 service@lovrabet.com