fix:即时通知通过STOMP下发

This commit is contained in:
wangff
2025-09-08 14:00:48 +08:00
parent eacc3c6f8d
commit d8cbb78c5d
19 changed files with 390 additions and 33 deletions

View File

@@ -1,6 +1,7 @@
package com.cool.store.service.impl;
import com.alibaba.fastjson.JSON;
import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.dao.EnterpriseUserDAO;
import com.cool.store.entity.EnterpriseUserDO;
@@ -109,7 +110,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
currentUser.setAppType("qw_self_dkf");
currentUser.setUnionid(enterpriseUser.getUnionid());
currentUser.setUserType(enterpriseUser.getUserType());
redisUtilPool.setString(RedisConstant.ACCESS_TOKEN_PREFIX + currentUser.getAccessToken(), JSON.toJSONString(currentUser), Constants.ACTION_TOKEN_EXPIRE);
redisUtilPool.setString(RedisConstant.ACCESS_TOKEN_PREFIX + currentUser.getAccessToken(), JSON.toJSONString(currentUser), CommonConstants.ACTION_TOKEN_EXPIRE);
return currentUser;
}
@@ -121,7 +122,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
}
String refreshToken = getToken();
RefreshUser refreshUser = new RefreshUser(userId, refreshToken, mobile);
redisUtilPool.setString(RedisConstant.REFRESH_TOKEN_PREFIX + refreshToken, JSON.toJSONString(refreshUser), Constants.REFRESH_TOKEN_EXPIRE);
redisUtilPool.setString(RedisConstant.REFRESH_TOKEN_PREFIX + refreshToken, JSON.toJSONString(refreshUser), CommonConstants.REFRESH_TOKEN_EXPIRE);
return refreshUser;
}

View File

@@ -0,0 +1,78 @@
package com.cool.store.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.dao.MessageTemplateDAO;
import com.cool.store.entity.MessageTemplateDO;
import com.cool.store.entity.StoreMessageDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.vo.notice.StoreMessageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* <p>
* 消息下发 服务类
* </p>
*
* @author wangff
* @since 2025/9/5
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class MessageIssueService {
private final MessageTemplateDAO messageTemplateDAO;
private final SimpMessagingTemplate simpMessagingTemplate;
/**
* 下发即时通知消息
*
* @param list 门店消息列表
*/
@Async("generalThreadPool")
public void issueMessage(List<StoreMessageDO> list) {
if (CollectionUtils.isEmpty(list)) return;
log.info("下发即时通知, messageList:{}", JSONObject.toJSONString(list));
try {
Set<Long> messageTemplateIds = CollStreamUtil.toSet(list, StoreMessageDO::getMessageTemplateId);
List<MessageTemplateDO> messageTemplateList = messageTemplateDAO.getByIds(new ArrayList<>(messageTemplateIds));
Map<Long, MessageTemplateDO> messageTemplateMap = CollStreamUtil.toMap(messageTemplateList, MessageTemplateDO::getId, v -> v);
for (StoreMessageDO storeMessageDO : list) {
if (StringUtils.isNotBlank(storeMessageDO.getOperatorList())) {
String[] userIds = storeMessageDO.getOperatorList().split(",");
if (ArrayUtil.isNotEmpty(userIds)) {
MessageTemplateDO messageTemplateDO = messageTemplateMap.get(storeMessageDO.getMessageTemplateId());
if (Objects.isNull(messageTemplateDO)) {
throw new ServiceException(ErrorCodeEnum.MESSAGE_NOT_EXIST);
}
StoreMessageVO storeMessageVO = BeanUtil.toBean(storeMessageDO, StoreMessageVO.class);
BeanUtil.copyProperties(messageTemplateDO, storeMessageVO);
String message = JSONObject.toJSONString(storeMessageVO);
for (String userId : userIds) {
try {
simpMessagingTemplate.convertAndSend("/queue/message/" + userId, message);
} catch (MessagingException e) {
log.info("即时通知下发异常, userId:{}, error:{}", userId, e.getMessage());
}
}
}
}
}
} catch (Exception e) {
log.info("即时通知下发异常", e);
}
}
}

View File

