记一次ThreadLocal在工作上的妙用
阐述:笔者目前所做的项目是一个跨境电商贸易的项目,最近接到一个需求,原来对接的xx海外供应商现在要增加一个子供应商,简而言之,就是将之前一个供应商一分为二,变成两个供应商,这就比较恶心了,首先要处理大量的数据,涉及到供应商数据,标准商品数据,店铺数据,甚至是各大电商平台的数据的修改,经过测试发现这两个供应商的外部唯一编码id不同,也就是我们常说的spuId不同,考虑到后期该供应商可能会有更多子供应商,经过细思考量之后,最后决定用ThreadLocal来结果不同子供应商的问题
如何使用:
- 建一个ThreadLocal的封装类
public class AtlrContextHolder {
private static final ThreadLocal<Long> CONTEXT_HOLDER = new ThreadLocal<>();
//这里也可以初始化给默认值,
public static Long get() {
return CONTEXT_HOLDER.get();
}
public static void set(Long supplierId) { CONTEXT_HOLDER.set(supplierId); }
}
- 在定时获取供应商数据的时候将供应商信息设置进去
@XxlJob("refreshMinettiAllItem")
public ReturnT<String> refreshMinettiAllItem(String args) {
log.info("全量更新Minetti商品,管理上下架,更新所有属性");
try{
AtlrContextHolder.set(Supplier.SupplierEnum.MINETT.getSupplierId());
strategyService.dealSupplier(SupplierTypeEnum.ATTELIER.getKey());
}catch (Exception e){
e.printStackTrace();
log.info("全量刷新Minetti失败");
return ReturnT.FAIL;
}
return ReturnT.SUCCESS;
}
/**
* Creative全量更新
*/
@XxlJob("refreshCreativeAllItem")
public ReturnT<String> refreshCreativeAllItem(String args) {
log.info("全量更新Creative商品,管理上下架,更新所有属性");
try{
AtlrContextHolder.set(Supplier.SupplierEnum.CREATIVE.getSupplierId());
strategyService.dealSupplier(SupplierTypeEnum.ATTELIER.getKey());
}catch (Exception e){
e.printStackTrace();
log.info("全量刷新Creative失败");
return ReturnT.FAIL;
}
return ReturnT.SUCCESS;
}
3.最后在真正执行业务的时候从threadlocal中获取就可以了
goodsList = atlrAPI.getGoodsList(round, 1000, null, Supplier.getEnumBySupplierId(AtlrContextHolder.get()).getName());
由此可以解决无论该供应商新增多少子供应商,都能从容的解决,即没有太大改动原来的代码,又符合开闭原则,threadlocal还是用的比较妙的,可能会有人问,不可以直接传入进去? 笔者代码这里都是顶级接口限制了空参,如果改动,将会涉及所有供应商都需要传入这个看似无用的参数。不是所有供应商都需要传入这个参数