一,用作车辆属性检查,车架号检查、车辆id检车、sku检查、场站检查、车辆sku检查
1.入口为定时任务触发,es车辆属性检查
package com.dst.common.job;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dst.common.util.checkEsData.AttributesCheckHandler;
import com.dst.common.util.checkEsData.CarIdCheckHandler;
import com.dst.common.util.checkEsData.CheckHandler;
import com.dst.common.util.checkEsData.SpuCodeCheckHandler;
import com.dst.common.util.checkEsData.StandardSkuCodeCheckHandler;
import com.dst.common.util.checkEsData.StationIdCheckHandler;
import com.dst.common.util.checkEsData.VinCodeCheckHandler;
import com.dst.modules.business.carinventory.service.IEsQueryService;
import com.dst.modules.business.vehicle.service.OperatingAttrManageService;
import com.dst.modules.business.vehicle.service.OperatingNewCarService;
import com.dst.modules.extend.GoodsAttributeServiceImpl;
import com.dstcar.common.utils.string.StringUtil;
import com.dstcar.entitys.goods.attributegroup.AttributeGroupAttrOut;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseDTO;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import com.dstcar.entitys.operating.newcar.OperatingNewCarViewListQuery;
import com.dstcar.entitys.operating.vehicleattr.attr.VehicleAttrManageDTO;
import com.dstcar.entitys.operating.vehicleattr.attr.VehicleAttrManageQuery;
import com.github.pagehelper.PageInfo;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import static java.util.stream.Collectors.toList;
/**
* 定时任务检查数据库中的数据和es中的数据不一致
*
* @author liu wei ping
* @version 1.0
* @date 2022-06-30 11:27:29
*/
@JobHandler("carInfoMatchEsJob")
@Component
@Slf4j
public class CarInfoMatchEsJob extends IJobHandler {
@Autowired
private OperatingNewCarService operatingNewCarService;
@Autowired
private IEsQueryService esQueryService;
@Autowired
private GoodsAttributeServiceImpl goodsAttributeService;
@Autowired
private OperatingAttrManageService operatingAttrManageService;
@Override
public ReturnT<String> execute(String param) throws Exception {
try {
List<AttributeGroupAttrOut> configSkuAttrList = goodsAttributeService.getGroupAttrListByKey();
List<String> configSkuAttrIdList =
configSkuAttrList.stream().map(AttributeGroupAttrOut::getAttrId).collect(toList());
OperatingNewCarViewListQuery query = new OperatingNewCarViewListQuery();
query.setPageSize(200);
query.setPageNum(1);
// 查在库库存
query.setStationId(-1);
PageInfo<OperatingNewCarBaseDTO> basicCarPageInfo =
operatingNewCarService.getOperatingNewCarBaseListPage(query);
Set<String> vinCodes =
basicCarPageInfo.getList().stream().map(OperatingNewCarBaseDTO::getVinCode).collect(Collectors.toSet());
// 只查车与sku定义相关的一些属性
Map<String, List<VehicleAttrManageDTO>> vinAttrMap = getVinCodeAttrListMap(configSkuAttrIdList, vinCodes);
List<EsVehicleInfo> esInfos = esQueryService.getEsVehicleInfoByVinCodes(new ArrayList<>(vinCodes), 0, 200);
List<OperatingNewCarBaseWithAttrDTO> attrDTOList = getOperatingNewCarBaseWithAttrs(basicCarPageInfo,
vinAttrMap);
// 比较结果(以数据库为准) ,比较carId,carNo,standardSkuCode,spuCode,stationId,attributes
checkInfoWithEs(attrDTOList, esInfos);
for (int j = 2; j <= basicCarPageInfo.getPages(); j++) {
query.setPageNum(j);
basicCarPageInfo = operatingNewCarService.getOperatingNewCarBaseListPage(query);
vinCodes =
basicCarPageInfo.getList().stream().map(OperatingNewCarBaseDTO::getVinCode).collect(Collectors.toSet());
esInfos = esQueryService.getEsVehicleInfoByVinCodes(new ArrayList<>(vinCodes),0,200);
vinAttrMap = getVinCodeAttrListMap(configSkuAttrIdList, vinCodes);
attrDTOList = getOperatingNewCarBaseWithAttrs(basicCarPageInfo, vinAttrMap);
// 校验数据
checkInfoWithEs(attrDTOList, esInfos);
log.info("车辆SKU数据库数据与ES数据校验第 {} 页完成...", j);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return ReturnT.SUCCESS;
} catch (Exception e) {
XxlJobLogger.log("定时任务检查数据库中的数据和es中的数据不一致报错: " + e.getMessage());
}
return ReturnT.FAIL;
}
private List<OperatingNewCarBaseWithAttrDTO> getOperatingNewCarBaseWithAttrs(PageInfo<OperatingNewCarBaseDTO> basicCarPageInfo, Map<String, List<VehicleAttrManageDTO>> vinAttrMap) {
List<OperatingNewCarBaseWithAttrDTO> attrDTOList =
basicCarPageInfo.getList().stream().map(OperatingNewCarBaseDTO::toChild).collect(toList());
attrDTOList.forEach(vo -> vo.setAttrs(vinAttrMap.get(vo.getVinCode())));
return attrDTOList;
}
private Map<String, List<VehicleAttrManageDTO>> getVinCodeAttrListMap(List<String> configSkuAttrIdList,
Set<String> vinCodes) {
List<VehicleAttrManageDTO> skuAttrs =
operatingAttrManageService.find(VehicleAttrManageQuery.builder()
.attrIds(configSkuAttrIdList)
.vinCodes(new ArrayList<>(vinCodes))
.build());
return skuAttrs.stream().collect(Collectors.groupingBy(VehicleAttrManageDTO::getVinCode));
}
private void checkInfoWithEs(List<OperatingNewCarBaseWithAttrDTO> cars, List<EsVehicleInfo> esInfos) {
if (CollectionUtils.isEmpty(cars)) {
return;
}
CheckHandler.Builder<OperatingNewCarBaseWithAttrDTO> builder = new CheckHandler.Builder<>();
builder.addHandler(new VinCodeCheckHandler())
.addHandler(new CarIdCheckHandler())
.addHandler(new StandardSkuCodeCheckHandler())
.addHandler(new SpuCodeCheckHandler())
.addHandler(new StationIdCheckHandler())
.addHandler(new AttributesCheckHandler());
StringBuilder stringBuilder;
for (OperatingNewCarBaseWithAttrDTO baseDTO : cars) {
stringBuilder = new StringBuilder();
builder.build().doCheck(baseDTO, esInfos, stringBuilder);
if(!StringUtil.isEmpty(stringBuilder.toString())){
stringBuilder.insert(0,"vinCode["+baseDTO.getVinCode()+"]");
log.error(stringBuilder.toString());
}
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import java.util.List;
/**
* @author liu wei ping
* @version 1.0
* @date 2022-06-30 18:10:06
*/
public abstract class CheckHandler<T> {
protected CheckHandler<T> next;
private void next(CheckHandler<T> next) {
this.next = next;
}
/**
* 校验
*
* @param baseDTO 实体
* @param esInfos es中的数据
* @param stringBuilder stringBuilder
*/
public abstract void doCheck(T baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder);
public static class Builder<T> {
private CheckHandler<T> head;
private CheckHandler<T> tail;
public Builder<T> addHandler(CheckHandler<T> handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public CheckHandler<T> build() {
return this.head;
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* 车架号校验
*
* @author liu wei ping
* @version 1.0
* @date 2022-06-30 18:30:45
*/
public class VinCodeCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
List<String> vinCodes = esInfos.stream().map(EsVehicleInfo::getVinCode).collect(toList());
if (!vinCodes.contains(baseDTO.getVinCode())) {
// 车架号不存在不往下校验了
stringBuilder.append("vinCode ").append("does not exit in es");
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* @author liu wei ping
* @version 1.0
* @date 2022-06-30 18:41:49
*/
public class CarIdCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
Optional<? extends EsVehicleInfo> info =
esInfos.stream().filter(esInfo -> esInfo.getVinCode().equals(baseDTO.getVinCode())).findFirst();
if (info.isPresent() && !info.get().getCarId().equals(baseDTO.getCarId())) {
stringBuilder.append("carId is different in es,in fact it is :").append(baseDTO.getCarId()).append("but " +
"in es it is :").append(info.get().getCarId());
}
if (Objects.nonNull(next)) {
next.doCheck(baseDTO, esInfos, stringBuilder);
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* 标准sku编码校验
*
* @author liu wei ping
* @version 1.0
* @date 2022-07-01 10:26:39
*/
public class StandardSkuCodeCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
Optional<? extends EsVehicleInfo> info =
esInfos.stream().filter(esInfo -> esInfo.getVinCode().equals(baseDTO.getVinCode())).findFirst();
if (info.isPresent() && !info.get().getStandardSkuCode().equals(baseDTO.getStandardSkuCode())) {
stringBuilder.append("standardSkuCode is different in es,in fact it is :").append(baseDTO.getStandardSkuCode()).append(
"but " +
"in es it is :").append(info.get().getStandardSkuCode());
}
if (Objects.nonNull(next)) {
next.doCheck(baseDTO, esInfos, stringBuilder);
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* spuCode校验
*
* @author liu wei ping
* @version 1.0
* @date 2022-07-01 10:28:17
*/
public class SpuCodeCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
Optional<? extends EsVehicleInfo> info =
esInfos.stream().filter(esInfo -> esInfo.getVinCode().equals(baseDTO.getVinCode())).findFirst();
if (info.isPresent() && !info.get().getSpuCode().equals(baseDTO.getSpuCode())) {
stringBuilder.append("spuCode is different in es,in fact it is :").append(baseDTO.getSkuCode()).append(
"but " +
"in es it is :").append(info.get().getSpuCode());
}
if (Objects.nonNull(next)) {
next.doCheck(baseDTO, esInfos, stringBuilder);
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* 场站id 校验
*
* @author liu wei ping
* @version 1.0
* @date 2022-07-01 10:30:22
*/
public class StationIdCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
Optional<? extends EsVehicleInfo> info =
esInfos.stream().filter(esInfo -> esInfo.getVinCode().equals(baseDTO.getVinCode())).findFirst();
if (info.isPresent() && !info.get().getStationId().equals(baseDTO.getStationId())) {
stringBuilder.append("stationId is different in es,in fact it is :").append(baseDTO.getStationId()).append(
"but " +
"in es it is :").append(info.get().getStationId());
}
if (Objects.nonNull(next)) {
next.doCheck(baseDTO, esInfos, stringBuilder);
}
}
}
package com.dst.common.util.checkEsData;
import com.dst.common.entitys.es.EsVehicleInfo;
import com.dstcar.common.utils.string.StringUtil;
import com.dstcar.entitys.operating.newcar.OperatingNewCarBaseWithAttrDTO;
import com.dstcar.entitys.operating.vehicleattr.attr.VehicleAttrManageDTO;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 属性比较
*
* @author liu wei ping
* @version 1.0
* @date 2022-07-01 10:32:41
*/
public class AttributesCheckHandler extends CheckHandler<OperatingNewCarBaseWithAttrDTO> {
@Override
public void doCheck(OperatingNewCarBaseWithAttrDTO baseDTO, List<? extends EsVehicleInfo> esInfos,
StringBuilder stringBuilder) {
Optional<? extends EsVehicleInfo> info =
esInfos.stream().filter(esInfo -> esInfo.getVinCode().equals(baseDTO.getVinCode())).findFirst();
List<VehicleAttrManageDTO> attrs = baseDTO.getAttrs();
Map<String, VehicleAttrManageDTO> attrMap = attrs.stream()
.collect(Collectors.toMap(VehicleAttrManageDTO::getAttrId, Function.identity()));
if (info.isPresent()) {
// ES 中的属性map 的格式为 attrId:attrValueId/attrValueName(针对手动输入的属性)
Map<String, Object> infoAttrMap = info.get().getAttributes();
for (Map.Entry<String, VehicleAttrManageDTO> entry : attrMap.entrySet()) {
// 分情况, 当attrValueId 不为空则比较attrValueId 否则就比较attrValueName
if (!StringUtil.isEmpty(entry.getValue()) && !infoAttrMap.get(entry.getKey()).equals(entry.getValue())) {
stringBuilder.append("attribute is different in es,attrId is")
.append(entry.getKey())
.append(" attrName is ")
.append(entry.getValue().getAttrName())
.append("value in es is")
.append(infoAttrMap.get(entry.getKey()))
.append("value in db is ")
.append(entry.getValue().getAttrValueId());
}
if (StringUtil.isEmpty(entry.getValue()) && !infoAttrMap.get(entry.getKey()).equals(entry.getValue())) {
stringBuilder.append("attribute is different in es,attrId is")
.append(entry.getKey())
.append(" attrName is ")
.append(entry.getValue().getAttrName())
.append("value in es is")
.append(infoAttrMap.get(entry.getKey()))
.append("value in db is ")
.append(entry.getValue().getAttrValueName());
}
}
}
if (Objects.nonNull(next)) {
next.doCheck(baseDTO, esInfos, stringBuilder);
}
}
}
2.使用责任链模式,加入链表结构,让检查方法顺序检查。