import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
import cn.dev33.satoken.annotation.SaIgnore; | |||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import javax.validation.constraints.*; | import javax.validation.constraints.*; | ||||
import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||
import org.apache.http.HttpRequest; | |||||
import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||
import com.ruoyi.common.annotation.RepeatSubmit; | import com.ruoyi.common.annotation.RepeatSubmit; | ||||
return iZsOperationGoodsService.queryPageList(bo, pageQuery); | return iZsOperationGoodsService.queryPageList(bo, pageQuery); | ||||
} | } | ||||
/** | |||||
* 查询商品配置列表 | |||||
*/ | |||||
@SaIgnore | |||||
@GetMapping("/noVerifyList") | |||||
public TableDataInfo<ZsOperationGoodsVo> listSpe(HttpRequest httpRequest, ZsOperationGoodsBo bo, PageQuery pageQuery) { | |||||
return iZsOperationGoodsService.queryPageList(bo, pageQuery); | |||||
} | |||||
/** | /** | ||||
* 导出商品配置列表 | * 导出商品配置列表 | ||||
*/ | */ |
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
import cn.dev33.satoken.annotation.SaIgnore; | |||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import javax.validation.constraints.*; | import javax.validation.constraints.*; | ||||
import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||
return iZsOperationWarnconfigService.queryPageList(bo, pageQuery); | return iZsOperationWarnconfigService.queryPageList(bo, pageQuery); | ||||
} | } | ||||
/** | |||||
* 查询预警配置列表 | |||||
*/ | |||||
@SaIgnore | |||||
@GetMapping("/noVerifyList") | |||||
public TableDataInfo<ZsOperationWarnconfigVo> listspe(HttpServletRequest request, ZsOperationWarnconfigBo bo, PageQuery pageQuery) { | |||||
//String secretKey = request.getHeader("secret_key"); | |||||
return iZsOperationWarnconfigService.queryPageList(bo, pageQuery); | |||||
} | |||||
/** | /** | ||||
* 导出预警配置列表 | * 导出预警配置列表 | ||||
*/ | */ |
package com.ruoyi.system.controller; | package com.ruoyi.system.controller; | ||||
import java.util.HashMap; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Map; | |||||
import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
import cn.dev33.satoken.annotation.SaIgnore; | import cn.dev33.satoken.annotation.SaIgnore; | ||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import javax.validation.constraints.*; | import javax.validation.constraints.*; | ||||
import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
@RestController | @RestController | ||||
@RequestMapping("/system/operationWarnresult") | @RequestMapping("/system/operationWarnresult") | ||||
@Slf4j | |||||
public class ZsOperationWarnresultController extends BaseController { | public class ZsOperationWarnresultController extends BaseController { | ||||
private final IZsOperationWarnresultService iZsOperationWarnresultService; | private final IZsOperationWarnresultService iZsOperationWarnresultService; | ||||
//立即调用预警监控 | //立即调用预警监控 | ||||
@SaIgnore | @SaIgnore | ||||
@GetMapping("/monitorWarn") | |||||
public void monitorWarn() { | |||||
iZsOperationWarnresultService.monitorWarn(); | |||||
@PostMapping("/receiveLatestGoodsInfo") | |||||
public Map receiveLatestGoodsInfo(@RequestBody Map map) { | |||||
try { | |||||
return iZsOperationWarnresultService.receiveLatestGoodsInfo(map); | |||||
} catch (Exception e) { | |||||
Map reMap = new HashMap(); | |||||
reMap.put("success",false); | |||||
reMap.put("message","失败"); | |||||
log.error("最新商品信息接收失败!=:",e); | |||||
return reMap; | |||||
} | |||||
} | } | ||||
} | } |
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | |||||
/** | /** | ||||
* 预警结果Service接口 | * 预警结果Service接口 | ||||
*/ | */ | ||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); | Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); | ||||
void monitorWarn(); | |||||
Map receiveLatestGoodsInfo(Map map); | |||||
} | } |
package com.ruoyi.system.service.impl; | package com.ruoyi.system.service.impl; | ||||
import cn.hutool.core.bean.BeanUtil; | import cn.hutool.core.bean.BeanUtil; | ||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; | |||||
import com.ruoyi.common.utils.StringUtils; | import com.ruoyi.common.utils.StringUtils; | ||||
import com.ruoyi.common.core.page.TableDataInfo; | import com.ruoyi.common.core.page.TableDataInfo; | ||||
import com.ruoyi.common.core.domain.PageQuery; | import com.ruoyi.common.core.domain.PageQuery; | ||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
import com.ruoyi.system.domain.ZsOperationWarnconfig; | |||||
import com.ruoyi.system.domain.*; | |||||
import com.ruoyi.system.mapper.ZsOperationGoodsMapper; | |||||
import com.ruoyi.system.mapper.ZsOperationSendconfigMapper; | |||||
import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper; | import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper; | ||||
import com.ruoyi.system.service.ISysDictDataService; | |||||
import com.ruoyi.system.task.MonitorTaskScheduler; | import com.ruoyi.system.task.MonitorTaskScheduler; | ||||
import com.ruoyi.system.utils.EmailUtils; | |||||
import lombok.Data; | |||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
import com.ruoyi.system.domain.bo.ZsOperationWarnresultBo; | import com.ruoyi.system.domain.bo.ZsOperationWarnresultBo; | ||||
import com.ruoyi.system.domain.vo.ZsOperationWarnresultVo; | import com.ruoyi.system.domain.vo.ZsOperationWarnresultVo; | ||||
import com.ruoyi.system.domain.ZsOperationWarnresult; | |||||
import com.ruoyi.system.mapper.ZsOperationWarnresultMapper; | import com.ruoyi.system.mapper.ZsOperationWarnresultMapper; | ||||
import com.ruoyi.system.service.IZsOperationWarnresultService; | import com.ruoyi.system.service.IZsOperationWarnresultService; | ||||
import org.thymeleaf.context.Context; | |||||
import org.thymeleaf.spring5.SpringTemplateEngine; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Collection; | |||||
import java.math.BigDecimal; | |||||
import java.math.RoundingMode; | |||||
import java.text.SimpleDateFormat; | |||||
import java.time.LocalTime; | |||||
import java.util.*; | |||||
/** | /** | ||||
* 预警结果Service业务层处理 | * 预警结果Service业务层处理 | ||||
*/ | */ | ||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
@Service | @Service | ||||
@Slf4j | |||||
public class ZsOperationWarnresultServiceImpl implements IZsOperationWarnresultService { | public class ZsOperationWarnresultServiceImpl implements IZsOperationWarnresultService { | ||||
private final ZsOperationWarnresultMapper baseMapper; | private final ZsOperationWarnresultMapper baseMapper; | ||||
private MonitorTaskScheduler monitorTaskScheduler; | private MonitorTaskScheduler monitorTaskScheduler; | ||||
@Autowired | @Autowired | ||||
private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper; | private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper; | ||||
@Autowired | |||||
private ZsOperationGoodsMapper zsOperationGoodsMapper; | |||||
@Autowired | |||||
private ZsOperationWarnresultMapper zsOperationWarnresultMapper; | |||||
@Autowired | |||||
private ZsOperationSendconfigMapper zsOperationSendconfigMapper; | |||||
@Autowired | |||||
private ISysDictDataService iSysDictDataService; | |||||
@Autowired | |||||
private SpringTemplateEngine templateEngine; | |||||
@Autowired | |||||
private EmailUtils emailUtils; | |||||
/** | /** | ||||
* 查询预警结果 | * 查询预警结果 | ||||
*/ | */ | ||||
} | } | ||||
return baseMapper.deleteBatchIds(ids) > 0; | return baseMapper.deleteBatchIds(ids) > 0; | ||||
} | } | ||||
//拉取商品 进行比对 | |||||
//接收预警数据 | |||||
@Override | @Override | ||||
public void monitorWarn() { | |||||
public Map receiveLatestGoodsInfo(Map dataMap) { | |||||
Map reMap =new HashMap(); | |||||
boolean success = true; | |||||
String message = "成功"; | |||||
//1.查询预警配置 | |||||
List<ZsOperationWarnconfig> zsOperationWarnconfigs = zsOperationWarnconfigMapper.selectList(); | List<ZsOperationWarnconfig> zsOperationWarnconfigs = zsOperationWarnconfigMapper.selectList(); | ||||
if (zsOperationWarnconfigs!=null&&zsOperationWarnconfigs.size()>0) { | if (zsOperationWarnconfigs!=null&&zsOperationWarnconfigs.size()>0) { | ||||
ZsOperationWarnconfig zsOperationWarnconfig = zsOperationWarnconfigs.get(0); | ZsOperationWarnconfig zsOperationWarnconfig = zsOperationWarnconfigs.get(0); | ||||
monitorTaskScheduler.monitorWarn(zsOperationWarnconfig); | |||||
//2.更新商品表和预警结果表信息 | |||||
String curUrl = (String)dataMap.get("url"); | |||||
String newName = (String)dataMap.get("title"); | |||||
String newSn = (String)dataMap.get("sku"); | |||||
String newRemark = (String)dataMap.get("remark"); | |||||
UpdateWrapper goodsUpdateWrapper = new UpdateWrapper<>(); | |||||
goodsUpdateWrapper.eq("goods_sku_url",curUrl); | |||||
goodsUpdateWrapper.set("goods_sku_name",newName); | |||||
goodsUpdateWrapper.set("goods_sku_sn",newSn); | |||||
goodsUpdateWrapper.set("remark",newRemark); | |||||
int j = zsOperationGoodsMapper.update(null,goodsUpdateWrapper); | |||||
UpdateWrapper<ZsOperationWarnresult> updateWrapper = new UpdateWrapper<>(); | |||||
updateWrapper.eq("goods_sku_url",curUrl); | |||||
updateWrapper.set("goods_sku_name",newName); | |||||
updateWrapper.set("goods_sku_sn",newSn); | |||||
int i = zsOperationWarnresultMapper.update(null,updateWrapper); | |||||
//3.查询商品基准价格 | |||||
QueryWrapper<ZsOperationGoods> goodsQueryWrapper = new QueryWrapper(); | |||||
goodsQueryWrapper.eq("goods_sku_url",curUrl); | |||||
List<ZsOperationGoods> goodsList = zsOperationGoodsMapper.selectList(goodsQueryWrapper); | |||||
//4.比较基准价格和最新的价格是否相差大于等于 设定的阈值 | |||||
if (goodsList!=null&&goodsList.size()>0) { | |||||
ZsOperationGoods zsOperationGoods =goodsList.get(0); | |||||
String newPriceStr = (String)dataMap.get("price"); | |||||
if (org.apache.commons.lang3.StringUtils.isNotBlank(newPriceStr)) { | |||||
newPriceStr =newPriceStr.replace(",","").trim(); | |||||
BigDecimal newPrice = new BigDecimal(newPriceStr); | |||||
//如果新价格大于0 | |||||
if (newPrice.compareTo(BigDecimal.ZERO) > 0) { | |||||
//判断这个商品最新的价格是否已经存在预警结果表了,如果在不发送消息和生成结果 | |||||
if (checkIsExistsWarnResult(curUrl,newPrice)) { | |||||
message = "已经存在预警结果表,并且价格没有再次变化,不记录 url=:"+curUrl; | |||||
log.info(message); | |||||
} else { | |||||
//获取基准价格 | |||||
BigDecimal initPrice = zsOperationGoods.getInitPrice(); | |||||
//获取基准价格和最新价格的差值比例 | |||||
BigDecimal percentageChange= getChangeThreshold(initPrice,newPrice); | |||||
//我们设置的预警阈值 | |||||
BigDecimal priceChange = new BigDecimal(zsOperationWarnconfig.getPriceChangeThreshold()); | |||||
// 比较差值比例是否大于等于我们设置的预警阈值 | |||||
if (percentageChange.compareTo(priceChange) >= 0) { | |||||
//5.生成 预警结果数据 | |||||
String warnTypes = zsOperationWarnconfig.getWarnTypes(); | |||||
ZsOperationWarnresult zsOperationWarnresult = new ZsOperationWarnresult(); | |||||
zsOperationWarnresult.setWarnTime(new Date()); | |||||
zsOperationWarnresult.setGoodsSkuName(zsOperationGoods.getGoodsSkuName()); | |||||
zsOperationWarnresult.setGoodsSkuSn(zsOperationGoods.getGoodsSkuSn()); | |||||
zsOperationWarnresult.setGoodsSkuUrl(curUrl); | |||||
zsOperationWarnresult.setInitPrice(initPrice); | |||||
zsOperationWarnresult.setCurPrice(newPrice); | |||||
zsOperationWarnresult.setPriceChangeRatio(percentageChange.toString()); | |||||
zsOperationWarnresult.setWarnTypes(warnTypes); | |||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
String warnDate = sdf.format(zsOperationWarnresult.getWarnTime()); | |||||
//根据平台编码获取平台名称 | |||||
String platformName = iSysDictDataService.selectDictLabel("zs_operation_platform",zsOperationGoods.getPlatform()); | |||||
String title = "Digital System 系统提醒:您所监控的 "+platformName+" 商品已发生价格波动"; | |||||
WarnEmail warnEmail = new WarnEmail(); | |||||
warnEmail.setPlatformName(platformName); | |||||
warnEmail.setSkuName(zsOperationGoods.getGoodsSkuName()); | |||||
warnEmail.setSkuSn(newSn); | |||||
warnEmail.setSkuUrl(curUrl); | |||||
warnEmail.setWarnTime(warnDate); | |||||
warnEmail.setCurPrice(initPrice.toString()); | |||||
warnEmail.setNewPrice(newPrice.toString()); | |||||
warnEmail.setImagePath((String)dataMap.get("screenshotUrl")); | |||||
//读取邮件模板 | |||||
Context context = new Context(); | |||||
context.setVariable("warnEmail", warnEmail); | |||||
String warnContentHtml = templateEngine.process("warnEmail", context); | |||||
zsOperationWarnresult.setWarnContent(warnContentHtml); | |||||
zsOperationWarnresult.setSnapshotUrl((String)dataMap.get("screenshotUrl")); | |||||
zsOperationWarnresult.setStatus(0); | |||||
zsOperationWarnresult.setPlatform(zsOperationGoods.getPlatform()); | |||||
zsOperationWarnresult.setCompareStatus(1); | |||||
zsOperationWarnresultMapper.insert(zsOperationWarnresult); | |||||
//6.发送邮件 | |||||
QueryWrapper<ZsOperationSendconfig> sendWrapper= new QueryWrapper<>(); | |||||
sendWrapper.eq("module",0); | |||||
sendWrapper.in("code",warnTypes.split(",")); | |||||
//根据预警编码 查询出对应的预警信息接收地址 | |||||
List<ZsOperationSendconfig> zsOperationSendconfigList = zsOperationSendconfigMapper.selectList(sendWrapper); | |||||
if (zsOperationSendconfigList!=null&&zsOperationSendconfigList.size()>0) { | |||||
for (ZsOperationSendconfig zsOperationSendconfig : zsOperationSendconfigList) { | |||||
String receiveEmailStr = zsOperationSendconfig.getConfigValue(); | |||||
String[] receiveEmails = receiveEmailStr.split(","); | |||||
for (String receiveEmail : receiveEmails) { | |||||
//发送数据 1立刻发送 0 9:00-18:00 发送 | |||||
String warnTimeRange = zsOperationWarnconfig.getWarnTimeRange(); | |||||
if ("1".equals(warnTimeRange)) { | |||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId()); | |||||
} else { | |||||
if (isBetween9And18()) { | |||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId()); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
message = "预警接收配置为空,不发送邮件"; | |||||
log.info(message); | |||||
} | |||||
} else { | |||||
message = "商品:"+newName+";价格变动小于阈值,不生成比对结果;本次变动幅度=:"+percentageChange; | |||||
log.info(message); | |||||
} | |||||
} | |||||
} else { | |||||
log.info("商品:"+newName+";新价格为0,不生成比对结果"); | |||||
} | |||||
} | |||||
} else { | |||||
success = false; | |||||
message = "商品不存在"; | |||||
} | |||||
} else { | |||||
success = false; | |||||
message = "预警配置为空"; | |||||
} | |||||
reMap.put("success",success); | |||||
reMap.put("message",message); | |||||
return reMap; | |||||
} | |||||
public boolean checkIsExistsWarnResult(String url,BigDecimal newPrice) { | |||||
boolean isExists = false; | |||||
QueryWrapper<ZsOperationWarnresult> queryWrapper = new QueryWrapper<>(); | |||||
queryWrapper.eq("goods_sku_url",url); | |||||
queryWrapper.eq("status",0); | |||||
queryWrapper.orderByDesc("warn_time"); | |||||
List<ZsOperationWarnresult> list = zsOperationWarnresultMapper.selectList(queryWrapper); | |||||
if (list!=null&&list.size()>0) { | |||||
ZsOperationWarnresult zsOperationWarnresult = list.get(0); | |||||
BigDecimal curPrice = zsOperationWarnresult.getCurPrice(); | |||||
if (curPrice!=null&&newPrice.compareTo(curPrice)==0) { | |||||
isExists = true; | |||||
} | |||||
} | |||||
return isExists; | |||||
} | |||||
/** | |||||
* 判断价格变化是否超过阈值 | |||||
* @param curPrice 当前价格(基准价) | |||||
* @param newPrice 新价格 | |||||
* @return 变化幅度超过阈值返回true,否则false | |||||
*/ | |||||
public BigDecimal getChangeThreshold(BigDecimal curPrice,BigDecimal newPrice) { | |||||
// 参数校验 | |||||
if (curPrice == null || newPrice == null ) { | |||||
throw new IllegalArgumentException("参数不能为空"); | |||||
} | } | ||||
// 计算价格变化绝对值 | |||||
BigDecimal diff = newPrice.subtract(curPrice).abs(); | |||||
// 计算百分比变化(保留4位小数) | |||||
BigDecimal percentageChange = diff.divide(curPrice, 4, RoundingMode.HALF_UP) | |||||
.multiply(new BigDecimal("100")); | |||||
return percentageChange; | |||||
} | |||||
public boolean isBetween9And18() { | |||||
LocalTime currentTime = LocalTime.now(); | |||||
LocalTime startTime = LocalTime.of(9, 0); // 9:00 | |||||
LocalTime endTime = LocalTime.of(18, 0); // 18:00 | |||||
// 判断当前时间是否在 [9:00, 18:00] 区间(包含边界) | |||||
return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime); | |||||
} | } | ||||
} | } |
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; | ||||
import com.ruoyi.system.domain.ZsOperationGoods; | |||||
import com.ruoyi.system.domain.ZsOperationSendconfig; | |||||
import com.ruoyi.system.domain.ZsOperationWarnconfig; | |||||
import com.ruoyi.system.domain.ZsOperationWarnresult; | |||||
import com.ruoyi.system.domain.*; | |||||
import com.ruoyi.system.mapper.ZsOperationGoodsMapper; | import com.ruoyi.system.mapper.ZsOperationGoodsMapper; | ||||
import com.ruoyi.system.mapper.ZsOperationSendconfigMapper; | import com.ruoyi.system.mapper.ZsOperationSendconfigMapper; | ||||
import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper; | import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper; | ||||
import com.ruoyi.system.mapper.ZsOperationWarnresultMapper; | import com.ruoyi.system.mapper.ZsOperationWarnresultMapper; | ||||
import com.ruoyi.system.service.ISysDictDataService; | |||||
import com.ruoyi.system.utils.EmailUtils; | import com.ruoyi.system.utils.EmailUtils; | ||||
import com.ruoyi.system.utils.HttpUtil; | import com.ruoyi.system.utils.HttpUtil; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | ||||
import org.springframework.scheduling.support.CronTrigger; | import org.springframework.scheduling.support.CronTrigger; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import org.thymeleaf.context.Context; | |||||
import org.thymeleaf.spring5.SpringTemplateEngine; | |||||
import javax.annotation.PostConstruct; | import javax.annotation.PostConstruct; | ||||
import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
import java.math.RoundingMode; | import java.math.RoundingMode; | ||||
@Slf4j | @Slf4j | ||||
public class MonitorTaskScheduler { | public class MonitorTaskScheduler { | ||||
private final ThreadPoolTaskScheduler taskScheduler; | |||||
// private final ThreadPoolTaskScheduler taskScheduler; | |||||
private ScheduledFuture<?> scheduledTask; | private ScheduledFuture<?> scheduledTask; | ||||
@Autowired | @Autowired | ||||
private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper; | private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper; | ||||
@Autowired | @Autowired | ||||
private EmailUtils emailUtils; | private EmailUtils emailUtils; | ||||
public MonitorTaskScheduler( ) { | |||||
@Autowired | |||||
private ISysDictDataService iSysDictDataService; | |||||
@Autowired | |||||
private SpringTemplateEngine templateEngine; | |||||
/* public MonitorTaskScheduler( ) { | |||||
this.taskScheduler = new ThreadPoolTaskScheduler(); | this.taskScheduler = new ThreadPoolTaskScheduler(); | ||||
this.taskScheduler.setPoolSize(1); | this.taskScheduler.setPoolSize(1); | ||||
this.taskScheduler.initialize(); | this.taskScheduler.initialize(); | ||||
} | |||||
}*/ | |||||
@PostConstruct | |||||
/* @PostConstruct | |||||
public void init() { | public void init() { | ||||
// 启动时从数据库加载初始配置 | // 启动时从数据库加载初始配置 | ||||
rescheduleTask(); | rescheduleTask(); | ||||
new CronTrigger(cron) | new CronTrigger(cron) | ||||
); | ); | ||||
} | } | ||||
} | |||||
}*/ | |||||
//比对商品价格编号是否超过了阈值 并记录 | //比对商品价格编号是否超过了阈值 并记录 | ||||
public void monitorWarn(ZsOperationWarnconfig zsOperationWarnconfig) { | public void monitorWarn(ZsOperationWarnconfig zsOperationWarnconfig) { | ||||
String curUrl = zsOperationGoods.getGoodsSkuUrl(); | String curUrl = zsOperationGoods.getGoodsSkuUrl(); | ||||
//3.根据url 获取商品最新信息 | //3.根据url 获取商品最新信息 | ||||
log.info("调用接口开始"); | log.info("调用接口开始"); | ||||
Map<String, Object> reMap = HttpUtil.sendGetRequest(curUrl,true,zsOperationGoods.getPlatform()); | |||||
Map<String, Object> reMap = HttpUtil.sendGetRequest(curUrl,false,zsOperationGoods.getPlatform()); | |||||
log.info("调用接口结束"); | log.info("调用接口结束"); | ||||
try { | |||||
Thread.sleep(10000); | |||||
} catch (InterruptedException e) { | |||||
e.printStackTrace(); | |||||
} | |||||
if ((boolean)reMap.get("success")) { | if ((boolean)reMap.get("success")) { | ||||
List dataList = (List)reMap.get("data"); | List dataList = (List)reMap.get("data"); | ||||
Map dataMap = (Map)dataList.get(0); | Map dataMap = (Map)dataList.get(0); | ||||
String receiveEmailStr = zsOperationSendconfig.getConfigValue(); | String receiveEmailStr = zsOperationSendconfig.getConfigValue(); | ||||
String[] receiveEmails = receiveEmailStr.split(","); | String[] receiveEmails = receiveEmailStr.split(","); | ||||
for (String receiveEmail : receiveEmails) { | for (String receiveEmail : receiveEmails) { | ||||
String platformName = iSysDictDataService.selectDictLabel("zs_operation_platform",zsOperationGoods.getPlatform()); | |||||
String title = "Digital System 系统提醒:您所监控的 "+platformName+" 商品已发生价格波动"; | |||||
WarnEmail warnEmail = new WarnEmail(); | |||||
warnEmail.setPlatformName(platformName); | |||||
warnEmail.setSkuName(zsOperationGoods.getGoodsSkuName()); | |||||
warnEmail.setSkuSn(newSn); | |||||
warnEmail.setSkuUrl(curUrl); | |||||
warnEmail.setWarnTime(warnDate); | |||||
warnEmail.setCurPrice(initPrice.toString()); | |||||
warnEmail.setNewPrice(newPrice.toString()); | |||||
warnEmail.setImagePath((String)dataMap.get("screenshotUrl")); | |||||
Context context = new Context(); | |||||
context.setVariable("warnEmail", warnEmail); | |||||
String warnContentHtml = templateEngine.process("warnEmail", context); | |||||
//发送数据 1立刻发送 0 9:00-18:00 发送 | //发送数据 1立刻发送 0 9:00-18:00 发送 | ||||
String warnTimeRange = zsOperationWarnconfig.getWarnTimeRange(); | String warnTimeRange = zsOperationWarnconfig.getWarnTimeRange(); | ||||
if ("1".equals(warnTimeRange)) { | if ("1".equals(warnTimeRange)) { | ||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,"商品价格变化预警 商品名=:"+zsOperationGoods.getGoodsSkuName(),warnContent,zsOperationSendconfig.getSmtpId()); | |||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId()); | |||||
} else { | } else { | ||||
if (isBetween9And18()) { | if (isBetween9And18()) { | ||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,"商品价格变化预警 商品名=:"+zsOperationGoods.getGoodsSkuName(),warnContent,zsOperationSendconfig.getSmtpId()); | |||||
emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId()); | |||||
} | } | ||||
} | } | ||||
} | } |
import com.amazonaws.retry.v2.SimpleRetryPolicy; | import com.amazonaws.retry.v2.SimpleRetryPolicy; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.apache.http.client.HttpClient; | |||||
import org.apache.http.client.HttpRequestRetryHandler; | |||||
import org.apache.http.impl.client.HttpClientBuilder; | import org.apache.http.impl.client.HttpClientBuilder; | ||||
import org.apache.http.impl.client.HttpClients; | |||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | |||||
import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | ||||
// 发送GET请求 | // 发送GET请求 | ||||
log.info("开始时间="+getdate()); | log.info("开始时间="+getdate()); | ||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()); | |||||
/* HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()); | |||||
factory.setConnectTimeout(300000); // 连接超时,单位为毫秒 | factory.setConnectTimeout(300000); // 连接超时,单位为毫秒 | ||||
factory.setReadTimeout(300000); // 读取超时,单位为毫秒 | factory.setReadTimeout(300000); // 读取超时,单位为毫秒 | ||||
RestTemplate restTemplate = new RestTemplate(factory); | RestTemplate restTemplate = new RestTemplate(factory); | ||||
ResponseEntity<Map> response = restTemplate.getForEntity(builder.toUriString(), Map.class);*/ | |||||
RestTemplate restTemplate = createRobustRestTemplate(); | |||||
ResponseEntity<Map> response = restTemplate.getForEntity(builder.toUriString(), Map.class); | ResponseEntity<Map> response = restTemplate.getForEntity(builder.toUriString(), Map.class); | ||||
log.info("成功结束时间="+getdate()); | |||||
Map body = response.getBody(); | Map body = response.getBody(); | ||||
Long end = System.currentTimeMillis(); | Long end = System.currentTimeMillis(); | ||||
log.info("调用获取商品最新信息接口耗时=:"+(end-start)); | |||||
log.info("调用获取商品最新信息接口成功耗时=:"+(end-start)); | |||||
return body; | return body; | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
log.info("结束时间="+getdate()); | |||||
log.info("失败结束时间="+getdate()); | |||||
Long end = System.currentTimeMillis(); | |||||
log.info("调用获取商品最新信息接口失败耗时=:"+(end-start)); | |||||
/* if (count<1) { | /* if (count<1) { | ||||
count++; | count++; | ||||
send(url,needScreenshot,platform,count); | send(url,needScreenshot,platform,count); | ||||
return formattedTime; | return formattedTime; | ||||
} | } | ||||
public static RestTemplate createRobustRestTemplate() { | |||||
// 配置连接池 | |||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); | |||||
connectionManager.setMaxTotal(10); // 最大连接数:ml-citation{ref="3" data="citationList"} | |||||
connectionManager.setDefaultMaxPerRoute(10); // 每个路由最大连接数:ml-citation{ref="3" data="citationList"} | |||||
// 配置重试策略(最多重试3次) | |||||
HttpRequestRetryHandler retryHandler = (exception, executionCount, context) -> | |||||
executionCount <= 0 && exception instanceof org.apache.http.NoHttpResponseException; | |||||
// 构建HttpClient | |||||
HttpClient httpClient = HttpClients.custom() | |||||
.setConnectionManager(connectionManager) | |||||
.setRetryHandler(retryHandler) // 失败重试策略:ml-citation{ref="5" data="citationList"} | |||||
.setKeepAliveStrategy((response, context) -> 180_000) // Keep-Alive策略:ml-citation{ref="3" data="citationList"} | |||||
.build(); | |||||
// 配置请求工厂 | |||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); | |||||
factory.setConnectTimeout(120000); // 连接超时 | |||||
factory.setReadTimeout(300000); // 读取超时 | |||||
factory.setConnectionRequestTimeout(120000); // 从连接池获取连接超时 | |||||
return new RestTemplate(factory); | |||||
} | |||||
} | } |