diff --git a/nla-common/src/main/java/cn/nla/common/config/WebConfig.java b/nla-common/src/main/java/cn/nla/common/config/WebConfig.java index 59cb1af..b7e3d2f 100644 --- a/nla-common/src/main/java/cn/nla/common/config/WebConfig.java +++ b/nla-common/src/main/java/cn/nla/common/config/WebConfig.java @@ -30,7 +30,8 @@ public class WebConfig implements WebMvcConfigurer { "/user/**/register", "/user/**/login", "/user/**/uploadFile", - "/cop/coupon/v1/new_user_coupon"); + "/cop/coupon/v1/new_user_coupon", + "/odr/product/v1/query_state"); } /** diff --git a/nla-common/src/main/java/cn/nla/common/enums/StockTaskStateEnum.java b/nla-common/src/main/java/cn/nla/common/enums/StockTaskStateEnum.java new file mode 100644 index 0000000..5e27682 --- /dev/null +++ b/nla-common/src/main/java/cn/nla/common/enums/StockTaskStateEnum.java @@ -0,0 +1,17 @@ +package cn.nla.common.enums; + +public enum StockTaskStateEnum { + /** + * 锁定 + */ + LOCK, + /** + * 完成 + */ + FINISH, + /** + * 取消,释放库存 + */ + CANCEL; + +} diff --git a/nla-common/src/main/java/cn/nla/common/model/CouponRecordMessage.java b/nla-common/src/main/java/cn/nla/common/model/CouponRecordMessage.java new file mode 100644 index 0000000..2d959c6 --- /dev/null +++ b/nla-common/src/main/java/cn/nla/common/model/CouponRecordMessage.java @@ -0,0 +1,22 @@ +package cn.nla.common.model; + +import lombok.Data; + +/** + * 消息对象 + **/ +@Data +public class CouponRecordMessage { + /** + * 消息id + */ + private String messageId; + /** + * 订单号 + */ + private String outTradeNo; + /** + * 库存锁定任务id + */ + private Long taskId; +} diff --git a/nla-coupon-service/pom.xml b/nla-coupon-service/pom.xml index d496d4e..6aa1713 100644 --- a/nla-coupon-service/pom.xml +++ b/nla-coupon-service/pom.xml @@ -24,5 +24,9 @@ org.projectlombok lombok + + org.springframework.boot + spring-boot-starter-test + diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/config/RabbitMQConfig.java b/nla-coupon-service/src/main/java/cn/nla/coupon/config/RabbitMQConfig.java new file mode 100644 index 0000000..921b19b --- /dev/null +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/config/RabbitMQConfig.java @@ -0,0 +1,100 @@ +package cn.nla.coupon.config; + +import lombok.Data; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.Exchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Configuration +@Data +public class RabbitMQConfig { + /** + * 交换机 + */ + @Value("${mq.config.coupon_event_exchange}") + private String eventExchange; + /** + * 第一个队列 延迟队列, + */ + @Value("${mq.config.coupon_release_delay_queue}") + private String couponReleaseDelayQueue; + /** + * 第一个队列的路由key + * 进入队列的路由key + */ + @Value("${mq.config.coupon_release_delay_routing_key}") + private String couponReleaseDelayRoutingKey; + /** + * 第二个队列,被监听恢复库存的队列 + */ + @Value("${mq.config.coupon_release_queue}") + private String couponReleaseQueue; + /** + * 第二个队列的路由key + * + * 即进入死信队列的路由key + */ + @Value("${mq.config.coupon_release_routing_key}") + private String couponReleaseRoutingKey; + /** + * 过期时间 + */ + @Value("${mq.config.ttl}") + private Integer ttl; + /** + * 消息转换器 + */ + @Bean + public MessageConverter messageConverter(){ + return new Jackson2JsonMessageConverter(); + } + /** + * 创建交换机 Topic类型,也可以用dirct路由 + * 一般一个微服务一个交换机 + */ + @Bean + public Exchange couponEventExchange(){ + return new TopicExchange(eventExchange,true,false); + } + /** + * 延迟队列 + */ + @Bean + public Queue couponReleaseDelayQueue(){ + Map args = new HashMap<>(3); + args.put("x-message-ttl",ttl); + args.put("x-dead-letter-routing-key",couponReleaseRoutingKey); + args.put("x-dead-letter-exchange",eventExchange); + return new Queue(couponReleaseDelayQueue,true,false,false,args); + } + /** + * 死信队列,普通队列,用于被监听 + */ + @Bean + public Queue couponReleaseQueue(){ + return new Queue(couponReleaseQueue,true,false,false); + } + /** + * 第一个队列,即延迟队列的绑定关系建立 + */ + @Bean + public Binding couponReleaseDelayBinding(){ + return new Binding(couponReleaseDelayQueue,Binding.DestinationType.QUEUE,eventExchange,couponReleaseDelayRoutingKey,null); + } + /** + * 死信队列绑定关系建立 + */ + @Bean + public Binding couponReleaseBinding(){ + return new Binding(couponReleaseQueue,Binding.DestinationType.QUEUE,eventExchange,couponReleaseRoutingKey,null); + } +} diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java index 3e83b76..1de7842 100644 --- a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java @@ -3,6 +3,7 @@ package cn.nla.coupon.controller; import cn.nla.common.enums.BizCodeEnum; import cn.nla.common.util.JsonData; import cn.nla.coupon.model.VO.CouponRecordVO; +import cn.nla.coupon.model.request.LockCouponRecordRequest; import cn.nla.coupon.service.CouponRecordService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -10,6 +11,7 @@ import io.swagger.annotations.ApiParam; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.Map; /** *

@@ -40,5 +42,11 @@ public class CouponRecordController { CouponRecordVO couponRecordVO = couponRecordService.findById(recordId); return couponRecordVO == null ? JsonData.buildResult(BizCodeEnum.COUPON_NO_EXITS) : JsonData.buildSuccess(couponRecordVO); } + + @ApiOperation("rpc-锁定,优惠券记录") + @PostMapping("lock_records") + public JsonData lockCouponRecords(@ApiParam("锁定优惠券请求对象") @RequestBody LockCouponRecordRequest recordRequest) { + return couponRecordService.lockCouponRecords(recordRequest); + } } diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/feign/OrderFeignService.java b/nla-coupon-service/src/main/java/cn/nla/coupon/feign/OrderFeignService.java new file mode 100644 index 0000000..59e99cd --- /dev/null +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/feign/OrderFeignService.java @@ -0,0 +1,18 @@ +package cn.nla.coupon.feign; + +import cn.nla.common.util.JsonData; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.*; + + +/** + * Feign调用优惠券服务接口 + */ +@FeignClient(name = "nla-order-service") +public interface OrderFeignService { + /** + * 查询订单状态 + */ + @GetMapping("/odr/product/v1/query_state") + JsonData queryProductOrderState(@RequestParam("out_trade_no") String outTradeNo); +} diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/mapper/CouponRecordMapper.java b/nla-coupon-service/src/main/java/cn/nla/coupon/mapper/CouponRecordMapper.java index 4f2e1ef..9878307 100644 --- a/nla-coupon-service/src/main/java/cn/nla/coupon/mapper/CouponRecordMapper.java +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/mapper/CouponRecordMapper.java @@ -2,6 +2,9 @@ package cn.nla.coupon.mapper; import cn.nla.coupon.model.entity.CouponRecordEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** *

@@ -13,4 +16,14 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface CouponRecordMapper extends BaseMapper { + + /** + * 批量更新优惠券使用记录 + */ + int lockUseStateBatch(@Param("userId") Long userId, @Param("useState") String useState, @Param("lockCouponRecordIds") List lockCouponRecordIds); + + /** + * 更新优惠券使用记录 + */ + void updateState(@Param("couponRecordId") Long couponRecordId, @Param("useState") String useState); } diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/LockCouponRecordRequest.java b/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/LockCouponRecordRequest.java new file mode 100644 index 0000000..3329de1 --- /dev/null +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/LockCouponRecordRequest.java @@ -0,0 +1,22 @@ +package cn.nla.coupon.model.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel(value = "优惠券锁定对象",description = "优惠券锁定对象") +@Data +public class LockCouponRecordRequest { + /** + * 优惠券记录id列表 + */ + @ApiModelProperty(value = "优惠券记录id列表",example = "[1,2,3]") + private List lockCouponRecordIds; + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号",example = "3234fw234rfd232") + private String orderOutTradeNo; +} diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/mq/CouponMQListener.java b/nla-coupon-service/src/main/java/cn/nla/coupon/mq/CouponMQListener.java new file mode 100644 index 0000000..a529489 --- /dev/null +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/mq/CouponMQListener.java @@ -0,0 +1,66 @@ +package cn.nla.coupon.mq; + +import cn.nla.common.model.CouponRecordMessage; +import cn.nla.coupon.service.CouponRecordService; +import com.rabbitmq.client.Channel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.io.IOException; + +@Slf4j +@Component +@RabbitListener(queues = "${mq.config.coupon_release_queue}") +public class CouponMQListener { + + @Resource + private CouponRecordService couponRecordService; + +// @Resource +// private RedissonClient redissonClient; + + /** + * 重复消费-幂等性 + *

+ * 消费失败,重新入队后最大重试次数: + * 如果消费失败,不重新入队,可以记录日志,然后插到数据库人工排查 + *

+ * 消费者这块还有啥问题,大家可以先想下,然后给出解决方案 + */ + @RabbitHandler + public void releaseCouponRecord(CouponRecordMessage recordMessage, Message message, Channel channel) throws IOException { + //防止同个解锁任务并发进入;如果是串行消费不用加锁;加锁有利也有弊,看项目业务逻辑而定 + //Lock lock = redissonClient.getLock("lock:coupon_record_release:"+recordMessage.getTaskId()); + //lock.lock(); + log.info("监听到消息:releaseCouponRecord消息内容:{}", recordMessage); + long msgTag = message.getMessageProperties().getDeliveryTag(); + boolean flag = couponRecordService.releaseCouponRecord(recordMessage); + try { + if (flag) { + //确认消息消费成功 + channel.basicAck(msgTag, false); + } else { + log.error("释放优惠券失败 flag=false,{}", recordMessage); + channel.basicReject(msgTag, true); + } + } catch (IOException e) { + log.error("释放优惠券记录异常:{},msg:{}", e, recordMessage); + channel.basicReject(msgTag, true); + } +// finally { +// lock.unlock(); +// } + + } + +// @RabbitHandler +// public void releaseCouponRecord2(String msg,Message message, Channel channel) throws IOException { +// log.info(msg); +// channel.basicAck(message.getMessageProperties().getDeliveryTag(),true); +// } + +} diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java index 1716277..0020d45 100644 --- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java @@ -1,8 +1,11 @@ package cn.nla.coupon.service; +import cn.nla.common.model.CouponRecordMessage; import cn.nla.common.model.PageResult; +import cn.nla.common.util.JsonData; import cn.nla.coupon.model.VO.CouponRecordVO; import cn.nla.coupon.model.entity.CouponRecordEntity; +import cn.nla.coupon.model.request.LockCouponRecordRequest; import com.baomidou.mybatisplus.extension.service.IService; /** @@ -21,4 +24,18 @@ public interface CouponRecordService extends IService { PageResult page(int page, int size); CouponRecordVO findById(long recordId); + /** + * 锁定优惠券 + * + * 1)锁定优惠券记录 + * 2)task表插入记录 + * 3)发送延迟消息 + */ + JsonData lockCouponRecords(LockCouponRecordRequest recordRequest); + /** + * 解锁优惠券记录 + * 1)查询task工作单是否存在 + * 2) 查询订单状态 + */ + boolean releaseCouponRecord(CouponRecordMessage recordMessage); } diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java index 940d47d..e604cd4 100644 --- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java +++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java @@ -1,19 +1,40 @@ package cn.nla.coupon.service.impl; +import cn.nla.common.enums.BizCodeEnum; +import cn.nla.common.enums.CouponStateEnum; +import cn.nla.common.enums.ProductOrderStateEnum; +import cn.nla.common.enums.StockTaskStateEnum; +import cn.nla.common.exception.BizException; import cn.nla.common.interceptor.LoginInterceptor; +import cn.nla.common.model.CouponRecordMessage; import cn.nla.common.model.LoginUser; import cn.nla.common.model.PageResult; +import cn.nla.common.util.JsonData; +import cn.nla.coupon.config.RabbitMQConfig; +import cn.nla.coupon.feign.OrderFeignService; +import cn.nla.coupon.mapper.CouponTaskMapper; import cn.nla.coupon.model.VO.CouponRecordVO; import cn.nla.coupon.model.entity.CouponRecordEntity; import cn.nla.coupon.mapper.CouponRecordMapper; +import cn.nla.coupon.model.entity.CouponTaskEntity; +import cn.nla.coupon.model.request.LockCouponRecordRequest; import cn.nla.coupon.service.CouponRecordService; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; import java.util.stream.Collectors; /** @@ -24,9 +45,22 @@ import java.util.stream.Collectors; * @author YJs * @since 2024-08-08 */ +@Slf4j @Service public class CouponRecordServiceImpl extends ServiceImpl implements CouponRecordService { + @Resource + private CouponTaskMapper couponTaskMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private RabbitMQConfig rabbitMQConfig; + + @Resource + private OrderFeignService orderFeignService; + @Override public PageResult page(int page, int size) { LoginUser loginUser = LoginInterceptor.threadLocal.get(); @@ -57,4 +91,81 @@ public class CouponRecordServiceImpl extends ServiceImpl lockCouponRecordIds = recordRequest.getLockCouponRecordIds(); + // 锁定优惠券记录 + int updateRows = baseMapper.lockUseStateBatch(loginUser.getId(), CouponStateEnum.USED.name(), lockCouponRecordIds); + //task表插入记录 + List couponTaskList = lockCouponRecordIds.stream().map(obj -> { + CouponTaskEntity couponTask = new CouponTaskEntity(); + couponTask.setCreateTime(new Date()); + couponTask.setOutTradeNo(orderOutTradeNo); + couponTask.setCouponRecordId(obj); + couponTask.setLockState(StockTaskStateEnum.LOCK.name()); + return couponTask; + }).collect(Collectors.toList()); + int insertRows = couponTaskMapper.insertBatch(couponTaskList); + log.info("优惠券记录锁定updateRows={}", updateRows); + log.info("新增优惠券记录task insertRows={}", insertRows); + if (lockCouponRecordIds.size() == insertRows && insertRows == updateRows) { + //发送延迟消息 + for (CouponTaskEntity couponTask : couponTaskList) { + CouponRecordMessage couponRecordMessage = new CouponRecordMessage(); + couponRecordMessage.setOutTradeNo(orderOutTradeNo); + couponRecordMessage.setTaskId(couponTask.getId()); + rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(), rabbitMQConfig.getCouponReleaseDelayRoutingKey(), couponRecordMessage); + log.info("优惠券锁定消息发送成功:{}", JSON.toJSONString(couponRecordMessage)); + } + return JsonData.buildSuccess(); + } else { + throw new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL); + } + } + + @Override + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) + public boolean releaseCouponRecord(CouponRecordMessage recordMessage) { + //查询下task是否存 + CouponTaskEntity task = couponTaskMapper.selectOne(new QueryWrapper().eq("id", recordMessage.getTaskId())); + if (task == null) { + log.warn("工作单不存,消息:{}", recordMessage); + return true; + } + //lock状态才处理 + if (task.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())) { + //查询订单状态 + JsonData jsonData = orderFeignService.queryProductOrderState(recordMessage.getOutTradeNo()); + if (jsonData.getCode() == 0) { + //正常响应,判断订单状态 + String state = jsonData.getData().toString(); + if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)) { + //状态是NEW新建状态,则返回给消息队,列重新投递 + log.warn("订单状态是NEW,返回给消息队列,重新投递:{}", recordMessage); + return false; + } + //如果是已经支付 + if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)) { + //如果已经支付,修改task状态为finish + task.setLockState(StockTaskStateEnum.FINISH.name()); + couponTaskMapper.update(task, new QueryWrapper().eq("id", recordMessage.getTaskId())); + log.info("订单已经支付,修改库存锁定工作单FINISH状态:{}", recordMessage); + return true; + } + } + //订单不存在,或者订单被取消,确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW + log.warn("订单不存在,或者订单被取消,确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW,message:{}", recordMessage); + task.setLockState(StockTaskStateEnum.CANCEL.name()); + couponTaskMapper.update(task, new QueryWrapper().eq("id", recordMessage.getTaskId())); + //恢复优惠券记录是NEW状态 + baseMapper.updateState(task.getCouponRecordId(), CouponStateEnum.NEW.name()); + } else { + log.warn("工作单状态不是LOCK,state={},消息体={}", task.getLockState(), recordMessage); + } + return true; + } + } diff --git a/nla-coupon-service/src/main/resources/application.yml b/nla-coupon-service/src/main/resources/application.yml index 59e84b3..cef309b 100644 --- a/nla-coupon-service/src/main/resources/application.yml +++ b/nla-coupon-service/src/main/resources/application.yml @@ -8,36 +8,52 @@ spring: port: 6379 database: 0 password: yuan123456 - #数据库配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://117.72.43.105:3306/p_nla_coupon?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: Yuan625621105. cloud: - #注册中心地址 nacos: discovery: server-addr: 117.72.43.105:8848 # username: nacos # password: sW5U%pxecL#p # namespace: yjs -#配置plus打印sql⽇志 + + rabbitmq: + host: 192.168.30.130 + port: 5672 + virtual-host: / + password: admin + username: admin + listener: + simple: + acknowledge-mode: manual + mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -#设置⽇志级别,ERROR/WARN/INFO/DEBUG,默认是INFO以上才显示 #logging: # level: # root: INFO -#seata配置 -seata: - tx-service-group: ${spring.application.name}-group - service: - grouplist: - nla: 127.0.0.1:8091 - vgroup-mapping: - nla-coupon-service-group: nla +#seata: +# tx-service-group: ${spring.application.name}-group +# service: +# grouplist: +# nla: 127.0.0.1:8091 +# vgroup-mapping: +# nla-coupon-service-group: nla + + +mq: + config: + coupon_release_delay_queue: coupon.release.delay.queue + coupon_release_queue: coupon.release.queue + coupon_event_exchange: coupon.event.exchange + coupon_release_delay_routing_key: coupon.release.delay.routing.key + coupon_release_routing_key: coupon.release.routing.key + ttl: 6000 diff --git a/nla-coupon-service/src/main/resources/application_m.yml b/nla-coupon-service/src/main/resources/application_m.yml new file mode 100644 index 0000000..c2b61c2 --- /dev/null +++ b/nla-coupon-service/src/main/resources/application_m.yml @@ -0,0 +1,74 @@ +server: + port: 9002 +spring: + application: + name: nla-coupon-service + # 缓存 + redis: + host: 127.0.0.1 + port: 6379 + database: 0 + password: yuan123456 + #数据库配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://117.72.43.105:3306/p_nla_coupon?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: Yuan625621105. + #注册中心地址 + cloud: + nacos: + discovery: + server-addr: 117.72.43.105:8848 +# username: nacos +# password: sW5U%pxecL#p +# namespace: yjs + + #消息队列 + rabbitmq: + host: 192.168.30.130 + port: 5672 + virtual-host: / + password: admin + username: admin + #开启手动确认消息 + listener: + simple: + acknowledge-mode: manual + +#配置plus打印sql⽇志 +mybatis-plus: + configuration: + log-impl: + org.apache.ibatis.logging.stdout.StdOutImpl +#设置⽇志级别,ERROR/WARN/INFO/DEBUG,默认是INFO以上才显示 +#logging: +# level: +# root: INFO + + +#seata配置 +#seata: +# tx-service-group: ${spring.application.name}-group +# service: +# grouplist: +# nla: 127.0.0.1:8091 +# vgroup-mapping: +# nla-coupon-service-group: nla + + +##自定义消息队列配置,发送锁定库存消息-》延迟exchange-》lock.queue-》死信exchange-》release.queue +mq: + config: + #延迟队列,不能被监听消费 + coupon_release_delay_queue: coupon.release.delay.queue + #延迟队列的消息过期后转发的队列 + coupon_release_queue: coupon.release.queue + #交换机 + coupon_event_exchange: coupon.event.exchange + #进入延迟队列的路由key + coupon_release_delay_routing_key: coupon.release.delay.routing.key + #消息过期,进入释放死信队列的key + coupon_release_routing_key: coupon.release.routing.key + #消息过期时间,毫秒,临时改为6分钟 + ttl: 360000 diff --git a/nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml b/nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml index 487e4da..ba0c252 100644 --- a/nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml +++ b/nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml @@ -4,18 +4,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -23,4 +23,19 @@ id, coupon_id, create_time, use_state, user_id, user_name, coupon_title, start_time, end_time, order_id, price, condition_price + + + update coupon_record set use_state=#{useState} where user_id=#{userId} and use_state='NEW' and id in + + #{id} + + + + + + update coupon_record + set use_state = #{useState} + where id = #{couponRecordId} + + diff --git a/nla-coupon-service/src/test/java/cn/nla/coupon/CouponApplicationTests.java b/nla-coupon-service/src/test/java/cn/nla/coupon/CouponApplicationTests.java new file mode 100644 index 0000000..30a59eb --- /dev/null +++ b/nla-coupon-service/src/test/java/cn/nla/coupon/CouponApplicationTests.java @@ -0,0 +1,31 @@ +package cn.nla.coupon; + +import cn.nla.common.model.CouponRecordMessage; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = CouponApplication.class) +@Slf4j +public class CouponApplicationTests { + + @Resource + private RabbitTemplate rabbitTemplate; + +@Test +public void send() { +// rabbitTemplate.convertAndSend("coupon.event.exchange", "coupon.release.delay.routing.key", "测试数据"); + CouponRecordMessage message = new CouponRecordMessage(); + message.setOutTradeNo("123456abc"); + message.setTaskId(1L); + rabbitTemplate.convertAndSend("coupon.event.exchange", "coupon.release.delay.routing.key", message); +} + +} + diff --git a/nla-order-service/src/main/java/cn/nla/order/OrderApplication.java b/nla-order-service/src/main/java/cn/nla/order/OrderApplication.java index fa9f45c..f5831ff 100644 --- a/nla-order-service/src/main/java/cn/nla/order/OrderApplication.java +++ b/nla-order-service/src/main/java/cn/nla/order/OrderApplication.java @@ -3,10 +3,16 @@ package cn.nla.order; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ComponentScan; +import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @MapperScan("cn.nla.*.mapper") +@EnableFeignClients +@EnableDiscoveryClient +@EnableTransactionManagement @ComponentScan(basePackages = {"cn.nla.*"}) public class OrderApplication { public static void main(String[] args) { diff --git a/nla-order-service/src/main/resources/application.yml b/nla-order-service/src/main/resources/application.yml index 54ad622..fd1f578 100644 --- a/nla-order-service/src/main/resources/application.yml +++ b/nla-order-service/src/main/resources/application.yml @@ -14,6 +14,13 @@ spring: url: jdbc:mysql://117.72.43.105:3306/p_nla_order?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: Yuan625621105. + cloud: + nacos: + discovery: + server-addr: 117.72.43.105:8848 + # username: nacos + # password: sW5U%pxecL#p + # namespace: yjs #配置plus打印sql⽇志 mybatis-plus: configuration: