fix:即时通知通过STOMP下发
This commit is contained in:
@@ -201,5 +201,23 @@ public class CommonConstants {
|
|||||||
|
|
||||||
public static final String WX_SELF_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
|
public static final String WX_SELF_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码最大错误次数
|
||||||
|
*/
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public enum MatterTypeEnum {
|
|||||||
SERVICE_PACKAGE(4,"服务包"),
|
SERVICE_PACKAGE(4,"服务包"),
|
||||||
RESTOCK(5,"补货"),
|
RESTOCK(5,"补货"),
|
||||||
INVENTORY(6,"盘点"),
|
INVENTORY(6,"盘点"),
|
||||||
|
REALTIME(7, "即时消息"),
|
||||||
;
|
;
|
||||||
|
|
||||||
MatterTypeEnum(Integer code, String message) {
|
MatterTypeEnum(Integer code, String message) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public enum ModuleCodeEnum {
|
|||||||
DISH(3,"菜品",Arrays.asList(MatterTypeEnum.NOTICE)),
|
DISH(3,"菜品",Arrays.asList(MatterTypeEnum.NOTICE)),
|
||||||
FRANCHISE(4,"加盟",Arrays.asList(MatterTypeEnum.NOTICE)),
|
FRANCHISE(4,"加盟",Arrays.asList(MatterTypeEnum.NOTICE)),
|
||||||
//其他(投诉与客户服务、临时通知)
|
//其他(投诉与客户服务、临时通知)
|
||||||
OTHER(5,"其他",Arrays.asList(MatterTypeEnum.NOTICE)),
|
OTHER(5,"其他",Arrays.asList(MatterTypeEnum.NOTICE, MatterTypeEnum.REALTIME)),
|
||||||
;
|
;
|
||||||
|
|
||||||
ModuleCodeEnum(Integer code, String message,List<MatterTypeEnum> matterTypeEnums) {
|
ModuleCodeEnum(Integer code, String message,List<MatterTypeEnum> matterTypeEnums) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public enum SceneEnum {
|
|||||||
RESTOCK(35, "补货", "", MatterTypeEnum.LOGISTICS),
|
RESTOCK(35, "补货", "", MatterTypeEnum.LOGISTICS),
|
||||||
INVENTORY(40, "盘点", "", MatterTypeEnum.LOGISTICS),
|
INVENTORY(40, "盘点", "", MatterTypeEnum.LOGISTICS),
|
||||||
|
|
||||||
|
REALTIME(45, "即时消息", "", MatterTypeEnum.REALTIME),
|
||||||
;
|
;
|
||||||
|
|
||||||
private Integer sceneCode;
|
private Integer sceneCode;
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.cool.store.executor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.cool.store.constants.CommonConstants;
|
||||||
|
import com.cool.store.utils.UUIDUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.MDC;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhangchenbiao
|
||||||
|
* @FileName: MdcTaskExecutor
|
||||||
|
* @Description:
|
||||||
|
* @date 2021-11-02 21:00
|
||||||
|
*/
|
||||||
|
public class MdcTaskExecutor extends ThreadPoolTaskExecutor {
|
||||||
|
private Logger log = LoggerFactory.getLogger(MdcTaskExecutor.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Future<T> submit(Callable<T> task) {
|
||||||
|
Map<String, String> context = MDC.getCopyOfContextMap();
|
||||||
|
return super.submit(() -> {
|
||||||
|
T result;
|
||||||
|
if (context != null) {
|
||||||
|
//将父线程的MDC内容传给子线程
|
||||||
|
MDC.setContextMap(context);
|
||||||
|
}
|
||||||
|
//直接给子线程设置MDC
|
||||||
|
setTraceIdIfAbsent();
|
||||||
|
try {
|
||||||
|
//执行任务
|
||||||
|
result = task.call();
|
||||||
|
} finally {
|
||||||
|
log.info("ThreadMonitor:{}info:ExecutedTasks->{},totalTask->{}, RunningTasks->{}, PendingTasks->{},corePoolSize-{},currentPoolSize->{},LargestPoolSize->{}",
|
||||||
|
this.getThreadNamePrefix(),this.getThreadPoolExecutor().getCompletedTaskCount(),this.getThreadPoolExecutor().getTaskCount(),
|
||||||
|
this.getActiveCount(),this.getThreadPoolExecutor().getQueue().size(),this.getCorePoolSize(),
|
||||||
|
this.getPoolSize(),this.getThreadPoolExecutor().getLargestPoolSize());
|
||||||
|
try {
|
||||||
|
MDC.clear();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("MDC clear exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable task) {
|
||||||
|
log.info("mdc thread pool task executor execute");
|
||||||
|
Map<String, String> context = MDC.getCopyOfContextMap();
|
||||||
|
super.execute(() -> {
|
||||||
|
if (context != null) {
|
||||||
|
//将父线程的MDC内容传给子线程
|
||||||
|
MDC.setContextMap(context);
|
||||||
|
}
|
||||||
|
//直接给子线程设置MDC
|
||||||
|
setTraceIdIfAbsent();
|
||||||
|
try {
|
||||||
|
//执行任务
|
||||||
|
task.run();
|
||||||
|
} finally {
|
||||||
|
log.info("ThreadMonitor:{}info:ExecutedTasks->{},totalTask->{}, RunningTasks->{}, PendingTasks->{},corePoolSize-{},currentPoolSize->{},LargestPoolSize->{}",
|
||||||
|
this.getThreadNamePrefix(),this.getThreadPoolExecutor().getCompletedTaskCount(),this.getThreadPoolExecutor().getTaskCount(),
|
||||||
|
this.getActiveCount(),this.getThreadPoolExecutor().getQueue().size(),this.getCorePoolSize(),
|
||||||
|
this.getPoolSize(),this.getThreadPoolExecutor().getLargestPoolSize());
|
||||||
|
try {
|
||||||
|
MDC.clear();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("MDC clear exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTraceIdIfAbsent() {
|
||||||
|
String key = CommonConstants.REQUEST_ID;
|
||||||
|
String value = UUIDUtils.get32UUID();
|
||||||
|
String k = MDC.get(key);
|
||||||
|
if (StringUtils.isBlank(value)) {
|
||||||
|
value = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(k)) {
|
||||||
|
MDC.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.cool.store.executor;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.task.TaskExecutor;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 线程池配置类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/9/5
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class ThreadPoolTaskConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用线程池
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public TaskExecutor generalThreadPool() {
|
||||||
|
int cores = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
ThreadPoolTaskExecutor executor = new MdcTaskExecutor();
|
||||||
|
// 核心线程数目
|
||||||
|
executor.setCorePoolSize(cores*2);
|
||||||
|
// 指定最大线程数
|
||||||
|
executor.setMaxPoolSize(200);
|
||||||
|
// 队列中最大的数目
|
||||||
|
executor.setQueueCapacity(5000);
|
||||||
|
// 线程名称前缀
|
||||||
|
executor.setThreadNamePrefix("generalThreadPool_");
|
||||||
|
// 对拒绝task的处理策略
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
// 线程空闲后的最大存活时间
|
||||||
|
executor.setKeepAliveSeconds(60);
|
||||||
|
// 加载
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,4 +22,6 @@ public class BatchPublishRequest {
|
|||||||
@ApiModelProperty( "默认处理人信息 type[person position userGroup organization]")
|
@ApiModelProperty( "默认处理人信息 type[person position userGroup organization]")
|
||||||
List<CommonDTO> userInfoList;
|
List<CommonDTO> userInfoList;
|
||||||
|
|
||||||
|
@ApiModelProperty("事项类型")
|
||||||
|
private Integer matterType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.cool.store.service.impl;
|
package com.cool.store.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cool.store.constants.CommonConstants;
|
||||||
import com.cool.store.constants.RedisConstant;
|
import com.cool.store.constants.RedisConstant;
|
||||||
import com.cool.store.dao.EnterpriseUserDAO;
|
import com.cool.store.dao.EnterpriseUserDAO;
|
||||||
import com.cool.store.entity.EnterpriseUserDO;
|
import com.cool.store.entity.EnterpriseUserDO;
|
||||||
@@ -109,7 +110,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
|
|||||||
currentUser.setAppType("qw_self_dkf");
|
currentUser.setAppType("qw_self_dkf");
|
||||||
currentUser.setUnionid(enterpriseUser.getUnionid());
|
currentUser.setUnionid(enterpriseUser.getUnionid());
|
||||||
currentUser.setUserType(enterpriseUser.getUserType());
|
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;
|
return currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
|
|||||||
}
|
}
|
||||||
String refreshToken = getToken();
|
String refreshToken = getToken();
|
||||||
RefreshUser refreshUser = new RefreshUser(userId, refreshToken, mobile);
|
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;
|
return refreshUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package com.cool.store.service.impl;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.cool.store.context.LoginUserInfo;
|
import com.cool.store.context.LoginUserInfo;
|
||||||
import com.cool.store.context.PartnerUserHolder;
|
|
||||||
import com.cool.store.dao.*;
|
import com.cool.store.dao.*;
|
||||||
import com.cool.store.dto.notice.CommonDTO;
|
import com.cool.store.dto.notice.CommonDTO;
|
||||||
import com.cool.store.dto.notice.MessageTemplateCountDTO;
|
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.cool.store.vo.notice.*;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -65,6 +62,8 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
EnterpriseUserDAO enterpriseUserDAO;
|
EnterpriseUserDAO enterpriseUserDAO;
|
||||||
@Resource
|
@Resource
|
||||||
MatterConfigDAO matterConfigDAO;
|
MatterConfigDAO matterConfigDAO;
|
||||||
|
@Resource
|
||||||
|
MessageIssueService messageIssueService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -153,6 +152,7 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
log.info("未找到待发布消息模板");
|
log.info("未找到待发布消息模板");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<StoreMessageDO> realtimeMessageList = new ArrayList<>();
|
||||||
list.stream().forEach(x -> {
|
list.stream().forEach(x -> {
|
||||||
List<StoreMessageDO> result = new ArrayList<>();
|
List<StoreMessageDO> result = new ArrayList<>();
|
||||||
storeAreaDTOS.forEach(y->{
|
storeAreaDTOS.forEach(y->{
|
||||||
@@ -174,6 +174,9 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
result.add(storeMessageDO);
|
result.add(storeMessageDO);
|
||||||
});
|
});
|
||||||
storeMessageDAO.batchInsert(result);
|
storeMessageDAO.batchInsert(result);
|
||||||
|
if (MatterTypeEnum.REALTIME.getCode().equals(request.getMatterType())) {
|
||||||
|
realtimeMessageList.addAll(result);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
List<Long> updateIds = list.stream().map(MessageTemplateDO::getId).collect(Collectors.toList());
|
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.getStoreInfoList()),
|
||||||
JSONObject.toJSONString(request.getUserInfoList()),
|
JSONObject.toJSONString(request.getUserInfoList()),
|
||||||
userId);
|
userId);
|
||||||
|
// 即时消息下发
|
||||||
|
messageIssueService.issueMessage(realtimeMessageList);
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,6 +276,7 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
batchPublishRequest.setIds(Arrays.asList(messageTemplateDO.getId()));
|
batchPublishRequest.setIds(Arrays.asList(messageTemplateDO.getId()));
|
||||||
batchPublishRequest.setStoreInfoList(JSONObject.parseArray(storeInfo, CommonDTO.class));
|
batchPublishRequest.setStoreInfoList(JSONObject.parseArray(storeInfo, CommonDTO.class));
|
||||||
batchPublishRequest.setUserInfoList(JSONObject.parseArray(userInfo, CommonDTO.class));
|
batchPublishRequest.setUserInfoList(JSONObject.parseArray(userInfo, CommonDTO.class));
|
||||||
|
batchPublishRequest.setMatterType(matterConfig.getMatterType());
|
||||||
try {
|
try {
|
||||||
batchPublishMessageTemplate(batchPublishRequest,"");
|
batchPublishMessageTemplate(batchPublishRequest,"");
|
||||||
} catch (ServiceException e) {
|
} catch (ServiceException e) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.cool.store.service.login;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cool.store.constants.CommonConstants;
|
||||||
import com.cool.store.constants.RedisConstant;
|
import com.cool.store.constants.RedisConstant;
|
||||||
import com.cool.store.context.CurrentUserHolder;
|
import com.cool.store.context.CurrentUserHolder;
|
||||||
import com.cool.store.context.LoginUserInfo;
|
import com.cool.store.context.LoginUserInfo;
|
||||||
@@ -57,7 +58,7 @@ public abstract class LoginBaseService implements LoginStrategy {
|
|||||||
String errorCount = redisUtilPool.getString(errorPasswordCountKey);
|
String errorCount = redisUtilPool.getString(errorPasswordCountKey);
|
||||||
//判断密码错误次数
|
//判断密码错误次数
|
||||||
if (StringUtils.isNotBlank(errorCount)) {
|
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);
|
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());
|
CurrentUser currentUser = enterpriseService.getLoginInfo(userLoginDO.getMobile());
|
||||||
UserBaseInfoVO userBAseInfoVO = BeanUtil.toBean(currentUser, UserBaseInfoVO.class);
|
UserBaseInfoVO userBAseInfoVO = BeanUtil.toBean(currentUser, UserBaseInfoVO.class);
|
||||||
RefreshUser refreshUser = enterpriseService.getRefreshUser(userLoginDO.getUserId(), userLoginDO.getMobile());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.cool.store.service.login.impl;
|
package com.cool.store.service.login.impl;
|
||||||
|
|
||||||
import com.aliyun.core.utils.StringUtils;
|
import com.aliyun.core.utils.StringUtils;
|
||||||
|
import com.cool.store.constants.CommonConstants;
|
||||||
import com.cool.store.constants.RedisConstant;
|
import com.cool.store.constants.RedisConstant;
|
||||||
import com.cool.store.dto.login.UserLoginDTO;
|
import com.cool.store.dto.login.UserLoginDTO;
|
||||||
import com.cool.store.entity.login.UserLoginDO;
|
import com.cool.store.entity.login.UserLoginDO;
|
||||||
@@ -39,7 +40,7 @@ public class PasswordLoginServiceImpl extends LoginBaseService {
|
|||||||
if (StringUtils.isBlank(userLoginDO.getPassword())) {
|
if (StringUtils.isBlank(userLoginDO.getPassword())) {
|
||||||
return ResponseResult.fail(ErrorCodeEnum.IMPROVE_USER_INFO);
|
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())) {
|
if (!password.equals(userLoginDO.getPassword())) {
|
||||||
String errorPasswordCountKey = MessageFormat.format(RedisConstant.ERROR_PASSWORD_COUNT_KEY, LocalDate.now(), param.getMobile());
|
String errorPasswordCountKey = MessageFormat.format(RedisConstant.ERROR_PASSWORD_COUNT_KEY, LocalDate.now(), param.getMobile());
|
||||||
Long errorNum = redisUtilPool.incrby(errorPasswordCountKey, 1);
|
Long errorNum = redisUtilPool.incrby(errorPasswordCountKey, 1);
|
||||||
|
|||||||
@@ -220,23 +220,4 @@ public class Constants
|
|||||||
|
|
||||||
public static final String WANG_LEI_JOB_NUMBER = "19060164";
|
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,65 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>dev</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>dev2</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>dev2</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>local</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<profileActive>local</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>test</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>test</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>test3</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>test3</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>ab</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>ab</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>online</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>online</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>hd</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>hd</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>zcb</id>
|
||||||
|
<properties>
|
||||||
|
<profileActive>zcb</profileActive>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ public class SignValidateFilter implements Filter {
|
|||||||
"/zxjp/mini/program/v1/partnerManage/openArea/areaApplyQuery",
|
"/zxjp/mini/program/v1/partnerManage/openArea/areaApplyQuery",
|
||||||
"/zxjp/**/api/audit/result",
|
"/zxjp/**/api/audit/result",
|
||||||
"/zxjp/**/api/license",
|
"/zxjp/**/api/license",
|
||||||
"/zxjp/mini/line/getRegionPayPic"
|
"/zxjp/mini/line/getRegionPayPic",
|
||||||
|
"/zxjp/ws/**"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ public class TokenValidateFilter implements Filter {
|
|||||||
"/zxjp/pc/video/**",
|
"/zxjp/pc/video/**",
|
||||||
"/zxjp/**/api/license",
|
"/zxjp/**/api/license",
|
||||||
"/zxjp/pc/v3/login/accountLogin",
|
"/zxjp/pc/v3/login/accountLogin",
|
||||||
"/zxjp/pc/v3/login/refreshLogin"
|
"/zxjp/pc/v3/login/refreshLogin",
|
||||||
|
"/zxjp/ws/**"
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.cool.store.config.websocket;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.MessageChannel;
|
||||||
|
import org.springframework.messaging.simp.config.ChannelRegistration;
|
||||||
|
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompCommand;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
|
||||||
|
import org.springframework.messaging.support.ChannelInterceptor;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||||
|
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* WebSocket配置类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/9/2
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocketMessageBroker
|
||||||
|
@Slf4j
|
||||||
|
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||||
|
registry.addEndpoint("/ws/zxzs")
|
||||||
|
.setAllowedOrigins("*")
|
||||||
|
.withSockJS(); // 启用SockJS支持
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||||
|
// 配置消息代理
|
||||||
|
registry.enableSimpleBroker("/topic", "/queue"); // 启用简单代理,用于广播和点对点消息
|
||||||
|
registry.setApplicationDestinationPrefixes("/app"); // 设置应用程序端点前缀
|
||||||
|
// registry.setUserDestinationPrefix("/user");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||||
|
// registration.interceptors(new ChannelInterceptor() {
|
||||||
|
// @Override
|
||||||
|
// public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||||
|
// StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
||||||
|
//
|
||||||
|
// if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
||||||
|
// // 从STOMP头部获取login字段作为用户标识
|
||||||
|
// String login = accessor.getLogin();
|
||||||
|
// log.info("用户login:{}", login);
|
||||||
|
// if (login != null && !login.isEmpty()) {
|
||||||
|
// // 设置用户身份
|
||||||
|
// accessor.setUser(() -> login);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return message;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.cool.store.response.ResponseResult;
|
|||||||
import com.cool.store.service.login.LoginBaseService;
|
import com.cool.store.service.login.LoginBaseService;
|
||||||
import com.cool.store.service.login.LoginStrategy;
|
import com.cool.store.service.login.LoginStrategy;
|
||||||
import com.cool.store.utils.SpringContextUtil;
|
import com.cool.store.utils.SpringContextUtil;
|
||||||
|
import com.cool.store.vo.login.UserLoginVO;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -28,13 +29,13 @@ public class LoginController {
|
|||||||
|
|
||||||
@ApiOperation("账号密码登录")
|
@ApiOperation("账号密码登录")
|
||||||
@PostMapping("/accountLogin")
|
@PostMapping("/accountLogin")
|
||||||
public ResponseResult accountLogin(@RequestBody UserLoginDTO param) {
|
public ResponseResult<UserLoginVO> accountLogin(@RequestBody UserLoginDTO param) {
|
||||||
return SpringContextUtil.getBean(param.getLoginType().getClazzName(), LoginStrategy.class).login(param);
|
return SpringContextUtil.getBean(param.getLoginType().getClazzName(), LoginStrategy.class).login(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("refresh登录")
|
@ApiOperation("refresh登录")
|
||||||
@PostMapping("/refreshLogin")
|
@PostMapping("/refreshLogin")
|
||||||
public ResponseResult refreshLogin(@RequestBody UserRefreshLoginDTO param) {
|
public ResponseResult<UserLoginVO> refreshLogin(@RequestBody UserRefreshLoginDTO param) {
|
||||||
return loginBaseService.refreshLogin(param);
|
return loginBaseService.refreshLogin(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -135,7 +135,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.0.7</version>
|
<version>5.7.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.aliyun</groupId>
|
<groupId>com.aliyun</groupId>
|
||||||
|
|||||||
Reference in New Issue
Block a user