11 changed files with 391 additions and 29 deletions
@ -0,0 +1,268 @@ |
|||||
|
package cc.hiver.mall.utils; |
||||
|
|
||||
|
import cc.hiver.core.common.redis.RedisTemplateHelper; |
||||
|
import cc.hiver.mall.entity.MallOrderGroup; |
||||
|
import cc.hiver.mall.pojo.vo.MallOrderVO; |
||||
|
import cn.hutool.json.JSONUtil; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 商家待成团订单缓存工具类 |
||||
|
* <p> |
||||
|
* 底层使用 Redis Hash 结构,保证按 shopId + orderId 维度的 O(1) 读写效率。 |
||||
|
* <pre> |
||||
|
* Key = SHOP_GROUP_ORDERS:{shopId} |
||||
|
* Field = orderId |
||||
|
* Value = MallOrderGroup 的 JSON 序列化 |
||||
|
* </pre> |
||||
|
* <p> |
||||
|
* 使用场景:订单状态发生变化时(创建、更新、取消、完成等), |
||||
|
* 由业务方主动调用本工具类的方法维护缓存,以减少 getMallOrderGroupByShopId 接口对数据库的查询压力。 |
||||
|
* |
||||
|
* @author system |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Component |
||||
|
public class ShopGroupOrderCacheUtil { |
||||
|
|
||||
|
/** Redis Key 前缀 */ |
||||
|
private static final String KEY_PREFIX = "SHOP_GROUP_ORDERS:"; |
||||
|
|
||||
|
/** 订单不再属于"待成团"的状态集合 */ |
||||
|
private static final int STATUS_DONE = 0; |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisTemplateHelper redisTemplateHelper; |
||||
|
|
||||
|
// ================================================================
|
||||
|
// Key 构建
|
||||
|
// ================================================================
|
||||
|
|
||||
|
private String buildKey(String shopId) { |
||||
|
return KEY_PREFIX + shopId; |
||||
|
} |
||||
|
|
||||
|
// ================================================================
|
||||
|
// 存放(put)
|
||||
|
// ================================================================
|
||||
|
|
||||
|
/** |
||||
|
* 存放单个订单到缓存 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @param orderVO 订单VO(必须包含有效的 id) |
||||
|
*/ |
||||
|
public void put(String shopId, MallOrderGroup orderVO) { |
||||
|
if (StringUtils.isBlank(shopId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { |
||||
|
log.info("UserPendingOrderCacheUtil.put 参数无效, userId={}, orderVO={}", shopId, orderVO); |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
String key = buildKey(shopId); |
||||
|
String json = JSONUtil.toJsonStr(orderVO); |
||||
|
redisTemplateHelper.hPut(key, orderVO.getId(), json); |
||||
|
log.info("缓存店铺待成团订单: shopId={}, orderId={}", shopId, orderVO.getId()); |
||||
|
} catch (Exception e) { |
||||
|
log.info("缓存店铺待成团订单失败: shopId={}, orderId={}", shopId, orderVO.getId(), e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量存放订单到缓存(通常用于缓存预热 / 首次加载) |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @param orders 订单列表 |
||||
|
*/ |
||||
|
public void putAll(String shopId, List<MallOrderGroup> orders) { |
||||
|
if (StringUtils.isBlank(shopId) || orders == null || orders.isEmpty()) { |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
String key = buildKey(shopId); |
||||
|
Map<String, String> map = new java.util.LinkedHashMap<>(orders.size()); |
||||
|
for (MallOrderGroup order : orders) { |
||||
|
if (order != null && StringUtils.isNotBlank(order.getId())) { |
||||
|
map.put(order.getId(), JSONUtil.toJsonStr(order)); |
||||
|
} |
||||
|
} |
||||
|
if (!map.isEmpty()) { |
||||
|
redisTemplateHelper.hPutAll(key, map); |
||||
|
log.info("批量缓存店铺待成团订单: shopId={}, count={}", shopId, map.size()); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.info("批量缓存店铺待成团订单失败: shopId={}", shopId, e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ================================================================
|
||||
|
// 删除(remove)
|
||||
|
// ================================================================
|
||||
|
|
||||
|
/** |
||||
|
* 根据 shopId 和 orderId 从缓存中删除指定订单 |
||||
|
* <p> |
||||
|
* 典型场景:订单成团、取消、退款成功后调用。 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @param orderId 订单ID |
||||
|
*/ |
||||
|
public void remove(String shopId, String orderId) { |
||||
|
if (StringUtils.isBlank(shopId) || StringUtils.isBlank(orderId)) { |
||||
|
log.info("UserPendingOrderCacheUtil.remove 参数无效, shopId={}, orderId={}", shopId, orderId); |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
String key = buildKey(shopId); |
||||
|
redisTemplateHelper.hDelete(key, orderId); |
||||
|
log.info("删除待成团订单缓存: shopId={}, orderId={}", shopId, orderId); |
||||
|
} catch (Exception e) { |
||||
|
log.info("删除待成团订单缓存失败: shopId={}, orderId={}", shopId, orderId, e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 清除指定店铺所有待成团订单缓存 |
||||
|
* <p> |
||||
|
* 典型场景:需要强制刷新该店铺缓存时调用。 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
*/ |
||||
|
public void removeAll(String shopId) { |
||||
|
if (StringUtils.isBlank(shopId)) { |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
redisTemplateHelper.delete(buildKey(shopId)); |
||||
|
log.info("清除店铺待成团订单缓存: shopId={}", shopId); |
||||
|
} catch (Exception e) { |
||||
|
log.info("清除店铺待成团订单缓存失败: shopId={}", shopId, e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ================================================================
|
||||
|
// 更新(update)
|
||||
|
// ================================================================
|
||||
|
|
||||
|
/** |
||||
|
* 根据 shopId 和 orderId 更新缓存中的订单信息 |
||||
|
* <p> |
||||
|
* 如果更新后的订单状态已经不属于"待完成"(status ∈ {10}), |
||||
|
* 则自动从缓存中移除该订单,无需调用方额外判断。 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @param orderVO 更新后的订单VO |
||||
|
*/ |
||||
|
public void update(String shopId, MallOrderGroup orderVO) { |
||||
|
if (StringUtils.isBlank(shopId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) { |
||||
|
log.warn("UserPendingOrderCacheUtil.update 参数无效, shopId={}, orderVO={}", shopId, orderVO); |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
// 如果订单状态已不属于待成团,直接删除
|
||||
|
/*if (!isTerminalStatus(orderVO.getStatus())) { |
||||
|
remove(shopId, orderVO.getId()); |
||||
|
log.debug("订单已终态,从缓存移除: shopId={}, orderId={}, status={}", |
||||
|
shopId, orderVO.getId(), orderVO.getStatus()); |
||||
|
return; |
||||
|
}*/ |
||||
|
// 覆盖更新
|
||||
|
put(shopId, orderVO); |
||||
|
log.info("更新店铺待成团缓存: shopId={}, orderId={}, status={}", |
||||
|
shopId, orderVO.getId(), orderVO.getStatus()); |
||||
|
} catch (Exception e) { |
||||
|
log.info("更新用户待完成订单缓存失败: shopId={}, orderId={}", shopId, orderVO.getId(), e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ================================================================
|
||||
|
// 查询(get)
|
||||
|
// ================================================================
|
||||
|
|
||||
|
/** |
||||
|
* 获取店铺待成团订单缓存 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @return 缓存的订单列表,缓存不存在时返回 null(调用方可据此判断是否需要回源查库) |
||||
|
*/ |
||||
|
public List<MallOrderGroup> getAll(String shopId) { |
||||
|
if (StringUtils.isBlank(shopId)) { |
||||
|
return null; |
||||
|
} |
||||
|
try { |
||||
|
String key = buildKey(shopId); |
||||
|
Map<Object, Object> entries = redisTemplateHelper.hGetAll(key); |
||||
|
if (entries == null || entries.isEmpty()) { |
||||
|
return null; |
||||
|
} |
||||
|
List<MallOrderGroup> result = new ArrayList<>(entries.size()); |
||||
|
for (Object value : entries.values()) { |
||||
|
if (value != null) { |
||||
|
result.add(JSONUtil.toBean(value.toString(), MallOrderGroup.class)); |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} catch (Exception e) { |
||||
|
log.info("获取店铺待成团订单缓存失败: shopId={}", shopId, e); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取店铺缓存待成团单个订单 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @param orderId 订单ID |
||||
|
* @return 缓存的订单VO,不存在时返回 null |
||||
|
*/ |
||||
|
public MallOrderVO get(String shopId, String orderId) { |
||||
|
if (StringUtils.isBlank(shopId) || StringUtils.isBlank(orderId)) { |
||||
|
return null; |
||||
|
} |
||||
|
try { |
||||
|
String key = buildKey(shopId); |
||||
|
Object value = redisTemplateHelper.hGet(key, orderId); |
||||
|
if (value == null) { |
||||
|
return null; |
||||
|
} |
||||
|
return JSONUtil.toBean(value.toString(), MallOrderVO.class); |
||||
|
} catch (Exception e) { |
||||
|
log.info("获取店铺单个待成团订单缓存失败: shopId={}, orderId={}", shopId, orderId, e); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断该店铺的缓存是否已存在 |
||||
|
* |
||||
|
* @param shopId 店铺ID |
||||
|
* @return true 表示缓存存在 |
||||
|
*/ |
||||
|
public boolean exists(String shopId) { |
||||
|
if (StringUtils.isBlank(shopId)) { |
||||
|
return false; |
||||
|
} |
||||
|
Boolean hasKey = redisTemplateHelper.hasKey(buildKey(shopId)); |
||||
|
return hasKey != null && hasKey; |
||||
|
} |
||||
|
|
||||
|
// ================================================================
|
||||
|
// 内部工具
|
||||
|
// ================================================================
|
||||
|
|
||||
|
/** |
||||
|
* 判断订单状态是否为终态(不再属于"待成团") |
||||
|
*/ |
||||
|
private boolean isTerminalStatus(Integer status) { |
||||
|
if (status == null) { |
||||
|
return false; |
||||
|
} |
||||
|
return status == STATUS_DONE; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue