merge origin master

This commit is contained in:
paulGao 2021-11-03 15:29:48 +08:00
commit c85caab197
38 changed files with 348 additions and 298 deletions

View File

@ -43,21 +43,21 @@ https://docs.pickmall.cn
### 💧 开源商城项目地址(gitee)
**Java后台商城所有API**https://gitee.com/beijing_hongye_huicheng/lilishop.git
**API商城所有API**https://gitee.com/beijing_hongye_huicheng/lilishop.git
**UI商城管理端/商家端/买家PC端** https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
**Uni-app商城移动端支持小程序/APP/H5**https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
**uniapp商城移动端支持小程序/APP/H5**https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
**docker一键部署商城部署脚本**https://gitee.com/beijing_hongye_huicheng/docker.git
### 💧 开源商城项目地址(github)
**Java后台商城所有API**https://github.com/hongyehuicheng/lilishop.git
**API商城所有API**https://github.com/hongyehuicheng/lilishop.git
**UI商城管理端/商家端/买家PC端** https://github.com/hongyehuicheng/lilishop-ui.git
**Uni-app商城移动端支持小程序/APP/H5**https://github.com/hongyehuicheng/lilishop-uniapp.git
**uniapp商城移动端支持小程序/APP/H5**https://github.com/hongyehuicheng/lilishop-uniapp.git
**docker一键部署商城部署脚本**https://github.com/hongyehuicheng/docker.git

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<!--日志文件保存路径-->
<springProperty scope="context" name="LOG_FILE_PATH" source="logging.file.path"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 配置elk日志收集 配饰的是 LOGSTASH 的地址-->
<destination>127.0.0.1:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@ -1,8 +1,6 @@
package cn.lili.controller.passport;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dto.MemberEditDTO;
@ -47,11 +45,8 @@ public class MemberBuyerController {
public ResultMessage<Object> userLogin(@NotNull(message = "用户名不能为空") @RequestParam String username,
@NotNull(message = "密码不能为空") @RequestParam String password,
@RequestHeader String uuid) {
if (verificationService.check(uuid, VerificationEnums.LOGIN)) {
return ResultUtil.data(this.memberService.usernameLogin(username, password));
} else {
throw new ServiceException(ResultCode.VERIFICATION_ERROR);
}
verificationService.check(uuid, VerificationEnums.LOGIN);
return ResultUtil.data(this.memberService.usernameLogin(username, password));
}
@ApiOperation(value = "短信登录接口")
@ -63,11 +58,8 @@ public class MemberBuyerController {
public ResultMessage<Object> smsLogin(@NotNull(message = "手机号为空") @RequestParam String mobile,
@NotNull(message = "验证码为空") @RequestParam String code,
@RequestHeader String uuid) {
if (smsUtil.verifyCode(mobile, VerificationEnums.LOGIN, uuid, code)) {
return ResultUtil.data(memberService.mobilePhoneLogin(mobile));
} else {
throw new ServiceException(ResultCode.VERIFICATION_SMS_ERROR);
}
smsUtil.verifyCode(mobile, VerificationEnums.LOGIN, uuid, code);
return ResultUtil.data(memberService.mobilePhoneLogin(mobile));
}
@ApiOperation(value = "注册用户")
@ -84,12 +76,9 @@ public class MemberBuyerController {
@RequestHeader String uuid,
@NotNull(message = "验证码不能为空") @RequestParam String code) {
boolean result = smsUtil.verifyCode(mobilePhone, VerificationEnums.REGISTER, uuid, code);
if (result) {
return ResultUtil.data(memberService.register(username, password, mobilePhone));
} else {
throw new ServiceException(ResultCode.VERIFICATION_SMS_ERROR);
}
smsUtil.verifyCode(mobilePhone, VerificationEnums.REGISTER, uuid, code);
return ResultUtil.data(memberService.register(username, password, mobilePhone));
}
@ApiOperation(value = "获取当前登录用户接口")
@ -109,13 +98,11 @@ public class MemberBuyerController {
@NotNull(message = "验证码为空") @RequestParam String code,
@RequestHeader String uuid) {
//校验短信验证码是否正确
if (smsUtil.verifyCode(mobile, VerificationEnums.FIND_USER, uuid, code)) {
//校验是否通过手机号可获取会员,存在则将会员信息存入缓存有效时间3分钟
if (memberService.findByMobile(uuid, mobile)) {
return ResultUtil.success();
}
}
throw new ServiceException(ResultCode.VERIFICATION_ERROR);
smsUtil.verifyCode(mobile, VerificationEnums.FIND_USER, uuid, code);
//校验是否通过手机号可获取会员,存在则将会员信息存入缓存有效时间3分钟
memberService.findByMobile(uuid, mobile);
return ResultUtil.success();
}
@ApiOperation(value = "修改密码")

View File

@ -121,7 +121,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: false
show: true
# 忽略TOKEN 鉴权 的url
ignored:

View File

@ -1,12 +1,10 @@
package cn.lili.controller.common;
import cn.lili.cache.limit.annotation.LimitPoint;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.verification.enums.VerificationEnums;
import cn.lili.modules.verification.service.VerificationService;
import cn.lili.common.vo.ResultMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@ -32,14 +30,8 @@ public class SliderImageController {
@GetMapping("/{verificationEnums}")
@ApiOperation(value = "获取校验接口,一分钟同一个ip请求10次")
public ResultMessage getSliderImage(@RequestHeader String uuid, @PathVariable VerificationEnums verificationEnums) {
try {
return ResultUtil.data(verificationService.createVerification(verificationEnums, uuid));
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("获取校验接口错误", e);
throw new ServiceException(ResultCode.VERIFICATION_EXIST);
}
return ResultUtil.data(verificationService.createVerification(verificationEnums, uuid));
}
@LimitPoint(name = "slider_image", key = "verification_pre_check", limit = 600)

View File

@ -2,12 +2,11 @@ package cn.lili.controller.common;
import cn.lili.cache.limit.annotation.LimitPoint;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.system.sms.SmsUtil;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.system.sms.SmsUtil;
import cn.lili.modules.verification.enums.VerificationEnums;
import cn.lili.modules.verification.service.VerificationService;
import cn.lili.common.vo.ResultMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -42,11 +41,8 @@ public class SmsController {
@RequestHeader String uuid,
@PathVariable String mobile,
@PathVariable VerificationEnums verificationEnums) {
if (verificationService.check(uuid, verificationEnums)) {
smsUtil.sendSmsCode(mobile, verificationEnums, uuid);
return ResultUtil.success(ResultCode.VERIFICATION_SEND_SUCCESS);
} else {
throw new ServiceException(ResultCode.VERIFICATION_SMS_EXPIRED_ERROR);
}
verificationService.check(uuid, verificationEnums);
smsUtil.sendSmsCode(mobile, verificationEnums, uuid);
return ResultUtil.success(ResultCode.VERIFICATION_SEND_SUCCESS);
}
}

View File

@ -118,7 +118,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: false
show: true
# 忽略鉴权url
ignored:

View File

@ -182,7 +182,6 @@ mybatis-plus:
# 日志
logging:
config: classpath:logback-spring.xml
# 输出级别
level:
cn.lili: info
@ -230,11 +229,11 @@ lili:
system:
isDemoSite: false
isTestModel: true
# 脱敏级别:
# 0不做脱敏处理
# 1管理端用户手机号等信息脱敏
# 2商家端信息脱敏为2时表示管理端商家端同时脱敏
# sensitiveLevel: 2
# 脱敏级别:
# 0不做脱敏处理
# 1管理端用户手机号等信息脱敏
# 2商家端信息脱敏为2时表示管理端商家端同时脱敏
# sensitiveLevel: 2
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数

View File

@ -121,7 +121,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: false
show: true
# 忽略鉴权url
ignored:

View File

@ -89,7 +89,7 @@ public interface Cache<T> {
*
* @param key 缓存key
*/
void remove(Object key);
Boolean remove(Object key);
/**
* 删除

View File

@ -78,9 +78,9 @@ public class RedisCache implements Cache {
}
@Override
public void remove(Object key) {
public Boolean remove(Object key) {
redisTemplate.delete(key);
return redisTemplate.delete(key);
}
/**

View File

@ -99,7 +99,8 @@ public enum ResultCode {
BRAND_DISABLE_ERROR(14003, "品牌禁用失败"),
BRAND_DELETE_ERROR(14004, "品牌删除失败"),
BRAND_NAME_EXIST_ERROR(20002, "品牌名称重复!"),
BRAND_USE_DISABLE_ERROR(20003, "分类已经绑定此品牌,请先解除关联"),
BRAND_USE_DISABLE_ERROR(20003, "分类已经绑定品牌,请先解除关联"),
BRAND_BIND_GOODS_ERROR(20005, "品牌已经绑定商品,请先解除关联"),
BRAND_NOT_EXIST(20004, "品牌不存在"),
/**
@ -154,7 +155,7 @@ public enum ResultCode {
* 购物车
*/
CART_ERROR(30001, "读取结算页的购物车异常"),
CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动不存在错误"),
CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动已关闭,请稍后重试"),
CART_PINTUAN_LIMIT_ERROR(30003, "购买数量超过拼团活动限制数量"),
SHIPPING_NOT_APPLY(30005, "购物商品不支持当前收货地址配送"),
@ -240,7 +241,7 @@ public enum ResultCode {
* 活动
*/
PROMOTION_GOODS_NOT_EXIT(40000, "当前促销商品不存在!"),
PROMOTION_SAME_ACTIVE_EXIST(40001, "当前时间内已存在同类活动"),
PROMOTION_SAME_ACTIVE_EXIST(40001, "活动时间内已存在同类活动,请选择关闭、删除当前时段的活动"),
PROMOTION_START_TIME_ERROR(40002, "活动起始时间不能小于当前时间"),
PROMOTION_END_TIME_ERROR(40003, "活动结束时间不能小于当前时间"),
PROMOTION_TIME_ERROR(40004, "活动起始时间必须大于结束时间"),
@ -425,8 +426,8 @@ public enum ResultCode {
*/
VERIFICATION_SEND_SUCCESS(80201, "短信验证码,发送成功"),
VERIFICATION_ERROR(80202, "验证失败"),
VERIFICATION_SMS_ERROR(80203, "短信验证码错误,请重新校验"),
VERIFICATION_SMS_EXPIRED_ERROR(80204, "验证码已失效,请重新校验"),
VERIFICATION_CODE_INVALID(80204, "验证码已失效,请重新校验"),
VERIFICATION_SMS_CHECKED_ERROR(80210, "短信验证码错误,请重新校验"),
/**
* 微信相关异常
@ -449,9 +450,8 @@ public enum ResultCode {
CUSTOM_WORDS_SECRET_KEY_ERROR(90002, "秘钥验证失败!"),
CONNECT_NOT_EXIST(90000, "登录方式不存在!"),
ELASTICSEARCH_INDEX_INIT_ERROR(90003, "索引初始化失败!"),
PURCHASE_ORDER_DEADLINE_ERROR(90004,"供求单,已超过报名截止时间")
;
PURCHASE_ORDER_DEADLINE_ERROR(90004, "供求单,已超过报名截止时间"),
INDEX_BUILDING(90005, "索引正在生成");
private final Integer code;
private final String message;

View File

@ -2,16 +2,20 @@ package cn.lili.common.exception;
import cn.lili.common.enums.ResultCode;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 全局业务异常类
*
* @author Chopper
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class ServiceException extends RuntimeException {
public static String DEFAULT_MESSAGE = "网络错误,请稍后重试!";
private static final long serialVersionUID = 3447728300174142127L;
public static final String DEFAULT_MESSAGE = "网络错误,请稍后重试!";
/**
* 异常消息

View File

@ -24,7 +24,10 @@ public class ThreadPoolUtil {
*/
private static final BlockingQueue<Runnable> BQUEUE = new ArrayBlockingQueue<Runnable>(100);
private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(SIZE_CORE_POOL, SIZE_MAX_POOL, ALIVE_TIME, TimeUnit.MILLISECONDS, BQUEUE, new ThreadPoolExecutor.CallerRunsPolicy());
public static ThreadPoolExecutor threadPool;
/**
* volatile禁止指令重排
*/
public static volatile ThreadPoolExecutor threadPool;
static {
POOL.prestartAllCoreThreads();
@ -49,22 +52,20 @@ public class ThreadPoolUtil {
}
/**
* dcs获取线程池
* DCL获取线程池
*
* @return 线程池对象
*/
public static ThreadPoolExecutor getThreadPool() {
if (threadPool != null) {
return threadPool;
} else {
synchronized (ThreadPoolUtil.class) {
if (threadPool == null) {
threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
return threadPool;
}
return threadPool;
}
synchronized (ThreadPoolUtil.class) {
if (threadPool == null) {
threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
}
}
return threadPool;
}
public static ThreadPoolExecutor getPool() {

View File

@ -7,7 +7,6 @@ import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
@ -41,7 +40,7 @@ public class Goods extends BaseEntity {
@ApiModelProperty(value = "商品名称")
@NotEmpty(message = "商品名称不能为空")
@Length(max = 100, message = "商品名称提案仓不能超过100个字符")
@Length(max = 100, message = "商品名称太长不能超过100个字符")
private String goodsName;
@ApiModelProperty(value = "商品价格", required = true)

View File

@ -35,7 +35,7 @@ public interface CategoryBrandService extends IService<CategoryBrand> {
* @param brandId 品牌ID
* @return 分类品牌关联信息
*/
List<CategoryBrand> getCategoryBrandListByBrandId(String brandId);
List<CategoryBrand> getCategoryBrandListByBrandId(List<String> brandId);
/**
* 保存分类品牌关系

View File

@ -20,6 +20,13 @@ import java.util.List;
public interface GoodsService extends IService<Goods> {
/**
* 根据品牌获取商品
*
* @param brandIds 品牌ids
*/
List<Goods> getByBrandIds(List<String> brandIds);
/**
* 下架所有商家商品
*

View File

@ -143,6 +143,13 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
void updateGoodsSkuStatus(Goods goods);
/**
* 发送生成ES商品索引
*
* @param goods 商品信息
*/
void generateEs(Goods goods);
/**
* 更新SKU库存
*

View File

@ -5,12 +5,14 @@ import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.entity.dos.CategoryBrand;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dto.BrandPageDTO;
import cn.lili.modules.goods.entity.vos.BrandVO;
import cn.lili.modules.goods.mapper.BrandMapper;
import cn.lili.modules.goods.service.BrandService;
import cn.lili.modules.goods.service.CategoryBrandService;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -44,6 +46,9 @@ public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements
@Autowired
private CategoryService categoryService;
@Autowired
private GoodsService goodsService;
@Override
public IPage<Brand> getBrandsByPage(BrandPageDTO page) {
LambdaQueryWrapper<Brand> queryWrapper = new LambdaQueryWrapper<>();
@ -88,7 +93,9 @@ public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements
Brand brand = this.checkExist(brandId);
//如果是要禁用则需要先判定绑定关系
if (Boolean.TRUE.equals(disable)) {
checkoutCategory(brandId);
List<String> ids = new ArrayList<>();
ids.add(brandId);
checkBind(ids);
}
brand.setDeleteFlag(disable);
return updateById(brand);
@ -96,7 +103,7 @@ public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements
@Override
public void deleteBrands(List<String> ids) {
ids.forEach(this::checkoutCategory);
checkBind(ids);
this.removeByIds(ids);
}
@ -104,16 +111,32 @@ public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements
/**
* 校验绑定关系
*
* @param brandId
* @param brandIds
*/
private void checkoutCategory(String brandId) {
private void checkBind(List<String> brandIds) {
//分了绑定关系查询
List<CategoryBrand> categoryBrands = categoryBrandService.getCategoryBrandListByBrandId(brandId);
List<CategoryBrand> categoryBrands = categoryBrandService.getCategoryBrandListByBrandId(brandIds);
if (!categoryBrands.isEmpty()) {
List<String> brandIds = categoryBrands.stream().map(CategoryBrand::getCategoryId).collect(Collectors.toList());
List<String> categoryIds = categoryBrands.stream().map(CategoryBrand::getCategoryId).collect(Collectors.toList());
throw new ServiceException(ResultCode.BRAND_USE_DISABLE_ERROR,
JSONUtil.toJsonStr(categoryService.getCategoryNameByIds(brandIds)));
JSONUtil.toJsonStr(categoryService.getCategoryNameByIds(categoryIds)));
}
//分了商品绑定关系查询
List<Goods> goods = goodsService.getByBrandIds(brandIds);
if (!goods.isEmpty()) {
List<String> goodsNames = goods.stream().map(Goods::getGoodsName).collect(Collectors.toList());
throw new ServiceException(ResultCode.BRAND_BIND_GOODS_ERROR,
JSONUtil.toJsonStr(goodsNames));
}
}
/**
* 校验绑定关系
*
* @param brandIds
*/
private void checkoutGoods(List<String> brandIds) {
}
/**

View File

@ -7,8 +7,6 @@ import cn.lili.modules.goods.service.CategoryBrandService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -36,8 +34,8 @@ public class CategoryBrandServiceImpl extends ServiceImpl<CategoryBrandMapper, C
}
@Override
public List<CategoryBrand> getCategoryBrandListByBrandId(String brandId) {
return this.list(new LambdaQueryWrapper<CategoryBrand>().eq(CategoryBrand::getBrandId, brandId));
public List<CategoryBrand> getCategoryBrandListByBrandId(List<String> brandId) {
return this.list(new LambdaQueryWrapper<CategoryBrand>().in(CategoryBrand::getBrandId, brandId));
}
@Override

View File

@ -119,6 +119,13 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Autowired
private Cache<GoodsVO> cache;
@Override
public List<Goods> getByBrandIds(List<String> brandIds) {
LambdaQueryWrapper<Goods> lambdaQueryWrapper = new LambdaQueryWrapper<Goods> ();
lambdaQueryWrapper.in(Goods::getBrandId,brandIds);
return list(lambdaQueryWrapper);
}
@Override
public void underStoreGoods(String storeId) {
//获取商品ID列表

View File

@ -43,7 +43,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -64,7 +63,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
* 缓存
*/
@Autowired
private Cache<GoodsSku> cache;
private Cache cache;
/**
* 分类
*/
@ -75,11 +74,6 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
*/
@Autowired
private GoodsGalleryService goodsGalleryService;
/**
* 缓存
*/
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* rocketMq
*/
@ -195,7 +189,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Override
public GoodsSku getGoodsSkuByIdFromCache(String id) {
//获取缓存中的sku
GoodsSku goodsSku = cache.get(GoodsSkuService.getCacheKeys(id));
GoodsSku goodsSku = (GoodsSku) cache.get(GoodsSkuService.getCacheKeys(id));
//如果缓存中没有信息则查询数据库然后写入缓存
if (goodsSku == null) {
goodsSku = this.getById(id);
@ -206,14 +200,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
}
//获取商品库存
String quantity = stringRedisTemplate.opsForValue().get(GoodsSkuService.getStockCacheKey(id));
Integer integer = (Integer) cache.get(GoodsSkuService.getStockCacheKey(id));
//库存不为空
if (StrUtil.isNotEmpty(quantity)) {
if (integer != null) {
//库存与缓存中不一致
if (!goodsSku.getQuantity().equals(Convert.toInt(quantity))) {
if (!goodsSku.getQuantity().equals(integer)) {
//写入最新的库存信息
goodsSku.setQuantity(Convert.toInt(quantity));
goodsSku.setQuantity(integer);
cache.put(GoodsSkuService.getCacheKeys(goodsSku.getId()), goodsSku);
}
}
@ -408,7 +402,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
goodsSku.setQuantity(quantity);
this.update(new LambdaUpdateWrapper<GoodsSku>().eq(GoodsSku::getId, skuId).set(GoodsSku::getQuantity, quantity));
cache.put(GoodsSkuService.getCacheKeys(skuId), goodsSku);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(skuId), quantity.toString());
cache.put(GoodsSkuService.getStockCacheKey(skuId), quantity);
//更新商品库存
List<GoodsSku> goodsSkus = new ArrayList<>();
@ -420,12 +414,12 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Override
public Integer getStock(String skuId) {
String cacheKeys = GoodsSkuService.getStockCacheKey(skuId);
String stockStr = stringRedisTemplate.opsForValue().get(cacheKeys);
if (stockStr != null) {
return Convert.toInt(stockStr);
Integer stock = (Integer) cache.get(cacheKeys);
if (stock != null) {
return stock;
} else {
GoodsSku goodsSku = getGoodsSkuByIdFromCache(skuId);
stringRedisTemplate.opsForValue().set(cacheKeys, goodsSku.getQuantity().toString());
cache.put(cacheKeys, goodsSku.getQuantity());
return goodsSku.getQuantity();
}
}
@ -497,7 +491,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
*
* @param goods 商品信息
*/
private void generateEs(Goods goods) {
public void generateEs(Goods goods) {
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GENERATOR_GOODS_INDEX.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goods), RocketmqSendCallbackBuilder.commonCallback());
@ -536,7 +530,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
}
goodsSku.setGoodsType(goods.getGoodsType());
skus.add(goodsSku);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
}
this.saveBatch(skus);
return skus;

View File

@ -1,14 +1,14 @@
package cn.lili.modules.order.cart.entity.dto;
import cn.lili.modules.member.entity.dos.MemberAddress;
import cn.lili.modules.order.cart.entity.enums.SuperpositionPromotionEnum;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.vo.OrderVO;
import cn.lili.modules.order.order.entity.vo.ReceiptVO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.SuperpositionPromotionEnum;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.entity.vo.PriceDetailVO;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.vo.OrderVO;
import cn.lili.modules.order.order.entity.vo.ReceiptVO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.vos.MemberCouponVO;
import io.swagger.annotations.ApiModelProperty;
@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 购物车视图
@ -147,4 +148,16 @@ public class TradeDTO implements Serializable {
public TradeDTO() {
this(CartTypeEnum.CART);
}
/**
* 过滤购物车中已选择的sku
*
* @return
*/
public List<CartSkuVO> getCheckedSkuList() {
if (skuList != null && !skuList.isEmpty()) {
return skuList.stream().filter(CartSkuVO::getChecked).collect(Collectors.toList());
}
return skuList;
}
}

View File

@ -33,4 +33,8 @@ public enum CartTypeEnum {
*/
KANJIA;
public String getPrefix() {
return "{" + this.name() + "}_";
}
}

View File

@ -1,30 +0,0 @@
package cn.lili.modules.order.cart.entity.enums;
/**
* 交易缓存枚举
*
* @author Chopper
* @since 2020-03-25 2:30 下午
*/
public enum TradeCacheEnum {
//================交易=================
/**
* 拼团
*/
PINTUAN,
/**
* 购物车原始数据
*/
CART_DATA,
/**
* 立即购买购物车原始数据
*/
BUY_NOW_CART_DATA;
public String getPrefix() {
return "{" + this.name() + "}_";
}
}

View File

@ -103,7 +103,7 @@ public class CouponRender implements CartRenderStep {
if (memberCoupon == null) {
return;
}
List<CartSkuVO> filterSku = filterSkuVo(tradeDTO.getSkuList(), memberCoupon);
List<CartSkuVO> filterSku = filterSkuVo(tradeDTO.getCheckedSkuList(), memberCoupon);
if (filterSku == null || filterSku.isEmpty()) {
tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon,
"购物车中没有满足优惠券使用范围的优惠券"));

View File

@ -11,13 +11,13 @@ import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.member.entity.dos.MemberAddress;
import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum;
import cn.lili.modules.order.cart.entity.enums.TradeCacheEnum;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.cart.entity.vo.TradeParams;
@ -92,6 +92,11 @@ public class CartServiceImpl implements CartService {
*/
@Autowired
private EsGoodsSearchService esGoodsSearchService;
/**
* ES商品
*/
@Autowired
private GoodsService goodsService;
/**
* 拼团
*/
@ -197,17 +202,12 @@ public class CartServiceImpl implements CartService {
*/
private String getOriginKey(CartTypeEnum cartTypeEnum) {
String cacheKey = "";
//如果会员登录了则要以会员id为key
AuthUser currentUser = UserContext.getCurrentUser();
if (cartTypeEnum.equals(CartTypeEnum.CART)) {
cacheKey = TradeCacheEnum.CART_DATA.getPrefix() + currentUser.getId();
} else if (cartTypeEnum.equals(CartTypeEnum.BUY_NOW)) {
cacheKey = TradeCacheEnum.BUY_NOW_CART_DATA.getPrefix() + currentUser.getId();
} else if (cartTypeEnum.equals(CartTypeEnum.PINTUAN)) {
cacheKey = TradeCacheEnum.PINTUAN.getPrefix() + currentUser.getId();
//缓存key默认使用购物车
if (cartTypeEnum != null) {
AuthUser currentUser = UserContext.getCurrentUser();
return cartTypeEnum.getPrefix() + currentUser.getId();
}
return cacheKey;
throw new ServiceException(ResultCode.ERROR);
}
@Override
@ -689,6 +689,8 @@ public class CartServiceImpl implements CartService {
cartSkuVO.setUtilPrice(promotionGoods.getPrice());
cartSkuVO.setPurchasePrice(promotionGoods.getPrice());
} else {
//如果拼团活动被异常处理则在这里安排mq重新写入商品索引
goodsSkuService.generateEs(goodsService.getById(cartSkuVO.getGoodsSku().getGoodsId()));
throw new ServiceException(ResultCode.CART_PINTUAN_NOT_EXIST_ERROR);
}
//检测拼团限购数量

View File

@ -99,8 +99,7 @@ public class OrderSearchParams extends PageVO {
//关键字查询
if (StrUtil.isNotEmpty(keywords)) {
wrapper.like("o.sn", keywords);
wrapper.like("oi.goods_name", keywords);
wrapper.like("o.sn", keywords).or().like("oi.goods_name", keywords);
}
//按卖家查询
wrapper.eq(StrUtil.equals(UserContext.getCurrentUser().getRole().name(), UserEnums.STORE.name()), "o.store_id", UserContext.getCurrentUser().getStoreId());

View File

@ -339,7 +339,7 @@ public class SeckillServiceImpl extends ServiceImpl<SeckillMapper, Seckill> impl
int sameNum = this.count(queryWrapper);
//当前时间段是否存在同类活动
if (sameNum > 0) {
throw new ServiceException("当前时间内已存在同类活动:" + seckill.getStartTime());
throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST);
}
}
}

View File

@ -18,6 +18,16 @@ import java.util.Map;
**/
public interface EsGoodsIndexService {
/**
* 全局索引初始化
*/
void init();
/**
* 获取es生成索引进度
* @return
*/
Map<String, Integer> getProgress();
/**
* 添加商品索引
*

View File

@ -2,6 +2,8 @@ package cn.lili.modules.search.serviceimpl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONObject;
@ -9,14 +11,17 @@ import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.elasticsearch.BaseElasticsearchService;
import cn.lili.elasticsearch.EsSuffix;
import cn.lili.elasticsearch.config.ElasticsearchProperties;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dos.GoodsWords;
import cn.lili.modules.goods.entity.dos.*;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.enums.GoodsWordsTypeEnum;
import cn.lili.modules.goods.service.GoodsWordsService;
import cn.lili.modules.goods.service.*;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.dto.BasePromotion;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
@ -27,6 +32,8 @@ import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
import cn.lili.modules.search.repository.EsGoodsIndexRepository;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.search.service.EsGoodsSearchService;
import cn.lili.modules.store.entity.dos.StoreGoodsLabel;
import cn.lili.modules.store.service.StoreGoodsLabelService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.IterableUtil;
@ -78,9 +85,111 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
private GoodsWordsService goodsWordsService;
@Autowired
private PromotionService promotionService;
@Autowired
private GoodsSkuService goodsSkuService;
@Autowired
private GoodsService goodsService;
@Autowired
private BrandService brandService;
@Autowired
private CategoryService categoryService;
@Autowired
private StoreGoodsLabelService storeGoodsLabelService;
@Autowired
private Cache<Object> cache;
@Override
public void init() {
//获取索引任务标识
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
//为空则默认写入没有任务
if (flag == null) {
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false);
}
//有正在初始化的任务则提示异常
if (Boolean.TRUE.equals(flag)) {
throw new ServiceException(ResultCode.INDEX_BUILDING);
}
//初始化标识
cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null);
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true);
ThreadUtil.execAsync(() -> {
try {
//查询商品信息
LambdaQueryWrapper<GoodsSku> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name());
queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
List<GoodsSku> list = goodsSkuService.list(queryWrapper);
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
//库存锁是在redis做的所以生成索引同时更新一下redis中的库存数量
for (GoodsSku goodsSku : list) {
Goods goods = goodsService.getById(goodsSku.getGoodsId());
//如果出现极端情况有sku没有与之匹配的商品则跳过
if (goods == null) {
continue;
}
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
//商品参数索引
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
List<GoodsParamsDTO> goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class);
index = new EsGoodsIndex(goodsSku, goodsParamDTOS);
}
//商品分类索引
if (goods.getCategoryPath() != null) {
List<Category> categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(",")));
if (!categories.isEmpty()) {
index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ","));
}
}
//商品品牌索引
Brand brand = brandService.getById(goods.getBrandId());
if (brand != null) {
index.setBrandName(brand.getName());
index.setBrandUrl(brand.getLogo());
}
//店铺分类索引
if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) {
List<StoreGoodsLabel> storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(",")));
if (!storeGoodsLabels.isEmpty()) {
index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ","));
}
}
//促销索引
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
index.setPromotionMap(goodsCurrentPromotionMap);
esGoodsIndices.add(index);
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
}
//初始化商品索引
this.initIndex(esGoodsIndices);
} catch (Exception e) {
log.error("商品索引生成异常:", e);
//如果出现异常则将进行中的任务标识取消掉打印日志
cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null);
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false);
}
});
}
@Override
public Map<String, Integer> getProgress() {
Map<String, Integer> map = (Map<String, Integer>) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix());
if (map == null) {
return null;
}
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
map.put("flag", Boolean.TRUE.equals(flag) ? 1 : 0);
return map;
}
@Override
public void addIndex(EsGoodsIndex goods) {
try {

View File

@ -159,7 +159,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
String categoryNamePath = categoryPath;
if (!categoryBuckets.isEmpty()) {
if (!categoryNameBuckets.isEmpty()) {
categoryNamePath = categoryNameBuckets.get(0).getKey().toString();
}
String[] split = ArrayUtil.distinct(categoryPath.split(","));
@ -187,6 +187,10 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
if (brandBuckets != null && !brandBuckets.isEmpty()) {
for (int i = 0; i < brandBuckets.size(); i++) {
String brandId = brandBuckets.get(i).getKey().toString();
//当商品品牌id为0时代表商品没有选择品牌所以过滤掉品牌选择器
if (brandId.equals("0")) {
continue;
}
if (CharSequenceUtil.isNotEmpty(goodsSearch.getBrandId())) {
List<String> brandList = Arrays.asList(goodsSearch.getBrandId().split("@"));
if (brandList.contains(brandId)) {

View File

@ -20,7 +20,7 @@ public interface VerificationService {
* @return 校验对象
* @throws IOException 校验错误
*/
Map<String, Object> createVerification(VerificationEnums verificationEnums, String uuid) throws IOException;
Map<String, Object> createVerification(VerificationEnums verificationEnums, String uuid);
/**
* 预校验

View File

@ -17,7 +17,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
@ -51,7 +50,7 @@ public class VerificationServiceImpl implements VerificationService {
* @return 验证码参数
*/
@Override
public Map<String, Object> createVerification(VerificationEnums verificationEnums, String uuid) throws IOException {
public Map<String, Object> createVerification(VerificationEnums verificationEnums, String uuid) {
if (uuid == null) {
throw new ServiceException(ResultCode.ILLEGAL_REQUEST_ERROR);
@ -97,8 +96,7 @@ public class VerificationServiceImpl implements VerificationService {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("创建校验错误", e);
return null;
throw new ServiceException(ResultCode.ERROR);
}
}
@ -136,16 +134,16 @@ public class VerificationServiceImpl implements VerificationService {
public boolean preCheck(Integer xPos, String uuid, VerificationEnums verificationEnums) {
Integer randomX = (Integer) cache.get(cacheKey(verificationEnums, uuid));
if (randomX == null) {
return false;
throw new ServiceException(ResultCode.VERIFICATION_CODE_INVALID);
}
log.debug("{}{}", randomX, xPos);
//验证结果
if (Math.abs(randomX - xPos) < verificationCodeProperties.getFaultTolerant()) {
//验证结果正确 && 删除标记成功
if (Math.abs(randomX - xPos) < verificationCodeProperties.getFaultTolerant() && cache.remove(cacheKey(verificationEnums, uuid))) {
//验证成功则记录验证结果 验证有效时间与验证码创建有效时间一致
cache.put(cacheResult(verificationEnums, uuid), true, verificationCodeProperties.getEffectiveTime());
return true;
}
return false;
throw new ServiceException(ResultCode.VERIFICATION_ERROR);
}
/**
@ -157,13 +155,11 @@ public class VerificationServiceImpl implements VerificationService {
*/
@Override
public boolean check(String uuid, VerificationEnums verificationEnums) {
Object object = cache.get(cacheResult(verificationEnums, uuid));
if (object == null) {
return false;
} else {
cache.remove(cacheResult(verificationEnums, uuid));
//如果有校验标记则返回校验结果
if (cache.remove(cacheResult(verificationEnums, uuid))) {
return true;
}
throw new ServiceException(ResultCode.VERIFICATION_CODE_INVALID);
}
/**

View File

@ -1,41 +1,15 @@
package cn.lili.controller.other;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.service.BrandService;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.promotion.service.PromotionService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.store.entity.dos.StoreGoodsLabel;
import cn.lili.modules.store.service.StoreGoodsLabelService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
@ -48,108 +22,22 @@ import java.util.Map;
@RestController
@Api(tags = "ES初始化接口")
@RequestMapping("/manager/elasticsearch")
@Slf4j
public class ElasticsearchController {
@Autowired
private EsGoodsIndexService esGoodsIndexService;
@Autowired
private GoodsSkuService goodsSkuService;
@Autowired
private GoodsService goodsService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private PromotionService promotionService;
@Autowired
private CategoryService categoryService;
@Autowired
private BrandService brandService;
@Autowired
private StoreGoodsLabelService storeGoodsLabelService;
@Autowired
private Cache cache;
@GetMapping
public ResultMessage<String> init() {
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
if (flag == null) {
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false);
}
if (Boolean.TRUE.equals(flag)) {
return ResultUtil.error(100000, "当前有任务在执行");
}
cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null);
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true);
ThreadUtil.execAsync(() -> {
try {
//查询商品信息
LambdaQueryWrapper<GoodsSku> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name());
queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
List<GoodsSku> list = goodsSkuService.list(queryWrapper);
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
//库存锁是在redis做的所以生成索引同时更新一下redis中的库存数量
for (GoodsSku goodsSku : list) {
Goods goods = goodsService.getById(goodsSku.getGoodsId());
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
List<GoodsParamsDTO> goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class);
index = new EsGoodsIndex(goodsSku, goodsParamDTOS);
}
if (goods.getCategoryPath() != null) {
List<Category> categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(",")));
if (!categories.isEmpty()) {
index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ","));
}
}
Brand brand = brandService.getById(goods.getBrandId());
if (brand != null) {
index.setBrandName(brand.getName());
index.setBrandUrl(brand.getLogo());
}
if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) {
List<StoreGoodsLabel> storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(",")));
if (!storeGoodsLabels.isEmpty()) {
index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ","));
}
}
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
index.setPromotionMap(goodsCurrentPromotionMap);
esGoodsIndices.add(index);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
}
//初始化商品索引
esGoodsIndexService.initIndex(esGoodsIndices);
} catch (Exception e) {
cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null);
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false);
log.error("初始化索引异常", e);
}
});
esGoodsIndexService.init();
return ResultUtil.success();
}
@GetMapping("/progress")
public ResultMessage<Map<String, Integer>> getProgress() {
try {
Map<String, Integer> map = (Map<String, Integer>) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix());
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
map.put("flag", Boolean.TRUE.equals(flag) ? 1 : 0);
return ResultUtil.data(map);
} catch (Exception e) {
return ResultUtil.data(null);
}
return ResultUtil.data(esGoodsIndexService.getProgress());
}
}

View File

@ -118,7 +118,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: false
show: true
# 忽略鉴权url
ignored:

View File

@ -2,6 +2,7 @@ package cn.lili.test.elasticsearch;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
@ -22,7 +23,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.lang.reflect.Field;
@ -52,7 +52,7 @@ class EsTest {
private GoodsSkuService goodsSkuService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
private Cache cache;
@Autowired
private PromotionService promotionService;
@ -161,7 +161,7 @@ class EsTest {
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
index.setPromotionMap(goodsCurrentPromotionMap);
esGoodsIndices.add(index);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
}
esGoodsIndexService.initIndex(esGoodsIndices);
Assertions.assertTrue(true);

View File

@ -118,7 +118,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: false
show: true
# 忽略鉴权url
ignored: