•  个人主页:VON
  • 文章所属专栏:微服务
  • 微服务系列文章

    重生之我在暑假学习微服务第一天《MybatisPlus-上篇》
    重生之我在暑假学习微服务第二天《MybatisPlus-下篇》
    重生之我在暑假学习微服务第三天《Docker-上篇》
    重生之我在暑假学习微服务第四天《Docker-下篇》
    重生之我在暑假学习微服务第五天《Docker部署项目篇》
    重生之我在暑假学习微服务第六天《微服务之拆分项目篇》
    重生之我在暑假学习微服务第七天《微服务之服务治理篇》
    重生之我在暑假学习微服务第八天《OpenFeign篇》
    未完待续......

    特别声明:本系列所涉及资料皆为黑马程序员课程中的资料

目录

 一、前言

二、用户部分

1、先将所用到的表导进去

2、创建user-service模块

3、改造user-service模块

(1)pom文件

(2)修改模块

(3)yaml文件

(4)测试

三、交易部分

1、创建trade-service模块

2、改造trade-service模块

(1)pom文件

(2)修改模块

(3)yaml文件

(4)改造代码 

(5)测试 

四、支付部分

1、创建pay-service模块

2、改造pay-service模块

(1)pom文件

(2)修改模块

(3)yaml文件

(4)改造代码 

(5)测试

结语


 一、前言

昨天没有更新,今天将昨天的部分也补偿上去,拆分项目所用的技术我们已经掌握的差不多了,接下来开始拆分剩下的模块。

二、用户部分

1、先将所用到的表导进去

2、创建user-service模块

还是默认直接创建就行了,创建完成后的目录是这样的

3、改造user-service模块

(1)pom文件

直接将cart-service中的拷贝过来就行了

  <dependencies><!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency>
<!--        api--><dependency><groupId>com.heima</groupId><artifactId>hm-api</artifactId><version>1.0.0</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-rsa</artifactId><version>1.0.9.RELEASE</version></dependency><!--数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!--nacos服务注册--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies>

(2)修改模块

这里教大家一个小技巧,把这两个勾选上可以自动导入包

整体来看就是这么多相关的包了 ,因为屏幕限制最后一个没截图上

 

这里刚才放错位置了

准备完成后开始启动项目

(3)yaml文件

(4)测试

运行前将这里设置为local

 可以看到测试成功了

 如果报错是数据库连接超时的话就将数据库地址改一下

可以在这改

 也可以在这改

三、交易部分

交易部分和用户部分差不多

1、创建trade-service模块

还是直接默认创建即可,创建完成后将包创建出来

2、改造trade-service模块

(1)pom文件

还是和用户部分的pom文件一样

(2)修改模块

这是修改后的模块

(3)yaml文件

(4)改造代码 

扣减库存部分代码

复制下这段代码

可以看到这里爆红了,原因是没找到这个类 

直接将hm-service中的类拉过来 

 

清理购物车商品

复制这段代码

 改造完成后放在这里

 改造trade-service

这个地方需要改造下

// 3.扣减库存try {itemClient.deductStock(detailDTOS);} catch (Exception e) {throw new RuntimeException("库存不足!");}// 4.清理购物车商品cartClient.deleteCartItemByIds(itemIds);return order.getId();

改造后的完整代码

