完成基本下单的学习

This commit is contained in:
2026-03-03 18:02:03 +08:00
parent 887fea1961
commit 8b37cccb93
24 changed files with 643 additions and 57 deletions

View File

@@ -78,5 +78,9 @@
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -3,27 +3,77 @@ package cn.mayiming.Controller;
import cn.mayiming.Service.OrderService;
import cn.mayiming.entity.Order;
import cn.mayiming.entity.Result;
import cn.mayiming.entity.StockDeductDTO;
import cn.mayiming.entity.User;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/order")
@PostMapping("/search")
public User getUserOrder(@RequestBody User user){
//throw new RuntimeException("Cuowu ");
return orderService.SearchUserbyname(user);
}
@GetMapping("/order")
@GetMapping("/list")
public List<Order> getUserOrder(@RequestParam Integer id){
return orderService.OrderListById(id);
}
@PostMapping("/create")
public Result<Object> createOrder(@RequestBody Map<String, Object> jsonMap){
try {
// 1. 安全获取userId先转Number再取int值兼容Integer/Long
Number userIdNum = (Number) jsonMap.get("userId");
if (userIdNum == null) {
return Result.fail(400, "userId不能为空");
}
int userId = userIdNum.intValue();
// 2. 安全获取stockid先转Number再取long值兼容Integer/Long
Number stockIdNum = (Number) jsonMap.get("stockid");
if (stockIdNum == null) {
return Result.fail(400, "stockid不能为空");
}
Long stockId = stockIdNum.longValue();
// 3. 安全获取deductnum先转Number再取int值兼容Integer/Long
Number deductNumNum = (Number) jsonMap.get("deductnum");
if (deductNumNum == null) {
return Result.fail(400, "deductnum不能为空");
}
int deductNum = deductNumNum.intValue();
// 4. 组装DTO
StockDeductDTO stockDeductDTO = new StockDeductDTO();
stockDeductDTO.setId(stockId);
stockDeductDTO.setDeductNum(deductNum);
// 5. 调用服务
int serviceResult = orderService.createOrder(stockDeductDTO, userId);
if (serviceResult != 0) {
// 库存扣减/订单创建失败
return Result.fail("库存扣减失败,订单创建失败");
}
// 成功可以返回额外数据比如订单ID
return Result.success("库存扣减成功,订单创建成功");
} catch (Exception e) {
// 捕获所有异常,返回友好提示
e.printStackTrace();
return Result.fail("订单创建异常:" + e.getMessage());
}
}
}

View File

@@ -2,8 +2,12 @@ package cn.mayiming.Service;
import cn.mayiming.Mapper.OrderMapper;
import cn.mayiming.entity.Order;
import cn.mayiming.entity.StockDeductDTO;
import cn.mayiming.entity.User;
import cn.mayiming.feign.StockFeignClient;
import cn.mayiming.feign.UserFeignClient;
import jakarta.annotation.Resource;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -17,6 +21,12 @@ public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private StockFeignClient stockFeignClient;
@Resource
private RocketMQTemplate rocketMQTemplate;
public User SearchUserbyname (User user) {
return userFeignClient.selectByUsername(user);
}
@@ -31,4 +41,30 @@ public class OrderService {
}
public void sendPaySuccessMessage(String msg) {
// 2. 发送消息:格式为 "主题:标签"
// 同步发送:等待 Broker 确认,返回发送结果(可靠)
try {
// 参数1topic:tag对应消费者的 topic + selectorExpression
// 参数2消息体自动序列化
rocketMQTemplate.convertAndSend("pay_topic:pay_success", msg);
} catch (Exception e) {
// 发送失败处理(如记录日志、重试、告警)
System.err.println("消息发送失败:" + ",原因:" + e.getMessage());
throw new RuntimeException("消息发送失败", e);
}
}
public int createOrder(StockDeductDTO stockDeductDTO,int i) {
int res = 0;
if(stockFeignClient.deductstock(stockDeductDTO)==0){
res ++;
}
if(userFeignClient.GetUserByid(i)==null){
res ++;
}
return res;
}
}

View File

@@ -0,0 +1,69 @@
package cn.mayiming.entity;
/**
* 通用接口响应结果类
* @param <T> 响应数据类型
*/
public class Result<T> {
// 响应码200成功500失败400参数错误等
private Integer code;
// 响应消息
private String msg;
// 响应数据
private T data;
// 静态构造方法(推荐)
// 成功(无数据)
public static <T> Result<T> success() {
return new Result<>(200, "操作成功", null);
}
// 成功(带数据)
public static <T> Result<T> success(T data) {
return new Result<>(200, "操作成功", data);
}
// 失败
public static <T> Result<T> fail(String msg) {
return new Result<>(500, msg, null);
}
// 失败(自定义码+消息)
public static <T> Result<T> fail(Integer code, String msg) {
return new Result<>(code, msg, null);
}
// 构造器、getter/setter
public Result() {}
public Result(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
// getter和setter
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

View File

@@ -0,0 +1,17 @@
package cn.mayiming.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class StockDeductDTO {
@NotNull
@JsonProperty("id")
private Long id;
@NotNull
@JsonProperty("deductnum")
private Integer deductNum;
}

View File

@@ -0,0 +1,14 @@
package cn.mayiming.feign;
import cn.mayiming.entity.StockDeductDTO;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "stock-service")
public interface StockFeignClient {
@PostMapping("/stock/deduct")
int deductstock(@RequestBody StockDeductDTO stockDeductDTO);
}

View File

@@ -24,7 +24,7 @@ spring:
# 数据库驱动类MySQL 8.x 用 com.mysql.cj.jdbc.Driver5.x 用 com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库连接 URL替换为你的数据库地址、端口、库名如 user_db
url: jdbc:mysql://rm-f8z6oc5a03331500p8o.mysql.rds.aliyuncs.com:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
url: jdbc:mysql://rm-f8z6oc5a03331500p8o.mysql.rds.aliyuncs.com:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
# 数据库用户名(默认 root根据实际情况修改
username: root
# 数据库密码(替换为你的 MySQL 密码)
@@ -38,4 +38,18 @@ spring:
# 连接超时时间(毫秒)
connection-timeout: 30000
# 连接最大存活时间(毫秒)
max-lifetime: 1800000
max-lifetime: 1800000
rocketmq:
# NameServer 地址(替换为你的 RocketMQ 服务器IP
name-server: 127.0.0.1:9876
producer:
# 生产者组名(必须唯一,建议:服务名+producer
group: pay-service-producer
# 发送失败重试次数默认2次
retry-times-when-send-failed: 3
# 发送超时时间默认3000ms
send-message-timeout: 5000
# 消息最大长度默认4M
max-message-size: 4194304
# 压缩消息阈值超过4K自动压缩
compress-message-body-threshold: 4096