|
|
|
@ -0,0 +1,341 @@
|
|
|
|
|
package com.ms.api.task;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
import com.doudian.open.api.product_GetRecommendCategory.ProductGetRecommendCategoryRequest;
|
|
|
|
|
import com.doudian.open.api.product_GetRecommendCategory.ProductGetRecommendCategoryResponse;
|
|
|
|
|
import com.doudian.open.api.product_GetRecommendCategory.data.CategoryDetailsItem;
|
|
|
|
|
import com.doudian.open.api.product_GetRecommendCategory.param.ProductGetRecommendCategoryParam;
|
|
|
|
|
import com.doudian.open.api.shop_getShopCategory.ShopGetShopCategoryRequest;
|
|
|
|
|
import com.doudian.open.api.shop_getShopCategory.ShopGetShopCategoryResponse;
|
|
|
|
|
import com.doudian.open.api.shop_getShopCategory.param.ShopGetShopCategoryParam;
|
|
|
|
|
import com.jinritemai.cloud.base.core.util.AuthThreadLocalUtil;
|
|
|
|
|
import com.ms.api.biz.MoveService;
|
|
|
|
|
import com.ms.api.bo.MoveShopSettingBO;
|
|
|
|
|
import com.ms.api.common.Ret;
|
|
|
|
|
import com.ms.api.common.StrObjMap;
|
|
|
|
|
import com.ms.api.common.TaskBaseService;
|
|
|
|
|
import com.ms.api.consts.MoveConst;
|
|
|
|
|
import com.ms.api.service.CategoryService;
|
|
|
|
|
import com.ms.api.service.CategoryShopService;
|
|
|
|
|
import com.ms.api.service.MoveShopSettingService;
|
|
|
|
|
import com.ms.api.service.MoveSystemSourceCategoryService;
|
|
|
|
|
import com.ms.api.tool.CommonTool;
|
|
|
|
|
import com.ms.api.tool.DsJsonRequestTemplate;
|
|
|
|
|
import com.ms.dal.entity.Category;
|
|
|
|
|
import com.ms.dal.entity.MoveShopSetting;
|
|
|
|
|
import com.ms.dal.entity.MoveSystemSourceCategory;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.modelmapper.ModelMapper;
|
|
|
|
|
import org.modelmapper.convention.MatchingStrategies;
|
|
|
|
|
import org.phprpc.util.AssocArray;
|
|
|
|
|
import org.phprpc.util.PHPSerializer;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.Executor;
|
|
|
|
|
import java.util.concurrent.Future;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 到搬家第二步的页面请求
|
|
|
|
|
* 注意,这个和之前的后台任务不同,属于接口的异步处理
|
|
|
|
|
*/
|
|
|
|
|
@Configuration
|
|
|
|
|
@Component
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class MoveToSecondTaskService extends TaskBaseService {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private DsJsonRequestTemplate dsJsonRequestTemplate;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MoveSystemSourceCategoryService moveSystemSourceCategoryService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private CategoryService categoryService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private CategoryShopService categoryShopService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MoveService moveService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MoveShopSettingService moveShopSettingService;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 同时开启任务处理数量, 这里可以开大些,有请求才有跑
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public int getCorePoolSiz() {
|
|
|
|
|
return 50;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 参数需要在线上环境根据实际情况调整
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public int getMaxPoolSize() {
|
|
|
|
|
return 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 这里只排队50个,超过50个会开线程,直到达道maxPoolSize大小
|
|
|
|
|
* 参数需要在线上环境根据实际情况调整
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public int getQueueCapacity() {
|
|
|
|
|
return 50;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 任务管理器名称
|
|
|
|
|
*/
|
|
|
|
|
public String getTaskExecutorName() {
|
|
|
|
|
return "moveToSecondTaskPool";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Bean(name = "moveToSecondTaskPool")
|
|
|
|
|
@Override
|
|
|
|
|
public Executor getAsyncExecutor() {
|
|
|
|
|
return super.getAsyncExecutor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Resource(name = "moveToSecondTaskPool")
|
|
|
|
|
protected Executor taskPool;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected Executor getTaskPool() {
|
|
|
|
|
return taskPool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Ret runParallelTask(Object params) {
|
|
|
|
|
if (ObjectUtil.isEmpty(params)) {
|
|
|
|
|
return CommonTool.failResult("参数不能为空");
|
|
|
|
|
}
|
|
|
|
|
StrObjMap fields = (StrObjMap) params;
|
|
|
|
|
List<String> productIds = (List<String>) fields.get("productIds");
|
|
|
|
|
Long shopId = (Long) fields.get("shopId");
|
|
|
|
|
String authCode = (String) fields.get("authCode");
|
|
|
|
|
int limitNum = 100;
|
|
|
|
|
if (productIds.size() > limitNum) {
|
|
|
|
|
return Ret.fail("最多支持" + limitNum + "个商品");
|
|
|
|
|
}
|
|
|
|
|
List<Object> productInfo = new ArrayList<>();
|
|
|
|
|
List<String> fetchFailIds = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// 并发执行
|
|
|
|
|
ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) getTaskPool();
|
|
|
|
|
List<Future<JSONObject>> futures = new ArrayList<>();
|
|
|
|
|
for (int i = 0; i < productIds.size(); i++) {
|
|
|
|
|
int finalI = i;
|
|
|
|
|
futures.add(taskExecutor.submit(() -> {
|
|
|
|
|
log.info("当前任务运行在线程: " + Thread.currentThread().getName() + "-" + finalI);
|
|
|
|
|
AuthThreadLocalUtil.set(String.valueOf(shopId));
|
|
|
|
|
HashMap<String, Object> mParams = new HashMap<>();
|
|
|
|
|
mParams.put("productId", productIds.get(finalI));
|
|
|
|
|
mParams.put("authCode", authCode);
|
|
|
|
|
String res = null;
|
|
|
|
|
JSONObject resObj = null;
|
|
|
|
|
try {
|
|
|
|
|
res = dsJsonRequestTemplate.execute("/micro_move/get_product_info", mParams);
|
|
|
|
|
resObj = JSON.parseObject(res);
|
|
|
|
|
JSONObject product = resObj.getJSONObject("productInfo");
|
|
|
|
|
Long sourceCategoryId = product.getLong("1688cid");
|
|
|
|
|
// 处理类目
|
|
|
|
|
String sourceCateListStr = StringUtils.join(product.getJSONArray("cateList"), ">");
|
|
|
|
|
log.info("productInfo:::" + sourceCategoryId.toString());
|
|
|
|
|
MoveSystemSourceCategory moveSystemSourceCategory = moveSystemSourceCategoryService.selectBySourceCategoryId(sourceCategoryId.toString());
|
|
|
|
|
if (!ObjectUtil.isEmpty(moveSystemSourceCategory)) {
|
|
|
|
|
PHPSerializer p = new PHPSerializer();
|
|
|
|
|
String content = moveSystemSourceCategory.getMatchCategoryList();
|
|
|
|
|
AssocArray assocArray = (AssocArray) p.unserialize(content.getBytes());
|
|
|
|
|
Map<String, Object> assocMap = assocArrayToHash(assocArray);
|
|
|
|
|
Long categoryId = this.getBestCategoryId(sourceCateListStr, assocMap, shopId);
|
|
|
|
|
if (ObjectUtil.isEmpty(categoryId)) {
|
|
|
|
|
product.put("ddCid", "");
|
|
|
|
|
product.put("ddCategoryList", "");
|
|
|
|
|
} else {
|
|
|
|
|
List<Long> categoryIds = this.getCategoryIdList(categoryId);
|
|
|
|
|
Category category = categoryService.selectByPrimaryKey(categoryId);
|
|
|
|
|
String path = category.getPath();
|
|
|
|
|
List<String> pathArr = Arrays.asList(path.split(">"));
|
|
|
|
|
product.put("ddCid", categoryIds);
|
|
|
|
|
product.put("ddCategoryList", pathArr);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ProductGetRecommendCategoryRequest request = new ProductGetRecommendCategoryRequest();
|
|
|
|
|
ProductGetRecommendCategoryParam param = request.getParam();
|
|
|
|
|
param.setScene("category_infer");
|
|
|
|
|
param.setName(product.getString("title"));
|
|
|
|
|
ProductGetRecommendCategoryResponse response = request.execute();
|
|
|
|
|
List<CategoryDetailsItem> categoryDetails = response.getData().getCategoryDetails();
|
|
|
|
|
if (!ObjectUtil.isEmpty(categoryDetails) && categoryDetails.size() > 0) {
|
|
|
|
|
log.info(categoryDetails.get(0).toString());
|
|
|
|
|
CategoryDetailsItem categoryDetailsItem = categoryDetails.get(0);
|
|
|
|
|
List<Long> categoryIds = new ArrayList<>();
|
|
|
|
|
List<String> pathArr = new ArrayList<>();
|
|
|
|
|
if (categoryDetailsItem.getCategoryDetail().getFirstCid() != 0) {
|
|
|
|
|
categoryIds.add(categoryDetailsItem.getCategoryDetail().getFirstCid());
|
|
|
|
|
}
|
|
|
|
|
if (categoryDetailsItem.getCategoryDetail().getSecondCid() != 0) {
|
|
|
|
|
categoryIds.add(categoryDetailsItem.getCategoryDetail().getSecondCid());
|
|
|
|
|
}
|
|
|
|
|
if (categoryDetailsItem.getCategoryDetail().getFirstCid() != 0) {
|
|
|
|
|
categoryIds.add(categoryDetailsItem.getCategoryDetail().getFirstCid());
|
|
|
|
|
}
|
|
|
|
|
if (categoryDetailsItem.getCategoryDetail().getFourthCid() != 0) {
|
|
|
|
|
categoryIds.add(categoryDetailsItem.getCategoryDetail().getFourthCid());
|
|
|
|
|
}
|
|
|
|
|
if (!categoryDetailsItem.getCategoryDetail().getFirstCname().isEmpty()) {
|
|
|
|
|
pathArr.add(categoryDetailsItem.getCategoryDetail().getFirstCname());
|
|
|
|
|
}
|
|
|
|
|
if (!categoryDetailsItem.getCategoryDetail().getSecondCname().isEmpty()) {
|
|
|
|
|
pathArr.add(categoryDetailsItem.getCategoryDetail().getSecondCname());
|
|
|
|
|
}
|
|
|
|
|
if (!categoryDetailsItem.getCategoryDetail().getThirdCname().isEmpty()) {
|
|
|
|
|
pathArr.add(categoryDetailsItem.getCategoryDetail().getThirdCname());
|
|
|
|
|
}
|
|
|
|
|
if (!categoryDetailsItem.getCategoryDetail().getFourthCname().isEmpty()) {
|
|
|
|
|
pathArr.add(categoryDetailsItem.getCategoryDetail().getFourthCname());
|
|
|
|
|
}
|
|
|
|
|
ShopGetShopCategoryRequest shopRequest = new ShopGetShopCategoryRequest();
|
|
|
|
|
ShopGetShopCategoryParam shopParam = shopRequest.getParam();
|
|
|
|
|
shopParam.setCid(categoryIds.get(categoryIds.size() - 2));
|
|
|
|
|
ShopGetShopCategoryResponse shopReponse = shopRequest.execute();
|
|
|
|
|
if (!ObjectUtil.isEmpty(shopReponse.getData())) {
|
|
|
|
|
product.put("ddCid", categoryIds);
|
|
|
|
|
product.put("ddCategoryList", pathArr);
|
|
|
|
|
} else {
|
|
|
|
|
product.put("ddCid", "");
|
|
|
|
|
product.put("ddCategoryList", "");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
product.put("ddCid", "");
|
|
|
|
|
product.put("ddCategoryList", "");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 处理价格
|
|
|
|
|
Double price = product.getDoubleValue("jd_price");
|
|
|
|
|
JSONObject skuMap = product.getJSONObject("skuMap");
|
|
|
|
|
Double consignPrice = 0D;
|
|
|
|
|
for (String key : skuMap.keySet()) {
|
|
|
|
|
JSONObject item = JSONObject.parseObject(skuMap.get(key).toString());
|
|
|
|
|
Double cPrice = item.getDoubleValue("consignPrice");
|
|
|
|
|
if (cPrice > consignPrice) {
|
|
|
|
|
consignPrice = cPrice;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Objects.isNull(consignPrice)) {
|
|
|
|
|
consignPrice = 0D;
|
|
|
|
|
}
|
|
|
|
|
MoveShopSetting moveShopSetting = moveShopSettingService.getDetailByShopId(shopId);
|
|
|
|
|
ModelMapper modelMapper = new ModelMapper();
|
|
|
|
|
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
|
|
|
|
|
MoveShopSettingBO condition = modelMapper.map(moveShopSetting, MoveShopSettingBO.class);
|
|
|
|
|
if (condition.getAliPriceType().equals(MoveConst.ALI_PRICE_TYPE_CONSIGN) && consignPrice > 0) {
|
|
|
|
|
price = consignPrice;
|
|
|
|
|
}
|
|
|
|
|
double mPrice = moveService.processConditionPrice(condition, price);
|
|
|
|
|
product.put("price", mPrice);
|
|
|
|
|
log.info(res);
|
|
|
|
|
return resObj.getJSONObject("productInfo");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
fetchFailIds.add(productIds.get(finalI));
|
|
|
|
|
log.error("获取商品信息失败,异常:", e);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (Future<JSONObject> future : futures) {
|
|
|
|
|
try {
|
|
|
|
|
JSONObject pInfo = future.get();
|
|
|
|
|
if(ObjectUtil.isNotEmpty(pInfo)){
|
|
|
|
|
productInfo.add(pInfo);
|
|
|
|
|
}
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
log.info("MoveToSecondTaskService get futures exception:", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ret ret = CommonTool.successResult();
|
|
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
|
|
result.put("productList", productInfo);
|
|
|
|
|
result.put("fetchFailIds", fetchFailIds);
|
|
|
|
|
ret.setData(result);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<Long> getCategoryIdList(Long categoryId) {
|
|
|
|
|
List<Long> categoryIdList = new ArrayList<>();
|
|
|
|
|
while (categoryId != 0) {
|
|
|
|
|
Category category = categoryService.selectByPrimaryKey(categoryId);
|
|
|
|
|
categoryIdList.add(categoryId);
|
|
|
|
|
categoryId = Long.valueOf(category.getParentCategoryId());
|
|
|
|
|
}
|
|
|
|
|
Collections.reverse(categoryIdList);
|
|
|
|
|
return categoryIdList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Map assocArrayToHash(AssocArray assocArray) {
|
|
|
|
|
HashMap hashMap = assocArray.toHashMap();
|
|
|
|
|
Map result = new HashMap();
|
|
|
|
|
for (Object key : hashMap.keySet()) {
|
|
|
|
|
if (hashMap.get(key) instanceof AssocArray) {
|
|
|
|
|
result.put(key.toString(), assocArrayToHash((AssocArray) hashMap.get(key)));
|
|
|
|
|
} else if (hashMap.get(key) instanceof byte[]) {
|
|
|
|
|
result.put(key.toString(), new String((byte[]) hashMap.get(key)));
|
|
|
|
|
} else {
|
|
|
|
|
result.put(key.toString(), hashMap.get(key));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log.info(result + "result");
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Long getBestCategoryId(String sourceCateListStr, Map assocMap, Long shopId) {
|
|
|
|
|
Double max = 0.00;
|
|
|
|
|
Long categoryId = null;
|
|
|
|
|
for (Object key : assocMap.keySet()) {
|
|
|
|
|
System.out.println("key:" + key + ", value:" + assocMap.get(key));
|
|
|
|
|
Category category = categoryShopService.getCategoryListByCategoryId(shopId, (Long.valueOf(key.toString())));
|
|
|
|
|
if (!ObjectUtil.isEmpty(category)) {
|
|
|
|
|
Double score = this.getJaroWinklerDistance(sourceCateListStr, category.getPath());
|
|
|
|
|
if (score > max) {
|
|
|
|
|
max = score;
|
|
|
|
|
categoryId = Long.valueOf(key.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return categoryId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double getJaroWinklerDistance(String first, String second) {
|
|
|
|
|
return StringUtils.getJaroWinklerDistance(first, second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object getTask() {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object processTask(Object params) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void clearTask(Object params) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|