@@ -3,7 +3,6 @@ package com.cool.store.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.context.PartnerUserHolder;
import com.cool.store.dao.*;
import com.cool.store.dto.notice.CommonDTO;
import com.cool.store.dto.notice.MessageTemplateCountDTO;
@@ -25,11 +24,9 @@ import com.cool.store.vo.PartnerUserInfoVO;
import com.cool.store.vo.notice.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -65,6 +62,8 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
EnterpriseUserDAO enterpriseUserDAO;
@Resource
MatterConfigDAO matterConfigDAO;
@Resource
MessageIssueService messageIssueService;
@@ -153,6 +152,7 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
log.info("未找到待发布消息模板");
}
List<StoreMessageDO> realtimeMessageList = new ArrayList<>();
list.stream().forEach(x -> {
List<StoreMessageDO> result = new ArrayList<>();
storeAreaDTOS.forEach(y->{
@@ -174,6 +174,9 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
result.add(storeMessageDO);
});
storeMessageDAO.batchInsert(result);
if (MatterTypeEnum.REALTIME.getCode().equals(request.getMatterType())) {
realtimeMessageList.addAll(result);
}
});
List<Long> updateIds = list.stream().map(MessageTemplateDO::getId).collect(Collectors.toList());
@@ -181,6 +184,8 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
JSONObject.toJSONString(request.getStoreInfoList()),
JSONObject.toJSONString(request.getUserInfoList()),
userId);
// 即时消息下发
messageIssueService.issueMessage(realtimeMessageList);
return Boolean.TRUE;
}
@@ -271,6 +276,7 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
batchPublishRequest.setIds(Arrays.asList(messageTemplateDO.getId()));
batchPublishRequest.setStoreInfoList(JSONObject.parseArray(storeInfo, CommonDTO.class));
batchPublishRequest.setUserInfoList(JSONObject.parseArray(userInfo, CommonDTO.class));
batchPublishRequest.setMatterType(matterConfig.getMatterType());
try {
batchPublishMessageTemplate(batchPublishRequest,"");
} catch (ServiceException e) {

View File

@@ -2,6 +2,7 @@ package com.cool.store.service.login;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.context.LoginUserInfo;
@@ -57,7 +58,7 @@ public abstract class LoginBaseService implements LoginStrategy {
String errorCount = redisUtilPool.getString(errorPasswordCountKey);
//判断密码错误次数
if (StringUtils.isNotBlank(errorCount)) {
if (Integer.parseInt(errorCount) >= Constants.MAX_ERROR_PASSWORD_COUNT) {
if (Integer.parseInt(errorCount) >= CommonConstants.MAX_ERROR_PASSWORD_COUNT) {
return ResponseResult.fail(ErrorCodeEnum.PASSWORD_ERROR_MAX_COUNT, errorCount);
}
}
@@ -100,6 +101,6 @@ public abstract class LoginBaseService implements LoginStrategy {
CurrentUser currentUser = enterpriseService.getLoginInfo(userLoginDO.getMobile());
UserBaseInfoVO userBAseInfoVO = BeanUtil.toBean(currentUser, UserBaseInfoVO.class);
RefreshUser refreshUser = enterpriseService.getRefreshUser(userLoginDO.getUserId(), userLoginDO.getMobile());
return new UserLoginVO(currentUser.getAccessToken(), refreshUser.getRefreshToken(), Constants.ACTION_TOKEN_EXPIRE, userBAseInfoVO);
return new UserLoginVO(currentUser.getAccessToken(), refreshUser.getRefreshToken(), CommonConstants.ACTION_TOKEN_EXPIRE, userBAseInfoVO);
}
}

View File

@@ -1,6 +1,7 @@
package com.cool.store.service.login.impl;
import com.aliyun.core.utils.StringUtils;
import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.dto.login.UserLoginDTO;
import com.cool.store.entity.login.UserLoginDO;
@@ -39,7 +40,7 @@ public class PasswordLoginServiceImpl extends LoginBaseService {
if (StringUtils.isBlank(userLoginDO.getPassword())) {
return ResponseResult.fail(ErrorCodeEnum.IMPROVE_USER_INFO);
}
String password = Md5Utils.md5(param.getPassword() + Constants.USER_AUTH_KEY);
String password = Md5Utils.md5(param.getPassword() + CommonConstants.USER_AUTH_KEY);
if (!password.equals(userLoginDO.getPassword())) {
String errorPasswordCountKey = MessageFormat.format(RedisConstant.ERROR_PASSWORD_COUNT_KEY, LocalDate.now(), param.getMobile());
Long errorNum = redisUtilPool.incrby(errorPasswordCountKey, 1);

View File

@@ -220,23 +220,4 @@ public class Constants
public static final String WANG_LEI_JOB_NUMBER = "19060164";
/**
* 密码最大错误次数
*/
public static final int MAX_ERROR_PASSWORD_COUNT = 5;
/**
* 用户密码
*/
public static final String USER_AUTH_KEY = "user_auth_key";
/**
* accessToken有效期单位秒
*/
public static final int ACTION_TOKEN_EXPIRE = 24 * 60 * 60;
/**
* refreshToken有效期单位秒
*/
public static final int REFRESH_TOKEN_EXPIRE = 30 * 24 * 60 * 60;
}