package com.hmall.trade.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.api.client.CartClient;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.exception.BadRequestException;
import com.hmall.common.utils.UserContext;
import com.hmall.trade.domain.dto.OrderFormDTO;
import com.hmall.trade.domain.po.Order;
import com.hmall.trade.domain.po.OrderDetail;
import com.hmall.trade.mapper.OrderMapper;
import com.hmall.trade.service.IOrderDetailService;
import com.hmall.trade.service.IOrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;/*** <p>* 服务实现类* </p>*/
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {private final ItemClient itemClient;private final IOrderDetailService detailService;private final CartClient cartClient;@Override@Transactionalpublic Long createOrder(OrderFormDTO orderFormDTO) {// 1.订单数据Order order = new Order();// 1.1.查询商品List<OrderDetailDTO> detailDTOS = orderFormDTO.getDetails();// 1.2.获取商品id和数量的MapMap<Long, Integer> itemNumMap = detailDTOS.stream().collect(Collectors.toMap(OrderDetailDTO::getItemId, OrderDetailDTO::getNum));Set<Long> itemIds = itemNumMap.keySet();// 1.3.查询商品List<ItemDTO> items = itemClient.queryItemByIds(itemIds);if (items == null || items.size() < itemIds.size()) {throw new BadRequestException("商品不存在");}// 1.4.基于商品价格、购买数量计算商品总价:totalFeeint total = 0;for (ItemDTO item : items) {total += item.getPrice() * itemNumMap.get(item.getId());}order.setTotalFee(total);// 1.5.其它属性order.setPaymentType(orderFormDTO.getPaymentType());order.setUserId(UserContext.getUser());order.setStatus(1);// 1.6.将Order写入数据库order表中save(order);// 2.保存订单详情List<OrderDetail> details = buildDetails(order.getId(), items, itemNumMap);detailService.saveBatch(details);// 3.扣减库存try {itemClient.deductStock(detailDTOS);} catch (Exception e) {throw new RuntimeException("库存不足!");}// 4.清理购物车商品cartClient.deleteCartItemByIds(itemIds);return order.getId();}private List<OrderDetail> buildDetails(Long orderId, List<ItemDTO> items, Map<Long, Integer> numMap) {List<OrderDetail> details = new ArrayList<>(items.size());for (ItemDTO item : items) {OrderDetail detail = new OrderDetail();detail.setName(item.getName());detail.setSpec(item.getSpec());detail.setPrice(item.getPrice());detail.setNum(numMap.get(item.getId()));detail.setItemId(item.getId());detail.setImage(item.getImage());detail.setOrderId(orderId);details.add(detail);}return details;}@Overridepublic void markOrderPaySuccess(Long orderId) {Order order = new Order();order.setId(orderId);order.setStatus(2); // 假设 2 表示“已支付”状态updateById(order);}}

 要将service换成Client

(5)测试 

这里在测试的时候遇到了2个问题

a-包导错了

因为包太多太乱了,所以有些蒙了,这里的所有的包都导成trade-service模块下的这点特别重要

b-又忘记nacos

错误处理完毕就可以测试了

这别忘了修改

 数据库别忘了连接

 可以看到查询到数据库中的数据了

 后台同样也有结果了

四、支付部分

1、创建pay-service模块

还是先将基础包创建出来

2、改造pay-service模块

(1)pom文件

<?xml version="1.0" encoding="UTF-8"?>
<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"><parent><artifactId>hmall</artifactId><groupId>com.heima</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>pay-service</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency><!--api--><dependency><groupId>com.heima</groupId><artifactId>hm-api</artifactId><version>1.0.0</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!--nacos 服务注册发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

(2)修改模块

将相对应的包拉去过来

(3)yaml文件

(4)改造代码 

扣减用户余额

 新建一个接口存储用户相关的

package com.hmall.api.client;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;@FeignClient("user-service")
public interface UserClient {@PutMapping("/users/money/deduct")void deductMoney(@RequestParam("pw") String pw,@RequestParam("amount") Integer amount);
}

标记订单状态

 

package com.hmall.api.client;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;@FeignClient("trade-service")
public interface TradeClient {@PutMapping("/orders/{orderId}")void markOrderPaySuccess(@PathVariable("orderId") Long orderId);
}

改造PayOrderServiceImpl

package com.hmall.pay.service.impl;import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.api.client.TradeClient;
import com.hmall.api.client.UserClient;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.BeanUtils;
import com.hmall.common.utils.UserContext;
import com.hmall.pay.domain.dto.PayApplyDTO;
import com.hmall.pay.domain.dto.PayOrderFormDTO;
import com.hmall.pay.domain.po.PayOrder;
import com.hmall.pay.enums.PayStatus;
import com.hmall.pay.mapper.PayOrderMapper;
import com.hmall.pay.service.IPayOrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.time.LocalDateTime;/*** <p>* 支付订单 服务实现类* </p>**/
@Service
@RequiredArgsConstructor
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {private final UserClient userClient;private final TradeClient tradeClient;@Overridepublic String applyPayOrder(PayApplyDTO applyDTO) {// 1.幂等性校验PayOrder payOrder = checkIdempotent(applyDTO);// 2.返回结果return payOrder.getId().toString();}@Override@Transactionalpublic void tryPayOrderByBalance(PayOrderFormDTO payOrderDTO) {// 1.查询支付单PayOrder po = getById(payOrderDTO.getId());// 2.判断状态if(!PayStatus.WAIT_BUYER_PAY.equalsValue(po.getStatus())){// 订单不是未支付,状态异常throw new BizIllegalException("交易已支付或关闭!");}// 3.尝试扣减余额userClient.deductMoney(payOrderDTO.getPw(), po.getAmount());// 4.修改支付单状态boolean success = markPayOrderSuccess(payOrderDTO.getId(), LocalDateTime.now());if (!success) {throw new BizIllegalException("交易已支付或关闭!");}// 5.修改订单状态tradeClient.markOrderPaySuccess(po.getBizOrderNo());}public boolean markPayOrderSuccess(Long id, LocalDateTime successTime) {return lambdaUpdate().set(PayOrder::getStatus, PayStatus.TRADE_SUCCESS.getValue()).set(PayOrder::getPaySuccessTime, successTime).eq(PayOrder::getId, id)// 支付状态的乐观锁判断.in(PayOrder::getStatus, PayStatus.NOT_COMMIT.getValue(), PayStatus.WAIT_BUYER_PAY.getValue()).update();}private PayOrder checkIdempotent(PayApplyDTO applyDTO) {// 1.首先查询支付单PayOrder oldOrder = queryByBizOrderNo(applyDTO.getBizOrderNo());// 2.判断是否存在if (oldOrder == null) {// 不存在支付单,说明是第一次,写入新的支付单并返回PayOrder payOrder = buildPayOrder(applyDTO);payOrder.setPayOrderNo(IdWorker.getId());save(payOrder);return payOrder;}// 3.旧单已经存在,判断是否支付成功if (PayStatus.TRADE_SUCCESS.equalsValue(oldOrder.getStatus())) {// 已经支付成功,抛出异常throw new BizIllegalException("订单已经支付!");}// 4.旧单已经存在,判断是否已经关闭if (PayStatus.TRADE_CLOSED.equalsValue(oldOrder.getStatus())) {// 已经关闭,抛出异常throw new BizIllegalException("订单已关闭");}// 5.旧单已经存在,判断支付渠道是否一致if (!StringUtils.equals(oldOrder.getPayChannelCode(), applyDTO.getPayChannelCode())) {// 支付渠道不一致,需要重置数据,然后重新申请支付单PayOrder payOrder = buildPayOrder(applyDTO);payOrder.setId(oldOrder.getId());payOrder.setQrCodeUrl("");updateById(payOrder);payOrder.setPayOrderNo(oldOrder.getPayOrderNo());return payOrder;}// 6.旧单已经存在,且可能是未支付或未提交,且支付渠道一致,直接返回旧数据return oldOrder;}private PayOrder buildPayOrder(PayApplyDTO payApplyDTO) {// 1.数据转换PayOrder payOrder = BeanUtils.toBean(payApplyDTO, PayOrder.class);// 2.初始化数据payOrder.setPayOverTime(LocalDateTime.now().plusMinutes(120L));payOrder.setStatus(PayStatus.WAIT_BUYER_PAY.getValue());payOrder.setBizUserId(UserContext.getUser());return payOrder;}public PayOrder queryByBizOrderNo(Long bizOrderNo) {return lambdaQuery().eq(PayOrder::getBizOrderNo, bizOrderNo).one();}
}

(5)测试

连接下数据库

 改为local

测试成功了 

 后台也返回出了查询数据

结语

本文记录了微服务项目拆分实践过程,主要分为用户、交易和支付三个模块的改造。作者详细介绍了每个模块的创建步骤,包括pom文件配置、模块结构调整、yaml文件编写和代码改造。在用户模块实现了用户服务基础功能;交易模块重点处理了订单创建、库存扣减和购物车清理;支付模块则完成了余额扣减和订单状态更新。文章特别强调了包导入的正确性和Nacos服务注册的重要性,并分享了测试过程中遇到的数据库连接、包导入错误等问题的解决方法。通过逐步拆分和改造,最终完成了三个微服务模块的独立部署和测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94773.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94773.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/94773.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何实现一个简单的基于Spring Boot的用户权限管理系统?

全文目录&#xff1a;开篇语前言系统设计概述步骤一&#xff1a;创建Spring Boot项目步骤二&#xff1a;配置数据库步骤三&#xff1a;定义实体类1. 用户实体类 User2. 角色实体类 Role3. 权限实体类 Permission步骤四&#xff1a;创建JPA Repository步骤五&#xff1a;配置Spr…

机器学习及其KNN算法

一、机器学习概述机器学习&#xff08;Machine Learning, ML&#xff09;是人工智能的核心分支&#xff0c;旨在通过算法让计算机从数据中自动学习规律并优化性能&#xff0c;而无需显式编程。这一技术领域起源于20世纪50年代&#xff0c;随着计算能力的提升和大数据时代的到来…

Kaggle 经典竞赛泰坦尼克号:超级无敌爆炸详细基础逐行讲解Pytorch实现代码,看完保证你也会!!!

讲解代码分为3个步骤&#xff1a;有什么用&#xff0c;为什么需要他&#xff0c;如何使用保证大家耐心看完一定大有裨益&#xff01;如果有懂的可以跳过&#xff0c;不过建议可以看完&#xff0c;查漏补缺嘛。现在开始吧&#xff01;项目目标我们的目标是根据泰坦尼克号乘客的个…

双目标定中旋转矩阵参数应用及旋转角度计算(聚焦坐标系平行)

一、引言 在双目视觉系统开发中&#xff0c;若需实现右相机坐标系与左相机坐标系平行&#xff0c;核心在于通过双目标定获取的旋转矩阵RRR&#xff0c;消除两相机间的相对旋转。本报告聚焦旋转矩阵的物理意义与工程应用&#xff0c;详细说明如何通过旋转矩阵计算相对旋转角度&a…

GraphRAG 入门教程:从原理到实战

GraphRAG 入门教程&#xff1a;从原理到实战 1. 什么是 GraphRAG&#xff1f; GraphRAG 是一种结构化的、分层的检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称 RAG&#xff09;方法 和传统的 RAG 不同&#xff0c;GraphRAG 不仅仅依赖文本相似度搜索…

系统集成项目管理工程师【第十一章 规划过程组】规划成本管理、成本估算、制定预算和规划质量管理篇

系统集成项目管理工程师【第十一章 规划过程组】规划成本管理、成本估算、制定预算和规划质量管理篇 一、规划成本管理&#xff1a;为成本管控定方向 规划成本管理是项目成本管理的起点&#xff0c;其核心是明确“如何管”的规则&#xff0c;为整个项目的成本管理提供统一框架。…

Xiphos Q8 SDR DOCK子板 AD9361 宽带收发器的 SDR 模块。

Q8 混合处理器卡的子板&#xff0c;包含基于 ADI 公司流行的 AD9361 宽带收发器的 SDR 模块。与基于 AD9361 的 SDR 模块接口PPS、CAN总线、串行、UART&#xff08;LVDS&#xff09;、USB接口电源接口&#xff08;5V、12V&#xff09; Q8 处理器卡的子板&#xff0c;集成了基于…

DPU(数据处理单元)架构中,SoC(系统级芯片)与FPGA(现场可编程门阵列)之间的数据交互

在DPU&#xff08;数据处理单元&#xff09;架构中&#xff0c;SoC&#xff08;系统级芯片&#xff09;与FPGA&#xff08;现场可编程门阵列&#xff09;之间的数据交互是实现高效异构计算的关键。根据通信目标和硬件特性&#xff0c;其交互数据类型可分为以下四类&#xff1a;…

图论(邻接表)DFS

竞赛中心 - 蓝桥云课 #include<bits/stdc.h> using namespace std; #define int long long const int A1e51; typedef pair<int,int>p; map<p,int>st; vector<p>edge[A]; int a[A]; int result0; bool dfs(int s,int u,int father,int v,int sum) {i…

深入理解VideoToolbox:iOS/macOS视频硬编解码实战指南

引言&#xff1a;VideoToolbox框架概述 VideoToolbox是Apple提供的底层框架&#xff0c;首次在WWDC2014上推出&#xff0c;为iOS和macOS开发者提供直接访问硬件编码器和解码器的能力。作为Core Media框架的重要组成部分&#xff0c;VideoToolbox专注于视频压缩、解压缩以及Cor…

Python基础语法练习

本文涵盖了 Python 基础编程中的多个重要概念&#xff0c;从简单的输出语句到运算符、字符串操作、变量赋值等都有涉及。这些例子非常适合初学者学习和理解 Python 的基本语法。1. Hello World# 输出Hello Worldprint("Hello, World!")2. 变量赋值# 创建变量并赋值na…

关于“致命错误:‘https://github.com/....git/‘ 鉴权失败”

问题分析 错误信息&#xff1a; remote: Invalid username or token. Password authentication is not supported for Git operations. 致命错误&#xff1a;https://github.com/yarajia/LittleTestToolsProject.git/ 鉴权失败原因&#xff1a;GitHub从2021年8月13日起不再支持…

基于Flask + Vue3 的新闻数据分析平台源代码+数据库+使用说明,爬取今日头条新闻数据,采集与清洗、数据分析、建立数据模型、数据可视化

介绍 本项目为新闻数据分析平台&#xff0c;目的是爬取新闻(目前仅含爬取今日头条)数据&#xff0c;然后对数据进行展示、采集与清洗、数据分析、建立数据模型、数据可视化。本项目采用前后端分离模式&#xff0c;前端使用 Vue3 ArcoDesign 搭建&#xff0c;后端使用 Python …

LabVIEW数字抽取滤波

​基于 LabVIEW 平台设计数字抽取滤波器&#xff0c;用于动态测试领域&#xff0c;解决高采样率数据的大动态范围需求与频带划分问题。方案替换硬件为可靠性优异的品牌&#xff0c;通过虚拟仪器架构实现信号处理功能&#xff0c;为动态信号分析提供高效、可复用的设计参考。应用…

云原生时代的 Linux:容器、虚拟化与分布式的基石

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 在云计算与容器化快速发展的今天&#xff0c;Linux 已经不再只是服务器上的操作系统&#xff0c;而是整个云原生生态的底层基石。无论是运…

多场景两阶段分布式鲁棒优化模型、数据驱动的综合能源系统

基于数据驱动的综合能源系统多场景两阶段分布式鲁棒优化模型 鲁棒优化是应对数据不确定性的一种优化方法&#xff0c;但单阶段鲁棒优化过于保守。为了解决这一问题&#xff0c;引入了两阶段鲁棒优化(Two-stage Robust Optimization)以及更一般的多阶段鲁棒优化&#xff0c;其核…

Python实现点云PCA配准——粗配准

本节我们来介绍PCA&#xff08;主成分分析&#xff09;算法进行点云配准&#xff0c;这是一种经典的统计降维与特征提取工具&#xff0c;在三维点云处理中常被用来完成“粗配准”。其核心思想是&#xff1a;先把两个待对齐的点云各自进行主成分分解&#xff0c;获得各自的“主轴…

零基础深度学习规划路线:从数学公式到AI大模型的系统进阶指南

引言在人工智能革命席卷全球的2025年&#xff0c;深度学习已成为改变行业格局的核心技术。本规划路线整合最新教育资源与实践方法&#xff0c;为完全零基础的学习者构建一条从数学基础到AI大模型的系统学习路径。通过清华大佬的实战课程、吴恩达的经典理论、Kaggle竞赛的实战锤…

基于Vue.js和Golang构建高效在线客服系统:前端实现与后端交互详解

在当今互联网时代&#xff0c;在线客服系统已成为企业与用户沟通的重要桥梁。本文将详细介绍如何使用Vue.js作为前端框架&#xff0c;Gin作为后端框架&#xff0c;构建一个高效的在线客服系统。一、项目背景与技术选型项目背景随着电子商务的迅猛发展&#xff0c;用户对即时咨询…

虚幻GAS底层原理解剖九 (内存管理)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、整体内存管理思路概览二、核心对象的生命周期与托管逻辑UGameplayAbility 的管理GameplayEffect 的内存管理ActiveGameplayEffect 生命周期三、属性&#xf…