【同步】BOOT 和 CLOUD 的功能
parent
6e492e1e6b
commit
ff4ed31c1b
|
|
@ -0,0 +1,104 @@
|
|||
package cn.iocoder.yudao.module.iot.core.messagebus.core.rabbitmq;
|
||||
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
|
||||
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.AcknowledgeMode;
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.MessageBuilder;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.amqp.core.TopicExchange;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基于 RabbitMQ 的 {@link IotMessageBus} 实现类
|
||||
*
|
||||
* @author ywc
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class IotRabbitMQMessageBus implements IotMessageBus {
|
||||
|
||||
private static final String ROUTING_KEY = "#";
|
||||
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
|
||||
private final RabbitAdmin rabbitAdmin;
|
||||
|
||||
@Getter
|
||||
private final List<IotMessageSubscriber<?>> subscribers = new ArrayList<>();
|
||||
|
||||
private final List<SimpleMessageListenerContainer> containers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void post(String topic, Object message) {
|
||||
rabbitTemplate.send(topic, ROUTING_KEY, MessageBuilder.withBody(JsonUtils.toJsonByte(message)).build());
|
||||
log.info("[post][topic({}) 发送消息({})]", topic, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public void register(IotMessageSubscriber<?> subscriber) {
|
||||
Type type = TypeUtil.getTypeArgument(subscriber.getClass(), 0);
|
||||
if (type == null) {
|
||||
throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
|
||||
}
|
||||
|
||||
// 1.1 声明交换机、队列和绑定关系
|
||||
Queue queue = new Queue(subscriber.getGroup(), true, false, false);
|
||||
rabbitAdmin.declareQueue(queue);
|
||||
TopicExchange exchange = new TopicExchange(subscriber.getTopic());
|
||||
rabbitAdmin.declareExchange(exchange);
|
||||
Binding binding = BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
|
||||
rabbitAdmin.declareBinding(binding);
|
||||
|
||||
// 1.2 创建消费容器
|
||||
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(rabbitTemplate.getConnectionFactory());
|
||||
container.setQueues(queue);
|
||||
container.setConcurrentConsumers(1);
|
||||
container.setMaxConcurrentConsumers(10);
|
||||
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
|
||||
container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
|
||||
try {
|
||||
subscriber.onMessage(JsonUtils.parseObject(message.getBody(), type));
|
||||
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
|
||||
} catch (Exception ex) {
|
||||
log.error("[onMessage][topic({}/{}) message({}) 消费者({}) 处理异常]",
|
||||
subscriber.getTopic(), subscriber.getGroup(), message, subscriber.getClass().getName(), ex);
|
||||
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
|
||||
}
|
||||
});
|
||||
container.start();
|
||||
|
||||
// 2. 保存消费者引用
|
||||
containers.add(container);
|
||||
subscribers.add(subscriber);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
for (SimpleMessageListenerContainer container : containers) {
|
||||
try {
|
||||
container.stop();
|
||||
container.destroy();
|
||||
log.info("[destroy][关闭 RabbitMQ 消费者容器成功]");
|
||||
} catch (Exception e) {
|
||||
log.error("[destroy][关闭 RabbitMQ 消费者容器异常]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
|||
public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) {
|
||||
// 校验关联数据是否存在
|
||||
sceneRuleService.validateSceneRuleList(createReqVO.getSceneRuleIds());
|
||||
adminUserApi.validateUserList(createReqVO.getReceiveUserIds());
|
||||
adminUserApi.validateUserList(createReqVO.getReceiveUserIds()).checkError();
|
||||
validateReceiveTemplates(createReqVO);
|
||||
|
||||
// 插入
|
||||
|
|
@ -62,7 +62,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
|||
validateAlertConfigExists(updateReqVO.getId());
|
||||
// 校验关联数据是否存在
|
||||
sceneRuleService.validateSceneRuleList(updateReqVO.getSceneRuleIds());
|
||||
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds());
|
||||
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds()).checkError();
|
||||
validateReceiveTemplates(updateReqVO);
|
||||
|
||||
// 更新
|
||||
|
|
@ -122,4 +122,4 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
|||
return alertConfigMapper.selectListBySceneRuleIdAndStatus(sceneRuleId, status);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,15 +103,15 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction {
|
|||
switch (typeEnum) {
|
||||
case SMS:
|
||||
smsSendApi.sendSingleSmsToAdmin(new SmsSendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams)).checkError();
|
||||
break;
|
||||
case MAIL:
|
||||
mailSendApi.sendSingleMailToAdmin(new MailSendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams)).checkError();
|
||||
break;
|
||||
case NOTIFY:
|
||||
notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams)).checkError();
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||
throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
|
||||
}
|
||||
// 4.2 校验 sku 是否存在
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(skuId);
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(skuId).getCheckedData();
|
||||
if (sku == null) {
|
||||
throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
|
||||
}
|
||||
|
|
@ -170,9 +170,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||
reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount());
|
||||
|
||||
// 2. 组合数据创建拼团记录
|
||||
MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId());
|
||||
MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()).getCheckedData();
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()).getCheckedData();
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()).getCheckedData();
|
||||
CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku);
|
||||
// 2.1. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP
|
||||
if (!isJoinCombination(record.getHeadId())) {
|
||||
|
|
@ -238,7 +238,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||
.setTemplateTitle(COMBINATION_SUCCESS)
|
||||
.setPage("pages/order/detail?id=" + record.getOrderId()) // 订单详情页
|
||||
.addMessage("thing1", "商品拼团活动") // 活动标题
|
||||
.addMessage("thing2", "恭喜您拼团成功!我们将尽快为您发货。")); // 温馨提示
|
||||
.addMessage("thing2", "恭喜您拼团成功!我们将尽快为您发货。")).checkError(); // 温馨提示
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -345,7 +345,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||
CombinationRecordStatusEnum.FAILED);
|
||||
// 2. 订单取消
|
||||
headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId(),
|
||||
TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getType()));
|
||||
TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getType()).checkError());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -122,9 +122,9 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
|
|||
|
||||
private void validateProductScope(Integer productScope, List<Long> productScopeValues) {
|
||||
if (Objects.equals(PromotionProductScopeEnum.SPU.getScope(), productScope)) {
|
||||
productSpuApi.validateSpuList(productScopeValues);
|
||||
productSpuApi.validateSpuList(productScopeValues).checkError();
|
||||
} else if (Objects.equals(PromotionProductScopeEnum.CATEGORY.getScope(), productScope)) {
|
||||
productCategoryApi.validateCategoryList(productScopeValues);
|
||||
productCategoryApi.validateCategoryList(productScopeValues).checkError();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -333,13 +333,13 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
|
|||
return respVO;
|
||||
}
|
||||
// 2.3 校验商品是否存在
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(spuId).getCheckedData();
|
||||
if (spu == null) {
|
||||
return respVO;
|
||||
}
|
||||
|
||||
// 3.1 获取商品 SKU 列表
|
||||
List<ProductSkuRespDTO> skuList = productSkuApi.getSkuListBySpuId(ListUtil.of(spuId));
|
||||
List<ProductSkuRespDTO> skuList = productSkuApi.getSkuListBySpuId(ListUtil.of(spuId)).getCheckedData();
|
||||
if (BooleanUtil.isTrue(spu.getSubCommissionType())) {
|
||||
// 3.2.1 商品独立分销模式:直接取 SKU 固定佣金
|
||||
// 注意:固定佣金允许为 0,表示商家主动设为零佣金;为空时,也按 0 处理
|
||||
|
|
|
|||
|
|
@ -164,11 +164,11 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
// 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验
|
||||
if (StrUtil.isNotEmpty(reqVO.getOldCode())) {
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
}
|
||||
// 2.2 使用新验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
|
||||
// 3. 更新用户手机
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
|
||||
|
|
@ -178,7 +178,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
public void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO) {
|
||||
// 1.1 获得对应的手机号信息
|
||||
SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo(
|
||||
UserTypeEnum.MEMBER.getValue(), reqVO.getCode());
|
||||
UserTypeEnum.MEMBER.getValue(), reqVO.getCode()).getCheckedData();
|
||||
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
|
||||
// 1.2 校验新手机是否已经被绑定
|
||||
validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber());
|
||||
|
|
@ -193,7 +193,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
MemberUserDO user = validateUserExists(userId);
|
||||
// 校验验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP()));
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
|
||||
// 更新用户密码
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId)
|
||||
|
|
@ -207,7 +207,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
|
||||
// 使用验证码
|
||||
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD,
|
||||
getClientIP()));
|
||||
getClientIP())).checkError();
|
||||
|
||||
// 更新密码
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(user.getId())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package cn.iocoder.yudao.module.system.api.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
|
|
@ -10,6 +12,8 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 角色")
|
||||
|
|
@ -22,4 +26,18 @@ public interface RoleApi {
|
|||
@Parameter(name = "ids", description = "角色编号数组", example = "1,2", required = true)
|
||||
CommonResult<Boolean> validRoleList(@RequestParam("ids") Collection<Long> ids);
|
||||
|
||||
}
|
||||
@GetMapping(PREFIX + "/get")
|
||||
@Operation(summary = "获得角色")
|
||||
@Parameter(name = "id", description = "角色编号", example = "1", required = true)
|
||||
CommonResult<RoleRespDTO> getRole(@RequestParam("id") Long id);
|
||||
|
||||
@GetMapping(PREFIX + "/list")
|
||||
@Operation(summary = "获得角色列表")
|
||||
@Parameter(name = "ids", description = "角色编号数组", example = "1,2", required = true)
|
||||
CommonResult<List<RoleRespDTO>> getRoleList(@RequestParam("ids") Collection<Long> ids);
|
||||
|
||||
default Map<Long, RoleRespDTO> getRoleMap(Collection<Long> ids) {
|
||||
return CollectionUtils.convertMap(getRoleList(ids).getCheckedData(), RoleRespDTO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package cn.iocoder.yudao.module.system.api.permission.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 角色 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class RoleRespDTO {
|
||||
|
||||
/**
|
||||
* 角色编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 角色状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
package cn.iocoder.yudao.module.system.api.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
import cn.iocoder.yudao.module.system.service.permission.RoleService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
|
|
@ -22,4 +26,17 @@ public class RoleApiImpl implements RoleApi {
|
|||
roleService.validateRoleList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<RoleRespDTO> getRole(Long id) {
|
||||
RoleDO role = roleService.getRole(id);
|
||||
return success(BeanUtils.toBean(role, RoleRespDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<RoleRespDTO>> getRoleList(Collection<Long> ids) {
|
||||
List<RoleDO> list = roleService.getRoleList(ids);
|
||||
return success(BeanUtils.toBean(list, RoleRespDTO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue