Browse Source

feat: 更新业务逻辑

master
xc-yjs 8 months ago
parent
commit
6198f80a19
  1. 3
      nla-common/src/main/java/cn/nla/common/config/WebConfig.java
  2. 17
      nla-common/src/main/java/cn/nla/common/enums/StockTaskStateEnum.java
  3. 22
      nla-common/src/main/java/cn/nla/common/model/CouponRecordMessage.java
  4. 4
      nla-coupon-service/pom.xml
  5. 100
      nla-coupon-service/src/main/java/cn/nla/coupon/config/RabbitMQConfig.java
  6. 8
      nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java
  7. 18
      nla-coupon-service/src/main/java/cn/nla/coupon/feign/OrderFeignService.java
  8. 13
      nla-coupon-service/src/main/java/cn/nla/coupon/mapper/CouponRecordMapper.java
  9. 22
      nla-coupon-service/src/main/java/cn/nla/coupon/model/request/LockCouponRecordRequest.java
  10. 66
      nla-coupon-service/src/main/java/cn/nla/coupon/mq/CouponMQListener.java
  11. 17
      nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java
  12. 111
      nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java
  13. 40
      nla-coupon-service/src/main/resources/application.yml
  14. 74
      nla-coupon-service/src/main/resources/application_m.yml
  15. 39
      nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml
  16. 31
      nla-coupon-service/src/test/java/cn/nla/coupon/CouponApplicationTests.java
  17. 6
      nla-order-service/src/main/java/cn/nla/order/OrderApplication.java
  18. 7
      nla-order-service/src/main/resources/application.yml

3
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");
}
/**

17
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;
}

22
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;
}

4
nla-coupon-service/pom.xml

@ -24,5 +24,9 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>

100
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<String,Object> 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);
}
}

8
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;
/**
* <p>
@ -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);
}
}

18
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);
}

13
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;
/**
* <p>
@ -13,4 +16,14 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface CouponRecordMapper extends BaseMapper<CouponRecordEntity> {
/**
* 批量更新优惠券使用记录
*/
int lockUseStateBatch(@Param("userId") Long userId, @Param("useState") String useState, @Param("lockCouponRecordIds") List<Long> lockCouponRecordIds);
/**
* 更新优惠券使用记录
*/
void updateState(@Param("couponRecordId") Long couponRecordId, @Param("useState") String useState);
}

22
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<Long> lockCouponRecordIds;
/**
* 订单号
*/
@ApiModelProperty(value = "订单号",example = "3234fw234rfd232")
private String orderOutTradeNo;
}

66
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;
/**
* 重复消费-幂等性
* <p>
* 消费失败重新入队后最大重试次数
* 如果消费失败不重新入队可以记录日志然后插到数据库人工排查
* <p>
* 消费者这块还有啥问题大家可以先想下然后给出解决方案
*/
@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);
// }
}

17
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<CouponRecordEntity> {
PageResult<CouponRecordVO> page(int page, int size);
CouponRecordVO findById(long recordId);
/**
* 锁定优惠券
*
* 1锁定优惠券记录
* 2task表插入记录
* 3发送延迟消息
*/
JsonData lockCouponRecords(LockCouponRecordRequest recordRequest);
/**
* 解锁优惠券记录
* 1查询task工作单是否存在
* 2) 查询订单状态
*/
boolean releaseCouponRecord(CouponRecordMessage recordMessage);
}

111
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<CouponRecordMapper, CouponRecordEntity> implements CouponRecordService {
@Resource
private CouponTaskMapper couponTaskMapper;
@Resource
private RabbitTemplate rabbitTemplate;
@Resource
private RabbitMQConfig rabbitMQConfig;
@Resource
private OrderFeignService orderFeignService;
@Override
public PageResult<CouponRecordVO> page(int page, int size) {
LoginUser loginUser = LoginInterceptor.threadLocal.get();
@ -57,4 +91,81 @@ public class CouponRecordServiceImpl extends ServiceImpl<CouponRecordMapper, Cou
BeanUtils.copyProperties(couponRecord, result);
return result;
}
@Override
public JsonData lockCouponRecords(LockCouponRecordRequest recordRequest) {
LoginUser loginUser = LoginInterceptor.threadLocal.get();
String orderOutTradeNo = recordRequest.getOrderOutTradeNo();
List<Long> lockCouponRecordIds = recordRequest.getLockCouponRecordIds();
// 锁定优惠券记录
int updateRows = baseMapper.lockUseStateBatch(loginUser.getId(), CouponStateEnum.USED.name(), lockCouponRecordIds);
//task表插入记录
List<CouponTaskEntity> 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<CouponTaskEntity>().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<CouponTaskEntity>().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<CouponTaskEntity>().eq("id", recordMessage.getTaskId()));
//恢复优惠券记录是NEW状态
baseMapper.updateState(task.getCouponRecordId(), CouponStateEnum.NEW.name());
} else {
log.warn("工作单状态不是LOCK,state={},消息体={}", task.getLockState(), recordMessage);
}
return true;
}
}

40
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

74
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

39
nla-coupon-service/src/main/resources/mapper/CouponRecordMapper.xml

@ -4,18 +4,18 @@
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.nla.coupon.model.entity.CouponRecordEntity">
<id column="id" property="id" />
<result column="coupon_id" property="couponId" />
<result column="create_time" property="createTime" />
<result column="use_state" property="useState" />
<result column="user_id" property="userId" />
<result column="user_name" property="userName" />
<result column="coupon_title" property="couponTitle" />
<result column="start_time" property="startTime" />
<result column="end_time" property="endTime" />
<result column="order_id" property="orderId" />
<result column="price" property="price" />
<result column="condition_price" property="conditionPrice" />
<id column="id" property="id"/>
<result column="coupon_id" property="couponId"/>
<result column="create_time" property="createTime"/>
<result column="use_state" property="useState"/>
<result column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
<result column="coupon_title" property="couponTitle"/>
<result column="start_time" property="startTime"/>
<result column="end_time" property="endTime"/>
<result column="order_id" property="orderId"/>
<result column="price" property="price"/>
<result column="condition_price" property="conditionPrice"/>
</resultMap>
<!-- 通用查询结果列 -->
@ -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
</sql>
<!--批量锁定优惠券记录-->
<update id="lockUseStateBatch">
update coupon_record set use_state=#{useState} where user_id=#{userId} and use_state='NEW' and id in
<foreach collection="lockCouponRecordIds" index="index" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</update>
<!--更新优惠券状态-->
<update id="updateState">
update coupon_record
set use_state = #{useState}
where id = #{couponRecordId}
</update>
</mapper>

31
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);
}
}

6
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) {

7
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:

Loading…
Cancel
Save