当前位置: 首页 > news >正文

ruoyi-product的ruoyi-product-dev.yml:

spring配置 spring: redis: host: localhost port: 6379 password: datasource: druid: stat-view-servlet: enabled: true loginUsername: ruoyi loginPassword: 123456 dynamic: druid: initial-size: 5 min-idle: 5 maxActive: 20 maxWait: 60000 connectTimeout: 30000 socketTimeout: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 filters: stat,slf4j connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 datasource: # 主库数据源 master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: root123 # 从库数据源 # slave: # username: # password: # url: # driver-class-name: seata: true # mybatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.product # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath:mapper/**/*.xml # springdoc配置 springdoc: gatewayUrl: http://localhost:8080/${spring.application.name} api-docs: # 是否开启接口文档 enabled: false

ruoyi-product示例代码:
Product.java

package com.ruoyi.product.domain; import lombok.Getter; import lombok.Setter; import java.util.Date; @Getter @Setter public class Product { private Integer id; /** * 价格 */ private Double price; /** * 库存 */ private Integer stock; private Date lastUpdateTime; }

ProductMapper.java

package com.ruoyi.product.mapper; import com.ruoyi.product.domain.Product; public interface ProductMapper { public Product selectById(Long productId); public void updateById(Product product); }

ProductMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.product.mapper.ProductMapper"> <resultMap type="com.ruoyi.product.domain.Product" id="ProductResult"> <id property="id" column="id" /> <result property="price" column="price" /> <result property="stock" column="stock" /> <result property="lastUpdateTime" column="last_update_time" /> </resultMap> <select id="selectById" parameterType="com.ruoyi.product.domain.Product" resultMap="ProductResult"> select id, price, stock, last_update_time from product where id = #{productId} </select> <update id="updateById" parameterType="com.ruoyi.product.domain.Product"> update product set price = #{price}, stock = #{stock}, last_update_time = sysdate() where id = #{id} </update> </mapper>

ProductService.java

package com.ruoyi.product.service; public interface ProductService { /** * 扣减库存 * * @param productId 商品 ID * @param amount 扣减数量 * @return 商品总价 */ Double reduceStock(Long productId, Integer amount); }

ProductServiceImpl.java

package com.ruoyi.product.service.impl; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.baomidou.dynamic.datasource.annotation.DS; import com.ruoyi.product.domain.Product; import com.ruoyi.product.mapper.ProductMapper; import com.ruoyi.product.service.ProductService; import io.seata.core.context.RootContext; @Service public class ProductServiceImpl implements ProductService { private static final Logger log = LoggerFactory.getLogger(ProductServiceImpl.class); @Resource private ProductMapper productMapper; /** * 事务传播特性设置为 REQUIRES_NEW 开启新的事务 重要!!!!一定要使用REQUIRES_NEW * 在若依的示例中,事务的传播特性必须设置REQUIRES_NEW,但经本人测试,多服务调用事务 * 设置成默认的REQUIRED也能回滚成功 */ @Transactional @Override public Double reduceStock(Long productId, Integer amount) { log.info("=============PRODUCT START================="); log.info("当前 XID: {}", RootContext.getXID()); // 检查库存 Product product = productMapper.selectById(productId); Integer stock = product.getStock(); log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount); if (stock < amount) { log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock); throw new RuntimeException("库存不足"); } log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice()); // 扣减库存 int currentStock = stock - amount; product.setStock(currentStock); productMapper.updateById(product); double totalPrice = product.getPrice() * amount; log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice); log.info("=============PRODUCT END================="); return totalPrice; } }

ProductController.java

package com.ruoyi.product.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.product.dto.ReduceStockRequest; import com.ruoyi.product.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; @PostMapping("/reduceStock") public R<Double> reduceStock(@Validated @RequestBody ReduceStockRequest request) { Double d = productService.reduceStock(request.getProductId(), request.getAmount()); return R.ok(d); } }

ReduceStockRequest.java

package com.ruoyi.product.dto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class ReduceStockRequest { private Long productId; private Integer amount; }

至此,商品服务就搭建好了,这里主要提供一个扣减商品库存的接口。

创建服务调用模块

在ruoyi-modules新建一个Module:ruoyi-call(当你也可以不新建Module,直接把Feign接口写在具调用的服务中,这里新建Module主是为了更好的体现模块之间的低耦合),该模块主要的作用是提供Feign接口,用于订单服务调用商品及账户服务,为了搭建方便,以及减少Maven依赖,pom依赖直接拷贝ruoyi-api-system中的依赖。
ruoyi-call的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-modules</artifactId> <version>3.6.6</version> </parent> <artifactId>ruoyi-call</artifactId> <packaging>jar</packaging> <name>ruoyi-call</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-core</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
http://www.jsqmd.com/news/1099099/

相关文章:

  • 抖音无水印下载终极指南:douyin-downloader让你快速保存任何视频
  • AI生图工具怎么选?2026年6月版实测对比
  • 【AI大模型应用开发】【项目实战】9.基于GPT2搭建医疗问诊机器人
  • 【毕业设计】基于 SpringBoot+Vue 的 4S 店车辆库存与订单管理系统的设计与实现 基于 SpringBoot+Vue 的汽车门店销售后台运维系统(源码+文档+远程调试,全bao定制等)
  • C++ STL之互斥锁与条件变量详解
  • Domain3-2 安全模型
  • Java开发者实战指南:Spring Boot集成AI大模型与Agent开发
  • SQL性能突降致数据库CPU飙升:系统性排查与根因定位指南
  • Mac与Android无缝连接:HoRNDIS USB网络共享驱动深度解析
  • 0.69B参数实现中文多模态AI:揭秘Qwen3-SmVL模型融合技术的完整实战指南
  • Codex使用教程:十大办公自动化场景实战指南 Codex教程、Codex使用技巧、Codex办公自动化、AI智能体、Codex工作流、Codex生成PPT、Codex周报、Codex日报、AI办公助
  • 国产DSP FT-M6678 DDR3配置避坑指南:从PLL时钟到PHY寄存器,手把手调通你的第一块板
  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 题解:AtCoder AT_awc0101_b A Single Strike of Dominoes
  • Python数据分析全流程实战:从数据清洗到可视化报告
  • 2026年6月零代码网站搭建与企业无代码建站工具测评:谁更适合你
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 解决音频格式兼容性难题:FlicFlac轻量级音频转换工具深度解析
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析
  • 小动物人工呼吸机
  • 餐饮老板必看:扫码点餐小程序3步搞定,别再让顾客干等了!
  • 终极指南:如何用Steam-auto-crack实现Steam游戏自动破解
  • ai agent框架spring ai/alibaba 源码原理分析(六) agent和组件
  • [C++]内存管理:串顺序存储的内存回收
  • 移动端游戏功耗测试实战:电流、功率、亮度和场景对比
  • ShaderGlass:如何在Windows桌面上实时运行GPU着色器的完整指南
  • 足球口袋教练 HarmonyOS 离线应用实战(03/20):ArkUI 首页仪表盘搭建
  • 企业 GEO 优化完整应用场景
  • 抖音内容监控助手:告别手动刷新,让优质内容主动找你
  • Vue3+ECharts使用渐变堆叠面积图实现图例横向滚动,超出出现滚动条,组件抽离复用,包含图表自适应窗口大小 - 附完整示例