RocketMQ 实战:模拟电商网站场景综合案例(三)
一、环境搭建:数据库表结构介绍
1、优惠券表
Field Type Comment coupon_id decigint(50) NOT NULL 优惠券ID coupon_price decimal(10,2) NULL 优惠券金额 user id bigint(50) NULL 用户ID order id bigint(32)NULL 订单ID is used int(1) NULL 是否使用 0未使用 1已使用 used time timestamp NULL 使用时间
2、商品表
Field Type Comment goods id bigint(50) NOT NULL 主键 goods name varchar(255) NULL 商品名称 goods number int(11) NULL 商品库存 goods_price decimal(10,2) NULL 商品价格 goods desc varchar(255) NULL 商品描述 add time timestamp NULL 添加时间
3、订单表
Field Type Comment order _id bigint(50) NOT NULL 订单ID user _id bigint(50) NULL 用户ID order status int(1) NULL 订单状态 0未确认 1己确认 2已取消 3无效 4退款 pay_status int(1) NULL 支付状态 0未支付 1支付中 2已支付 shipping_status int(1) NULL 发货状态 0未发货 1已发货 2已退货 address varchar(255) NULL 收货地址 consignee varchar(255)NULL 收货人 goods id bigint(50) NULL 商品ID goods number int(11) NULL 商品数量 goods price decimal(10,2) NULL 商品价格 goods amount decimal(10,0) NULL 商品总价 shipping_fee decimal(10,2) NULL 运费 order amount decimal(10,2) NULL 订单价格 coupon_id bigint(50) NULL 优惠券ID coupon_paid decimal(10,2) NULL 优惠券 money_paid decimal(10,2) NULL 已付金额 pay_amount decimal(10,2) NULL 支付金额 add time timestamp NULL 创建时间
4、订单商品日志表
Field Type Comment goods id int(11) NOT NULL 商品ID order id varchar(32) NOT NULL 订单ID goods number int(11) NULL 库存数量 log_time datetime NULL 记录时间
5、用户表
Field Type Comment user id bigint(50) NOT NULL 用户ID user_name varchar(255) NULL 用户姓名 user password varchar(255)NULL 用户密码 user mobile varchar(255)NULL 手机号 user score int(11)NULL 积分 user_reg_time timestamp NULL 注册时间 user money decimal(10,0)NULL 用户余额
6、用户余额日志表
Field Type Comment Juser id bigint(50) NOT NULL 用户ID order id bigint(50) NOT NULL 订单ID money_log_type int(1) NOT NULL 日志类型 1订单付款 2 订单退款 use money decimal(10,2) NULL 操作金额 create time timestamp NULL 日志时间
7、订单支付表
Field Type Comment pay_id bigint(50) NOT NULL 支付编号 order id bigint(50) NULL 订单编号 pay_amount decimal(10,2) NULL 支付金额 is_paid int(1) NULL 是否已支付 1否 2是
8、MQ 消息生产表
Field Type Comment id varchar(100) NOT NULL 主键 group _name varchar(100) NULL 生产者组名 msg_topic varchar(100) NULL 消息主题 msg_tag varchar(100) NULL Tag msg_key varchar(100) NULL Key hsg body varchar(500) NULL 消息内容 msg status int(1)NULL 0:未处理;1:已经处理 create time timestamp NOT NULL 记录时间
9、MQ 消息消费表
Field Type Comment msg_id varchar(50) NULL 消息ID group name varchar(100) NOT NULL 消费者组名 msg_tag varchar(100) NOT NULL Tag msg_key varchar(100) NOT NULL Key msg_body varchar(500) NULL 消息体 consumer status int(1) NULL 0:正在处理;1:处理成功;2:处理失败 consumer times int(1)NULL 消费次数 consumer_timestamp timestamp NULL 消费时间 remark varchar(500)NULL 备注
10、在 mysql 中,创建这 9 张表。
1)用 SQLyong 连接 mysql 数据库
保存的连接:localhost
MySQL Host Address : 如:localhost
用户名:root
密码:root
端口:3306【连接】
2)创建 trade 数据库。
3)创建 9 个 数据表。
/*
SQLyog Ultimate v8.32
MySQL - 5.5 .49 : Database - trade
*********************************************************************
*//*! 40101 SET NAMES utf8 */; /*! 40101 SET SQL_MODE = '' */; /*! 40014 SET @OLD_UNIQUE_CHECKS= @@UNIQUE_CHECKS, UNIQUE_CHECKS = 0 */;
/*! 40014 SET @OLD_FOREIGN_KEY_CHECKS= @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS = 0 */;
/*! 40101 SET @OLD_SQL_MODE= @@SQL_MODE, SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO' */;
/*! 40111 SET @OLD_SQL_NOTES= @@SQL_NOTES, SQL_NOTES = 0 */;
CREATE DATABASE /*! 32312 IF NOT EXISTS*/` trade` /*! 40100 DEFAULT CHARACTER SET utf8 */; USE ` trade` ; /*Table structure for table ` trade_coupon` */DROP TABLE IF EXISTS ` trade_coupon` ; CREATE TABLE ` trade_coupon` ( ` coupon_id` bigint( 50 ) NOT NULL COMMENT '优惠券ID' ,` coupon_price` decimal( 10,2 ) DEFAULT NULL COMMENT '优惠券金额' ,` user_id` bigint( 50 ) DEFAULT NULL COMMENT '用户ID' ,` order_id` bigint( 32 ) DEFAULT NULL COMMENT '订单ID' ,` is_used` int( 1 ) DEFAULT NULL COMMENT '是否使用 0未使用 1已使用' ,` used_time` timestamp NULL DEFAULT NULL COMMENT '使用时间' ,PRIMARY KEY ( ` coupon_id` ) ,KEY ` FK_trade_coupon` ( ` user_id` ) ,KEY ` FK_trade_coupon2` ( ` order_id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_coupon` *//*Table structure for table ` trade_goods` */DROP TABLE IF EXISTS ` trade_goods` ; CREATE TABLE ` trade_goods` ( ` goods_id` bigint( 50 ) NOT NULL AUTO_INCREMENT,` goods_name` varchar( 255 ) DEFAULT NULL COMMENT '商品名称' ,` goods_number` int( 11 ) DEFAULT NULL COMMENT '商品库存' ,` goods_price` decimal( 10,2 ) DEFAULT NULL COMMENT '商品价格' ,` goods_desc` varchar( 255 ) DEFAULT NULL COMMENT '商品描述' ,` add_time` timestamp NULL DEFAULT NULL COMMENT '添加时间' ,PRIMARY KEY ( ` goods_id` )
) ENGINE = InnoDB AUTO_INCREMENT = 345959443973935105 DEFAULT CHARSET = utf8; /*Data for the table ` trade_goods` */insert into ` trade_goods` ( ` goods_id` ,` goods_name` ,` goods_number` ,` goods_price` ,` goods_desc` ,` add_time` ) values ( 345959443973935104 ,'华为P30' ,999,'5000.00' ,'夜间拍照更美' ,'2019-07-09 20:38:00' ) ; /*Table structure for table ` trade_goods_number_log` */DROP TABLE IF EXISTS ` trade_goods_number_log` ; CREATE TABLE ` trade_goods_number_log` ( ` goods_id` bigint( 50 ) NOT NULL COMMENT '商品ID' ,` order_id` bigint( 50 ) NOT NULL COMMENT '订单ID' ,` goods_number` int( 11 ) DEFAULT NULL COMMENT '库存数量' ,` log_time` timestamp NULL DEFAULT NULL,PRIMARY KEY ( ` goods_id` ,` order_id` ) ,KEY ` FK_trade_goods_number_log2` ( ` order_id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_goods_number_log` *//*Table structure for table ` trade_mq_consumer_log` */DROP TABLE IF EXISTS ` trade_mq_consumer_log` ; CREATE TABLE ` trade_mq_consumer_log` ( ` msg_id` varchar( 50 ) DEFAULT NULL,` group_name` varchar( 100 ) NOT NULL,` msg_tag` varchar( 100 ) NOT NULL,` msg_key` varchar( 100 ) NOT NULL,` msg_body` varchar( 500 ) DEFAULT NULL,` consumer_status` int( 1 ) DEFAULT NULL COMMENT '0:正在处理;1:处理成功;2:处理失败' ,` consumer_times` int( 1 ) DEFAULT NULL,` consumer_timestamp` timestamp NULL DEFAULT NULL,` remark` varchar( 500 ) DEFAULT NULL,PRIMARY KEY ( ` group_name` ,` msg_tag` ,` msg_key` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_mq_consumer_log` *//*Table structure for table ` trade_mq_producer_temp` */DROP TABLE IF EXISTS ` trade_mq_producer_temp` ; CREATE TABLE ` trade_mq_producer_temp` ( ` id ` varchar( 100 ) NOT NULL,` group_name` varchar( 100 ) DEFAULT NULL,` msg_topic` varchar( 100 ) DEFAULT NULL,` msg_tag` varchar( 100 ) DEFAULT NULL,` msg_key` varchar( 100 ) DEFAULT NULL,` msg_body` varchar( 500 ) DEFAULT NULL,` msg_status` int( 1 ) DEFAULT NULL COMMENT '0:未处理;1:已经处理' ,` create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY ( ` id ` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_mq_producer_temp` *//*Table structure for table ` trade_order` */DROP TABLE IF EXISTS ` trade_order` ; CREATE TABLE ` trade_order` ( ` order_id` bigint( 50 ) NOT NULL COMMENT '订单ID' ,` user_id` bigint( 50 ) DEFAULT NULL COMMENT '用户ID' ,` order_status` int( 1 ) DEFAULT NULL COMMENT '订单状态 0未确认 1已确认 2已取消 3无效 4退款' ,` pay_status` int( 1 ) DEFAULT NULL COMMENT '支付状态 0未支付 1支付中 2已支付' ,` shipping_status` int( 1 ) DEFAULT NULL COMMENT '发货状态 0未发货 1已发货 2已收货' ,` address` varchar( 255 ) DEFAULT NULL COMMENT '收货地址' ,` consignee` varchar( 255 ) DEFAULT NULL COMMENT '收货人' ,` goods_id` bigint( 50 ) DEFAULT NULL COMMENT '商品ID' ,` goods_number` int( 11 ) DEFAULT NULL COMMENT '商品数量' ,` goods_price` decimal( 10,2 ) DEFAULT NULL COMMENT '商品价格' ,` goods_amount` decimal( 10,0 ) DEFAULT NULL COMMENT '商品总价' ,` shipping_fee` decimal( 10,2 ) DEFAULT NULL COMMENT '运费' ,` order_amount` decimal( 10,2 ) DEFAULT NULL COMMENT '订单价格' ,` coupon_id` bigint( 50 ) DEFAULT NULL COMMENT '优惠券ID' ,` coupon_paid` decimal( 10,2 ) DEFAULT NULL COMMENT '优惠券' ,` money_paid` decimal( 10,2 ) DEFAULT NULL COMMENT '已付金额' ,` pay_amount` decimal( 10,2 ) DEFAULT NULL COMMENT '支付金额' ,` add_time` timestamp NULL DEFAULT NULL COMMENT '创建时间' ,` confirm_time` timestamp NULL DEFAULT NULL COMMENT '订单确认时间' ,` pay_time` timestamp NULL DEFAULT NULL COMMENT '支付时间' ,PRIMARY KEY ( ` order_id` ) ,KEY ` FK_trade_order` ( ` user_id` ) ,KEY ` FK_trade_order2` ( ` goods_id` ) ,KEY ` FK_trade_order3` ( ` coupon_id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_order` *//*Table structure for table ` trade_pay` */DROP TABLE IF EXISTS ` trade_pay` ; CREATE TABLE ` trade_pay` ( ` pay_id` bigint( 50 ) NOT NULL COMMENT '支付编号' ,` order_id` bigint( 50 ) DEFAULT NULL COMMENT '订单编号' ,` pay_amount` decimal( 10,2 ) DEFAULT NULL COMMENT '支付金额' ,` is_paid` int( 1 ) DEFAULT NULL COMMENT '是否已支付 1否 2是' ,PRIMARY KEY ( ` pay_id` ) ,KEY ` FK_trade_pay` ( ` order_id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_pay` *//*Table structure for table ` trade_user` */DROP TABLE IF EXISTS ` trade_user` ; CREATE TABLE ` trade_user` ( ` user_id` bigint( 50 ) NOT NULL AUTO_INCREMENT COMMENT '用户ID' ,` user_name` varchar( 255 ) DEFAULT NULL COMMENT '用户姓名' ,` user_password` varchar( 255 ) DEFAULT NULL COMMENT '用户密码' ,` user_mobile` varchar( 255 ) DEFAULT NULL COMMENT '手机号' ,` user_score` int( 11 ) DEFAULT NULL COMMENT '积分' ,` user_reg_time` timestamp NULL DEFAULT NULL COMMENT '注册时间' ,` user_money` decimal( 10,0 ) DEFAULT NULL COMMENT '用户余额' ,PRIMARY KEY ( ` user_id` )
) ENGINE = InnoDB AUTO_INCREMENT = 345963634385633281 DEFAULT CHARSET = utf8; /*Data for the table ` trade_user` */insert into ` trade_user` ( ` user_id` ,` user_name` ,` user_password` ,` user_mobile` ,` user_score` ,` user_reg_time` ,` user_money` ) values ( 345963634385633280 ,'刘备' ,'123L' ,'18888888888L' ,100,'2019-07-09 13:37:03' ,'900' ) ; /*Table structure for table ` trade_user_money_log` */DROP TABLE IF EXISTS ` trade_user_money_log` ; CREATE TABLE ` trade_user_money_log` ( ` user_id` bigint( 50 ) NOT NULL COMMENT '用户ID' ,` order_id` bigint( 50 ) NOT NULL COMMENT '订单ID' ,` money_log_type` int( 1 ) NOT NULL COMMENT '日志类型 1订单付款 2 订单退款' ,` use_money` decimal( 10,2 ) DEFAULT NULL,` create_time` timestamp NULL DEFAULT NULL COMMENT '日志时间' ,PRIMARY KEY ( ` user_id` ,` order_id` ,` money_log_type` ) ,KEY ` FK_trade_user_money_log2` ( ` order_id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8; /*Data for the table ` trade_user_money_log` *//*! 40101 SET SQL_MODE = @OLD_SQL_MODE */;
/*! 40014 SET FOREIGN_KEY_CHECKS = @OLD_FOREIGN_KEY_CHECKS */;
/*! 40014 SET UNIQUE_CHECKS = @OLD_UNIQUE_CHECKS */;
/*! 40111 SET SQL_NOTES = @OLD_SQL_NOTES */;
二、项目工程初始化
1、创建 shop-parent 父工程,并在 pom.xml 中,导入依赖坐标。
< ?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" > < modelVersion> 4.0 .0 < /modelVersion> < groupId> com.iteima.shop< /groupId> < artifactId> shop-parent< /artifactId> < packaging> pom< /packaging> < version> 1.0 -SNAPSHOT< /version> < parent> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-parent< /artifactId> < version> 2.0 .1.RELEASE< /version> < /parent> < properties> < rocketmq-spring-boot-starter-version> 2.0 .3 < /rocketmq-spring-boot-starter-version> < /properties> < dependencies> < ! --dubbo--> < dependency> < groupId> com.alibaba.spring.boot< /groupId> < artifactId> dubbo-spring-boot-starter< /artifactId> < version> 2.0 .0 < /version> < /dependency> < ! --spring-boot-stater--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter< /artifactId> < exclusions> < exclusion> < artifactId> log4j-to-slf4j< /artifactId> < groupId> org.apache.logging.log4j< /groupId> < /exclusion> < /exclusions> < /dependency> < ! --zookeeper--> < dependency> < groupId> org.apache.zookeeper< /groupId> < artifactId> zookeeper< /artifactId> < version> 3.4 .10 < /version> < exclusions> < exclusion> < groupId> org.slf4j< /groupId> < artifactId> slf4j-log4j12 < /artifactId> < /exclusion> < exclusion> < groupId> log4j< /groupId> < artifactId> log4j< /artifactId> < /exclusion> < /exclusions> < /dependency> < dependency> < groupId> com.101tec< /groupId> < artifactId> zkclient< /artifactId> < version> 0 .9 < /version> < exclusions> < exclusion> < artifactId> slf4j-log4j12 < /artifactId> < groupId> org.slf4j< /groupId> < /exclusion> < /exclusions> < /dependency> < ! --Test--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-test< /artifactId> < scope> test< /scope> < /dependency> < dependency> < groupId> junit< /groupId> < artifactId> junit< /artifactId> < /dependency> < ! --RocketMQ--> < dependency> < groupId> org.apache.rocketmq< /groupId> < artifactId> rocketmq-spring-boot-starter< /artifactId> < version> ${rocketmq-spring-boot-starter-version} < /version> < /dependency> < ! --lombok--> < dependency> < groupId> org.projectlombok< /groupId> < artifactId> lombok< /artifactId> < version> 1.18 .6 < /version> < /dependency> < /dependencies> < modules> < module> .. /shop-order-web< /module> < module> .. /shop-coupon-service< /module> < module> .. /shop-user-service< /module> < module> .. /shop-order-service< /module> < module> .. /shop-pay-web< /module> < module> .. /shop-pojo< /module> < module> .. /shop-common< /module> < module> .. /shop-api< /module> < module> .. /shop-goods-service< /module> < module> .. /shop-pay-service< /module> < /modules> < build> < plugins> < plugin> < groupId> org.apache.maven.plugins< /groupId> < artifactId> maven-compiler-plugin< /artifactId> < version> 3.7 .0 < /version> < configuration> < target> 1 .8 < /target> < source> 1 .8 < /source> < /configuration> < /plugin> < /plugins> < /build> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-parent\ pom.xml -->
2、创建 shop-api 接口层 工程。
2.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-api< /artifactId> < dependencies> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-api\ pom.xml -->
2.2、创建 优惠券接口 类 ICouponService.java
package com.itheima.api; import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradeCoupon; /*** 优惠券接口*/
public interface ICouponService { /*** 根据ID查询优惠券对象* @param coupouId* @return*/public TradeCoupon findOne( Long coupouId) ; /*** 更细优惠券状态* @param coupon* @return*/Result updateCouponStatus( TradeCoupon coupon) ;
}
2.3、创建 接口 类 IGoodsService.java
package com.itheima.api; import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradeGoods;
import com.itheima.shop.pojo.TradeGoodsNumberLog; public interface IGoodsService { /*** 根据ID查询商品对象* @param goodsId* @return*/TradeGoods findOne( Long goodsId) ; /*** 扣减库存* @param goodsNumberLog* @return*/Result reduceGoodsNum( TradeGoodsNumberLog goodsNumberLog) ;
}
2.4、创建 接口 类 IOrderService.java
package com.itheima.api; import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradeOrder; public interface IOrderService { /*** 下单接口* @param order* @return*/public Result confirmOrder( TradeOrder order) ; }
2.5、创建 接口 类 IPayService.java
package com.itheima.api; import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradePay;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.remoting.exception.RemotingException; public interface IPayService { public Result createPayment( TradePay tradePay) ; public Result callbackPayment( TradePay tradePay) throws InterruptedException, RemotingException, MQClientException, MQBrokerException; }
2.6、创建 接口 类 IUserService.java
package com.itheima.api; import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradeUser;
import com.itheima.shop.pojo.TradeUserMoneyLog; public interface IUserService { TradeUser findOne( Long userId) ; Result updateMoneyPaid( TradeUserMoneyLog userMoneyLog) ;
}
3、创建 shop-common 工具工程。
3.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-common< /artifactId> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-common\ pom.xml -->
3.2、创建 类 ShopCode.java
package com.itheima.constant; /*** @author Think*/public enum ShopCode { //正确SHOP_SUCCESS( true, 1 , "正确" ) ,//错误SHOP_FAIL( false, 0 , "错误" ) ,//付款SHOP_USER_MONEY_PAID( true, 1 , "付款" ) ,//退款SHOP_USER_MONEY_REFUND( true, 2 , "退款" ) ,//订单未确认SHOP_ORDER_NO_CONFIRM( false, 0 , "订单未确认" ) ,//订单已确认SHOP_ORDER_CONFIRM( true, 1 , "订单已经确认" ) ,//订单已取消SHOP_ORDER_CANCEL( false, 2 , "订单已取消" ) ,//订单已取消SHOP_ORDER_INVALID( false, 3 , "订单无效" ) ,//订单已取消SHOP_ORDER_RETURNED( false, 4 , "订单已退货" ) ,//订单已付款SHOP_ORDER_PAY_STATUS_NO_PAY( true,0,"订单未付款" ) ,//订单已付款SHOP_ORDER_PAY_STATUS_PAYING( true,1,"订单正在付款" ) ,//订单已付款SHOP_ORDER_PAY_STATUS_IS_PAY( true,2,"订单已付款" ) ,//消息正在处理SHOP_MQ_MESSAGE_STATUS_PROCESSING( true, 0 , "消息正在处理" ) ,//消息处理成功SHOP_MQ_MESSAGE_STATUS_SUCCESS( true, 1 , "消息处理成功" ) ,//消息处理失败SHOP_MQ_MESSAGE_STATUS_FAIL( false, 2 , "消息处理失败" ) ,//请求参数有误SHOP_REQUEST_PARAMETER_VALID( false, -1, "请求参数有误" ) ,//优惠券已经使用SHOP_COUPON_ISUSED( true, 1 , "优惠券已经使用" ) ,//优惠券未使用SHOP_COUPON_UNUSED( false, 0 , "优惠券未使用" ) ,//快递运费不正确SHOP_ORDER_STATUS_UPDATE_FAIL( false, 10001 , "订单状态修改失败" ) ,//快递运费不正确SHOP_ORDER_SHIPPINGFEE_INVALID( false, 10002 , "订单运费不正确" ) ,//订单总价格不合法SHOP_ORDERAMOUNT_INVALID( false, 10003 , "订单总价格不正确" ) ,//订单保存失败SHOP_ORDER_SAVE_ERROR( false, 10004 , "订单保存失败" ) ,//订单确认失败SHOP_ORDER_CONFIRM_FAIL( false, 10005 , "订单确认失败" ) ,//商品不存在SHOP_GOODS_NO_EXIST( false, 20001 , "商品不存在" ) ,//订单价格非法SHOP_GOODS_PRICE_INVALID( false, 20002 , "商品价格非法" ) ,//商品库存不足SHOP_GOODS_NUM_NOT_ENOUGH( false, 20003 , "商品库存不足" ) ,//扣减库存失败SHOP_REDUCE_GOODS_NUM_FAIL( false, 20004 , "扣减库存失败" ) ,//库存记录为空SHOP_REDUCE_GOODS_NUM_EMPTY( false, 20005 , "扣减库存失败" ) ,//用户账号不能为空SHOP_USER_IS_NULL( false, 30001 , "用户账号不能为空" ) ,//用户信息不存在SHOP_USER_NO_EXIST( false, 30002 , "用户不存在" ) ,//余额扣减失败SHOP_USER_MONEY_REDUCE_FAIL( false, 30003 , "余额扣减失败" ) ,//已经退款SHOP_USER_MONEY_REFUND_ALREADY( true, 30004 , "订单已经退过款" ) ,//优惠券不不存在SHOP_COUPON_NO_EXIST( false, 40001 , "优惠券不存在" ) ,//优惠券不合法SHOP_COUPON_INVALIED( false, 40002 , "优惠券不合法" ) ,//优惠券使用失败SHOP_COUPON_USE_FAIL( false, 40003 , "优惠券使用失败" ) ,//余额不能小于0SHOP_MONEY_PAID_LESS_ZERO( false, 50001 , "余额不能小于0" ) ,//余额非法SHOP_MONEY_PAID_INVALID( false, 50002 , "余额非法" ) ,//Topic不能为空SHOP_MQ_TOPIC_IS_EMPTY( false, 60001 , "Topic不能为空" ) ,//消息体不能为空SHOP_MQ_MESSAGE_BODY_IS_EMPTY( false, 60002 , "消息体不能为空" ) ,//消息发送失败SHOP_MQ_SEND_MESSAGE_FAIL( false,60003,"消息发送失败" ) ,//支付订单未找到SHOP_PAYMENT_NOT_FOUND( false,70001,"支付订单未找到" ) ,//支付订单已支付SHOP_PAYMENT_IS_PAID( false,70002,"支付订单已支付" ) ,//订单付款失败SHOP_PAYMENT_PAY_ERROR( false,70002,"订单支付失败" ) ; Boolean success; Integer code; String message; ShopCode ( ) { } ShopCode( Boolean success, Integer code, String message) { this.success = success; this.code = code; this.message = message; } public Boolean getSuccess ( ) { return success; } public void setSuccess( Boolean success) { this.success = success; } public Integer getCode ( ) { return code; } public void setCode( Integer code) { this.code = code; } public String getMessage ( ) { return message; } public void setMessage( String message) { this.message = message; } @Overridepublic String toString ( ) { return "ShopCode{" +"success=" + success +", code=" + code +", message='" + message + '\' ' +'}' ; }
}
3.3、创建 类 CastException.java
package com.itheima.exception; import com.itheima.constant.ShopCode;
import lombok.extern.slf4j.Slf4j; /*** 异常抛出类*/
@Slf4j
public class CastException { public static void cast( ShopCode shopCode) { log.error( shopCode.toString( )) ; throw new CustomerException( shopCode) ; }
}
3.4、创建 类 CustomerException.java
package com.itheima.exception; import com.itheima.constant.ShopCode; /*** 自定义异常*/
public class CustomerException extends RuntimeException{ private ShopCode shopCode; public CustomerException( ShopCode shopCode) { this.shopCode = shopCode; }
}
3.5、创建 类 IDWorker.java
package com.itheima.utils; public class IDWorker { /*** 起始的时间戳*/private final static long START_STMP = 1480166465631L; /*** 每一部分占用的位数*/private final static long SEQUENCE_BIT = 12 ; //序列号占用的位数private final static long MACHINE_BIT = 5 ; //机器标识占用的位数private final static long DATACENTER_BIT = 5 ; //数据中心占用的位数/*** 每一部分的最大值*/private final static long MAX_DATACENTER_NUM = -1L ^ ( -1L << DATACENTER_BIT) ; private final static long MAX_MACHINE_NUM = -1L ^ ( -1L << MACHINE_BIT) ; private final static long MAX_SEQUENCE = -1L ^ ( -1L << SEQUENCE_BIT) ; /*** 每一部分向左的位移*/private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; //数据中心private long machineId; //机器标识private long sequence = 0L; //序列号private long lastStmp = -1L; //上一次时间戳public IDWorker( long datacenterId, long machineId) { if ( datacenterId > MAX_DATACENTER_NUM || datacenterId < 0 ) { throw new IllegalArgumentException( "datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0" ) ; } if ( machineId > MAX_MACHINE_NUM || machineId < 0 ) { throw new IllegalArgumentException( "machineId can't be greater than MAX_MACHINE_NUM or less than 0" ) ; } this.datacenterId = datacenterId; this.machineId = machineId; } /*** 产生下一个ID** @return*/public synchronized long nextId ( ) { long currStmp = getNewstmp( ) ; if ( currStmp < lastStmp) { throw new RuntimeException( "Clock moved backwards. Refusing to generate id" ) ; } if ( currStmp == lastStmp) { //相同毫秒内,序列号自增sequence = ( sequence + 1 ) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大if ( sequence == 0L) { currStmp = getNextMill( ) ; } } else { //不同毫秒内,序列号置为0sequence = 0L; } lastStmp = currStmp; return ( currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分| datacenterId << DATACENTER_LEFT //数据中心部分| machineId << MACHINE_LEFT //机器标识部分| sequence; //序列号部分} private long getNextMill ( ) { long mill = getNewstmp( ) ; while ( mill <= lastStmp) { mill = getNewstmp( ) ; } return mill; } private long getNewstmp ( ) { return System.currentTimeMillis( ) ; } public static void main( String[ ] args) { IDWorker idWorker = new IDWorker( 2 , 3 ) ; for ( int i = 0 ; i < 10 ; i++) { System.out.println( idWorker.nextId( )) ; } } }
4、创建 shop-coupon-service 优惠券服务 工程。
4.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-coupon-service< /artifactId> < dependencies> < ! --mybatis-springboot--> < dependency> < groupId> org.mybatis.spring.boot< /groupId> < artifactId> mybatis-spring-boot-starter< /artifactId> < version> 1.3 .1 < /version> < /dependency> < ! -- MySQL连接驱动 --> < dependency> < groupId> mysql< /groupId> < artifactId> mysql-connector-java< /artifactId> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-coupon-service\ pom.xml -->
4.2 创建 类 TradeCouponMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeCoupon;
import com.itheima.shop.pojo.TradeCouponExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeCouponMapper { int countByExample( TradeCouponExample example) ; int deleteByExample( TradeCouponExample example) ; int deleteByPrimaryKey( Long couponId) ; int insert( TradeCoupon record) ; int insertSelective( TradeCoupon record) ; List< TradeCoupon> selectByExample( TradeCouponExample example) ; TradeCoupon selectByPrimaryKey( Long couponId) ; int updateByExampleSelective( @Param( "record" ) TradeCoupon record, @Param( "example" ) TradeCouponExample example) ; int updateByExample( @Param( "record" ) TradeCoupon record, @Param( "example" ) TradeCouponExample example) ; int updateByPrimaryKeySelective( TradeCoupon record) ; int updateByPrimaryKey( TradeCoupon record) ;
}
4.3 创建 类 CancelMQListener.java
package com.itheima.shop.mq; import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.mapper.TradeCouponMapper;
import com.itheima.shop.pojo.TradeCoupon;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException; @Slf4j
@Component
@RocketMQMessageListener( topic = "${mq.order.topic} " , consumerGroup = "${mq.order.consumer.group.name} " , messageModel = MessageModel.BROADCASTING)
public class CancelMQListener implements RocketMQListener< MessageExt> { @Autowiredprivate TradeCouponMapper couponMapper; @Overridepublic void onMessage( MessageExt message) { try { //1. 解析消息内容String body = new String( message.getBody( ) , "UTF-8" ) ; MQEntity mqEntity = JSON.parseObject( body, MQEntity.class) ; log.info( "接收到消息" ) ; if( mqEntity.getCouponId( ) != null) { //2. 查询优惠券信息TradeCoupon coupon = couponMapper.selectByPrimaryKey( mqEntity.getCouponId( )) ; //3.更改优惠券状态coupon.setUsedTime( null) ; coupon.setIsUsed( ShopCode.SHOP_COUPON_UNUSED.getCode( )) ; coupon.setOrderId( null) ; couponMapper.updateByPrimaryKey( coupon) ; } log.info( "回退优惠券成功" ) ; } catch ( UnsupportedEncodingException e) { e.printStackTrace( ) ; log.error( "回退优惠券失败" ) ; } }
}
4.4 创建 类 CouponServiceImpl.java
package com.itheima.shop.service.impl; import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.api.ICouponService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.Result;
import com.itheima.exception.CastException;
import com.itheima.shop.mapper.TradeCouponMapper;
import com.itheima.shop.pojo.TradeCoupon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; @Component
@Service( interfaceClass = ICouponService.class)
public class CouponServiceImpl implements ICouponService{ @Autowiredprivate TradeCouponMapper couponMapper; @Overridepublic TradeCoupon findOne( Long coupouId) { if( coupouId== null) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } return couponMapper.selectByPrimaryKey( coupouId) ; } @Overridepublic Result updateCouponStatus( TradeCoupon coupon) { if( coupon== null|| coupon.getCouponId( ) == null) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } //更新优惠券状态couponMapper.updateByPrimaryKey( coupon) ; return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; }
}
4.5 创建 类 CouponServiceApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
@EnableDubboConfiguration
public class CouponServiceApplication { public static void main( String[ ] args) { SpringApplication.run( CouponServiceApplication.class,args) ; } }
4.6 创建 TradeCouponMapper.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.itheima.shop.mapper.TradeCouponMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeCoupon" > < id column = "coupon_id" property = "couponId" jdbcType = "BIGINT" /> < result column = "coupon_price" property = "couponPrice" jdbcType = "DECIMAL" /> < result column = "user_id" property = "userId" jdbcType = "BIGINT" /> < result column = "order_id" property = "orderId" jdbcType = "BIGINT" /> < result column = "is_used" property = "isUsed" jdbcType = "INTEGER" /> < result column = "used_time" property = "usedTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > coupon_id, coupon_price, user_id, order_id, is_used, used_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeCouponExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_coupon< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.Long" > select < include refid = "Base_Column_List" /> from trade_couponwhere coupon_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.Long" > delete from trade_couponwhere coupon_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeCouponExample" > delete from trade_coupon< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeCoupon" > insert into trade_coupon ( coupon_id, coupon_price, user_id, order_id, is_used, used_time) values ( ) < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeCoupon" > insert into trade_coupon< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "couponId != null" > coupon_id,< /if> < if test = "couponPrice != null" > coupon_price,< /if> < if test = "userId != null" > user_id,< /if> < if test = "orderId != null" > order_id,< /if> < if test = "isUsed != null" > is_used,< /if> < if test = "usedTime != null" > used_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "couponId != null" > < /if> < if test = "couponPrice != null" > < /if> < if test = "userId != null" > < /if> < if test = "orderId != null" > < /if> < if test = "isUsed != null" > < /if> < if test = "usedTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeCouponExample" resultType = "java.lang.Integer" > select count( *) from trade_coupon< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_coupon< set > < if test = "record.couponId != null" > coupon_id = < /if> < if test = "record.couponPrice != null" > coupon_price = < /if> < if test = "record.userId != null" > user_id = < /if> < if test = "record.orderId != null" > order_id = < /if> < if test = "record.isUsed != null" > is_used = < /if> < if test = "record.usedTime != null" > used_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_couponset coupon_id = coupon_price = user_id = order_id = is_used = used_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeCoupon" > update trade_coupon< set > < if test = "couponPrice != null" > coupon_price = < /if> < if test = "userId != null" > user_id = < /if> < if test = "orderId != null" > order_id = < /if> < if test = "isUsed != null" > is_used = < /if> < if test = "usedTime != null" > used_time = < /if> < /set> where coupon_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeCoupon" > update trade_couponset coupon_price = user_id = order_id = is_used = used_time = where coupon_id = < /update>
< /mapper>
4.7 创建 application.properties 配置文件。
spring.application.name = dubbo-coupon-provider
spring.dubbo.application.id = dubbo-coupon-provider
spring.dubbo.application.name = dubbo-coupon-provider
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183
spring.dubbo.server = true
spring.dubbo.protocol.name = dubbo
spring.dubbo.protocol.port = 20881
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/trade?useUnicode= true& characterEncoding = utf8
spring.datasource.username = root
spring.datasource.password = root
mybatis.type-aliases-package= com.itheima.shop.pojo
mybatis.mapper-locations= classpath:com/itheima/shop/mapper/*Mapper.xml
rocketmq.name-server= 192.168 .25.135:9876; 192.168 .25.138:9876
rocketmq.producer.group = orderProducerGroupmq.order.consumer.group.name = order_orderTopic_cancel_group
mq.order.topic = orderTopic
5、创建 shop-goods-service 商品服务 工程。
5.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-goods-service< /artifactId> < dependencies> < ! --mybatis-springboot--> < dependency> < groupId> org.mybatis.spring.boot< /groupId> < artifactId> mybatis-spring-boot-starter< /artifactId> < version> 1.3 .1 < /version> < /dependency> < ! -- MySQL连接驱动 --> < dependency> < groupId> mysql< /groupId> < artifactId> mysql-connector-java< /artifactId> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-goods-service\ pom.xml -->
5.2、 创建 接口 类 TradeGoodsMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeGoods;
import com.itheima.shop.pojo.TradeGoodsExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeGoodsMapper { int countByExample( TradeGoodsExample example) ; int deleteByExample( TradeGoodsExample example) ; int deleteByPrimaryKey( Long goodsId) ; int insert( TradeGoods record) ; int insertSelective( TradeGoods record) ; List< TradeGoods> selectByExample( TradeGoodsExample example) ; TradeGoods selectByPrimaryKey( Long goodsId) ; int updateByExampleSelective( @Param( "record" ) TradeGoods record, @Param( "example" ) TradeGoodsExample example) ; int updateByExample( @Param( "record" ) TradeGoods record, @Param( "example" ) TradeGoodsExample example) ; int updateByPrimaryKeySelective( TradeGoods record) ; int updateByPrimaryKey( TradeGoods record) ;
}
5.3、 创建 接口 类 TradeGoodsNumberLogMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeGoodsNumberLog;
import com.itheima.shop.pojo.TradeGoodsNumberLogExample;
import com.itheima.shop.pojo.TradeGoodsNumberLogKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeGoodsNumberLogMapper { int countByExample( TradeGoodsNumberLogExample example) ; int deleteByExample( TradeGoodsNumberLogExample example) ; int deleteByPrimaryKey( TradeGoodsNumberLogKey key) ; int insert( TradeGoodsNumberLog record) ; int insertSelective( TradeGoodsNumberLog record) ; List< TradeGoodsNumberLog> selectByExample( TradeGoodsNumberLogExample example) ; TradeGoodsNumberLog selectByPrimaryKey( TradeGoodsNumberLogKey key) ; int updateByExampleSelective( @Param( "record" ) TradeGoodsNumberLog record, @Param( "example" ) TradeGoodsNumberLogExample example) ; int updateByExample( @Param( "record" ) TradeGoodsNumberLog record, @Param( "example" ) TradeGoodsNumberLogExample example) ; int updateByPrimaryKeySelective( TradeGoodsNumberLog record) ; int updateByPrimaryKey( TradeGoodsNumberLog record) ;
}
5.4、 创建 接口 类 TradeMqConsumerLogMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeMqConsumerLog;
import com.itheima.shop.pojo.TradeMqConsumerLogExample;
import com.itheima.shop.pojo.TradeMqConsumerLogKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeMqConsumerLogMapper { int countByExample( TradeMqConsumerLogExample example) ; int deleteByExample( TradeMqConsumerLogExample example) ; int deleteByPrimaryKey( TradeMqConsumerLogKey key) ; int insert( TradeMqConsumerLog record) ; int insertSelective( TradeMqConsumerLog record) ; List< TradeMqConsumerLog> selectByExample( TradeMqConsumerLogExample example) ; TradeMqConsumerLog selectByPrimaryKey( TradeMqConsumerLogKey key) ; int updateByExampleSelective( @Param( "record" ) TradeMqConsumerLog record, @Param( "example" ) TradeMqConsumerLogExample example) ; int updateByExample( @Param( "record" ) TradeMqConsumerLog record, @Param( "example" ) TradeMqConsumerLogExample example) ; int updateByPrimaryKeySelective( TradeMqConsumerLog record) ; int updateByPrimaryKey( TradeMqConsumerLog record) ;
}
5.5、 创建 类 CancelMQListener.java
package com.itheima.shop.mq; import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.mapper.TradeGoodsMapper;
import com.itheima.shop.mapper.TradeGoodsNumberLogMapper;
import com.itheima.shop.mapper.TradeMqConsumerLogMapper;
import com.itheima.shop.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import java.util.Date; @Slf4j
@Component
@RocketMQMessageListener( topic = "${mq.order.topic} " ,consumerGroup = "${mq.order.consumer.group.name} " ,messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener< MessageExt> { @Value( "${mq.order.consumer.group.name} " ) private String groupName; @Autowiredprivate TradeGoodsMapper goodsMapper; @Autowiredprivate TradeMqConsumerLogMapper mqConsumerLogMapper; @Autowiredprivate TradeGoodsNumberLogMapper goodsNumberLogMapper; @Overridepublic void onMessage( MessageExt messageExt) { String msgId = null; String tags = null; String keys = null; String body = null; try { //1. 解析消息内容msgId = messageExt.getMsgId( ) ; tags = messageExt.getTags( ) ; keys = messageExt.getKeys( ) ; body = new String( messageExt.getBody( ) ,"UTF-8" ) ; log.info( "接受消息成功" ) ; //2. 查询消息消费记录TradeMqConsumerLogKey primaryKey = new TradeMqConsumerLogKey( ) ; primaryKey.setMsgTag( tags) ; primaryKey.setMsgKey( keys) ; primaryKey.setGroupName( groupName) ; TradeMqConsumerLog mqConsumerLog = mqConsumerLogMapper.selectByPrimaryKey( primaryKey) ; if( mqConsumerLog!= null) { //3. 判断如果消费过.. .//3.1 获得消息处理状态Integer status = mqConsumerLog.getConsumerStatus( ) ; //处理过.. .返回if( ShopCode.SHOP_MQ_MESSAGE_STATUS_SUCCESS.getCode( ) .intValue( ) == status.intValue( )) { log.info( "消息:" +msgId+",已经处理过" ) ; return ; } //正在处理.. .返回if( ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode( ) .intValue( ) == status.intValue( )) { log.info( "消息:" +msgId+",正在处理" ) ; return ; } //处理失败if( ShopCode.SHOP_MQ_MESSAGE_STATUS_FAIL.getCode( ) .intValue( ) == status.intValue( )) { //获得消息处理次数Integer times = mqConsumerLog.getConsumerTimes( ) ; if( times> 3 ) { log.info( "消息:" +msgId+",消息处理超过3次,不能再进行处理了" ) ; return ; } mqConsumerLog.setConsumerStatus( ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode( )) ; //使用数据库乐观锁更新TradeMqConsumerLogExample example = new TradeMqConsumerLogExample( ) ; TradeMqConsumerLogExample.Criteria criteria = example.createCriteria( ) ; criteria.andMsgTagEqualTo( mqConsumerLog.getMsgTag( )) ; criteria.andMsgKeyEqualTo( mqConsumerLog.getMsgKey( )) ; criteria.andGroupNameEqualTo( groupName) ; criteria.andConsumerTimesEqualTo( mqConsumerLog.getConsumerTimes( )) ; int r = mqConsumerLogMapper.updateByExampleSelective( mqConsumerLog, example) ; if( r<= 0 ) { //未修改成功,其他线程并发修改log.info( "并发修改,稍后处理" ) ; } } } else{ //4. 判断如果没有消费过.. .mqConsumerLog = new TradeMqConsumerLog( ) ; mqConsumerLog.setMsgTag( tags) ; mqConsumerLog.setMsgKey( keys) ; mqConsumerLog.setGroupName( groupName) ; mqConsumerLog.setConsumerStatus( ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode( )) ; mqConsumerLog.setMsgBody( body) ; mqConsumerLog.setMsgId( msgId) ; mqConsumerLog.setConsumerTimes( 0 ) ; //将消息处理信息添加到数据库mqConsumerLogMapper.insert( mqConsumerLog) ; } //5. 回退库存MQEntity mqEntity = JSON.parseObject( body, MQEntity.class) ; Long goodsId = mqEntity.getGoodsId( ) ; TradeGoods goods = goodsMapper.selectByPrimaryKey( goodsId) ; goods.setGoodsNumber( goods.getGoodsNumber( ) +mqEntity.getGoodsNum( )) ; goodsMapper.updateByPrimaryKey( goods) ; //6. 将消息的处理状态改为成功mqConsumerLog.setConsumerStatus( ShopCode.SHOP_MQ_MESSAGE_STATUS_SUCCESS.getCode( )) ; mqConsumerLog.setConsumerTimestamp( new Date( )) ; mqConsumerLogMapper.updateByPrimaryKey( mqConsumerLog) ; log.info( "回退库存成功" ) ; } catch ( Exception e) { e.printStackTrace( ) ; TradeMqConsumerLogKey primaryKey = new TradeMqConsumerLogKey( ) ; primaryKey.setMsgTag( tags) ; primaryKey.setMsgKey( keys) ; primaryKey.setGroupName( groupName) ; TradeMqConsumerLog mqConsumerLog = mqConsumerLogMapper.selectByPrimaryKey( primaryKey) ; if( mqConsumerLog== null) { //数据库未有记录mqConsumerLog = new TradeMqConsumerLog( ) ; mqConsumerLog.setMsgTag( tags) ; mqConsumerLog.setMsgKey( keys) ; mqConsumerLog.setGroupName( groupName) ; mqConsumerLog.setConsumerStatus( ShopCode.SHOP_MQ_MESSAGE_STATUS_FAIL.getCode( )) ; mqConsumerLog.setMsgBody( body) ; mqConsumerLog.setMsgId( msgId) ; mqConsumerLog.setConsumerTimes( 1 ) ; mqConsumerLogMapper.insert( mqConsumerLog) ; } else{ mqConsumerLog.setConsumerTimes( mqConsumerLog.getConsumerTimes( ) +1) ; mqConsumerLogMapper.updateByPrimaryKeySelective( mqConsumerLog) ; } } }
}
5.6、 创建 类 GoodsServiceImpl.java
package com.itheima.shop.service.impl; import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.api.IGoodsService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.Result;
import com.itheima.exception.CastException;
import com.itheima.shop.mapper.TradeGoodsMapper;
import com.itheima.shop.mapper.TradeGoodsNumberLogMapper;
import com.itheima.shop.pojo.TradeGoods;
import com.itheima.shop.pojo.TradeGoodsNumberLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.Date; @Component
@Service( interfaceClass = IGoodsService.class)
public class GoodsServiceImpl implements IGoodsService { @Autowiredprivate TradeGoodsMapper goodsMapper; @Autowiredprivate TradeGoodsNumberLogMapper goodsNumberLogMapper; @Overridepublic TradeGoods findOne( Long goodsId) { if ( goodsId == null) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } return goodsMapper.selectByPrimaryKey( goodsId) ; } @Overridepublic Result reduceGoodsNum( TradeGoodsNumberLog goodsNumberLog) { if ( goodsNumberLog == null || goodsNumberLog.getGoodsNumber( ) == null || goodsNumberLog.getOrderId( ) == null || goodsNumberLog.getGoodsNumber( ) == null || goodsNumberLog.getGoodsNumber( ) .intValue( ) <= 0 ) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } TradeGoods goods = goodsMapper.selectByPrimaryKey( goodsNumberLog.getGoodsId( )) ; if( goods.getGoodsNumber( ) < goodsNumberLog.getGoodsNumber( )) { //库存不足CastException.cast( ShopCode.SHOP_GOODS_NUM_NOT_ENOUGH) ; } //减库存goods.setGoodsNumber( goods.getGoodsNumber( ) -goodsNumberLog.getGoodsNumber( )) ; goodsMapper.updateByPrimaryKey( goods) ; //记录库存操作日志goodsNumberLog.setGoodsNumber( -( goodsNumberLog.getGoodsNumber( )) ) ; goodsNumberLog.setLogTime( new Date( )) ; goodsNumberLogMapper.insert( goodsNumberLog) ; return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; } }
5.7、 创建 类 GoodsServiceApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
@EnableDubboConfiguration
public class GoodsServiceApplication { public static void main( String[ ] args) { SpringApplication.run( GoodsServiceApplication.class,args) ; } }
5.8、 创建 文件 TradeGoodsMapper.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.itheima.shop.mapper.TradeGoodsMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeGoods" > < id column = "goods_id" property = "goodsId" jdbcType = "BIGINT" /> < result column = "goods_name" property = "goodsName" jdbcType = "VARCHAR" /> < result column = "goods_number" property = "goodsNumber" jdbcType = "INTEGER" /> < result column = "goods_price" property = "goodsPrice" jdbcType = "DECIMAL" /> < result column = "goods_desc" property = "goodsDesc" jdbcType = "VARCHAR" /> < result column = "add_time" property = "addTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > goods_id, goods_name, goods_number, goods_price, goods_desc, add_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeGoodsExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_goods< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.Long" > select < include refid = "Base_Column_List" /> from trade_goodswhere goods_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.Long" > delete from trade_goodswhere goods_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeGoodsExample" > delete from trade_goods< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeGoods" > insert into trade_goods ( goods_id, goods_name, goods_number, goods_price, goods_desc, add_time) values ( ) < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeGoods" > insert into trade_goods< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "goodsId != null" > goods_id,< /if> < if test = "goodsName != null" > goods_name,< /if> < if test = "goodsNumber != null" > goods_number,< /if> < if test = "goodsPrice != null" > goods_price,< /if> < if test = "goodsDesc != null" > goods_desc,< /if> < if test = "addTime != null" > add_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "goodsId != null" > < /if> < if test = "goodsName != null" > < /if> < if test = "goodsNumber != null" > < /if> < if test = "goodsPrice != null" > < /if> < if test = "goodsDesc != null" > < /if> < if test = "addTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeGoodsExample" resultType = "java.lang.Integer" > select count( *) from trade_goods< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_goods< set > < if test = "record.goodsId != null" > goods_id = < /if> < if test = "record.goodsName != null" > goods_name = < /if> < if test = "record.goodsNumber != null" > goods_number = < /if> < if test = "record.goodsPrice != null" > goods_price = < /if> < if test = "record.goodsDesc != null" > goods_desc = < /if> < if test = "record.addTime != null" > add_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_goodsset goods_id = goods_name = goods_number = goods_price = goods_desc = add_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeGoods" > update trade_goods< set > < if test = "goodsName != null" > goods_name = < /if> < if test = "goodsNumber != null" > goods_number = < /if> < if test = "goodsPrice != null" > goods_price = < /if> < if test = "goodsDesc != null" > goods_desc = < /if> < if test = "addTime != null" > add_time = < /if> < /set> where goods_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeGoods" > update trade_goodsset goods_name = goods_number = goods_price = goods_desc = add_time = where goods_id = < /update>
< /mapper>
5.9、 创建 文件 TradeGoodsNumberLogMapper.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.itheima.shop.mapper.TradeGoodsNumberLogMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeGoodsNumberLog" > < id column = "goods_id" property = "goodsId" jdbcType = "BIGINT" /> < id column = "order_id" property = "orderId" jdbcType = "BIGINT" /> < result column = "goods_number" property = "goodsNumber" jdbcType = "INTEGER" /> < result column = "log_time" property = "logTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > goods_id, order_id, goods_number, log_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLogExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_goods_number_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLogKey" > select < include refid = "Base_Column_List" /> from trade_goods_number_logwhere goods_id = and order_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLogKey" > delete from trade_goods_number_logwhere goods_id = and order_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLogExample" > delete from trade_goods_number_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLog" > insert into trade_goods_number_log ( goods_id, order_id, goods_number, log_time) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLog" > insert into trade_goods_number_log< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "goodsId != null" > goods_id,< /if> < if test = "orderId != null" > order_id,< /if> < if test = "goodsNumber != null" > goods_number,< /if> < if test = "logTime != null" > log_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "goodsId != null" > < /if> < if test = "orderId != null" > < /if> < if test = "goodsNumber != null" > < /if> < if test = "logTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLogExample" resultType = "java.lang.Integer" > select count( *) from trade_goods_number_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_goods_number_log< set > < if test = "record.goodsId != null" > goods_id = < /if> < if test = "record.orderId != null" > order_id = < /if> < if test = "record.goodsNumber != null" > goods_number = < /if> < if test = "record.logTime != null" > log_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_goods_number_logset goods_id = order_id = goods_number = log_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLog" > update trade_goods_number_log< set > < if test = "goodsNumber != null" > goods_number = < /if> < if test = "logTime != null" > log_time = < /if> < /set> where goods_id = and order_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeGoodsNumberLog" > update trade_goods_number_logset goods_number = log_time = where goods_id = and order_id = < /update>
< /mapper>
5.10、 创建 文件 TradeMqConsumerLogMapper.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.itheima.shop.mapper.TradeMqConsumerLogMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeMqConsumerLog" > < id column = "group_name" property = "groupName" jdbcType = "VARCHAR" /> < id column = "msg_tag" property = "msgTag" jdbcType = "VARCHAR" /> < id column = "msg_key" property = "msgKey" jdbcType = "VARCHAR" /> < result column = "msg_id" property = "msgId" jdbcType = "VARCHAR" /> < result column = "msg_body" property = "msgBody" jdbcType = "VARCHAR" /> < result column = "consumer_status" property = "consumerStatus" jdbcType = "INTEGER" /> < result column = "consumer_times" property = "consumerTimes" jdbcType = "INTEGER" /> < result column = "consumer_timestamp" property = "consumerTimestamp" jdbcType = "TIMESTAMP" /> < result column = "remark" property = "remark" jdbcType = "VARCHAR" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > group_name, msg_tag, msg_key, msg_id, msg_body, consumer_status, consumer_times, consumer_timestamp, remark< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLogExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_mq_consumer_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLogKey" > select < include refid = "Base_Column_List" /> from trade_mq_consumer_logwhere group_name = and msg_tag = and msg_key = < /select> < delete id = "deleteByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLogKey" > delete from trade_mq_consumer_logwhere group_name = and msg_tag = and msg_key = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLogExample" > delete from trade_mq_consumer_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLog" > insert into trade_mq_consumer_log ( group_name, msg_tag, msg_key, msg_id, msg_body, consumer_status, consumer_times, consumer_timestamp, remark) values ( ) < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLog" > insert into trade_mq_consumer_log< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "groupName != null" > group_name,< /if> < if test = "msgTag != null" > msg_tag,< /if> < if test = "msgKey != null" > msg_key,< /if> < if test = "msgId != null" > msg_id,< /if> < if test = "msgBody != null" > msg_body,< /if> < if test = "consumerStatus != null" > consumer_status,< /if> < if test = "consumerTimes != null" > consumer_times,< /if> < if test = "consumerTimestamp != null" > consumer_timestamp,< /if> < if test = "remark != null" > remark,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "groupName != null" > < /if> < if test = "msgTag != null" > < /if> < if test = "msgKey != null" > < /if> < if test = "msgId != null" > < /if> < if test = "msgBody != null" > < /if> < if test = "consumerStatus != null" > < /if> < if test = "consumerTimes != null" > < /if> < if test = "consumerTimestamp != null" > < /if> < if test = "remark != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLogExample" resultType = "java.lang.Integer" > select count( *) from trade_mq_consumer_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_mq_consumer_log< set > < if test = "record.groupName != null" > group_name = < /if> < if test = "record.msgTag != null" > msg_tag = < /if> < if test = "record.msgKey != null" > msg_key = < /if> < if test = "record.msgId != null" > msg_id = < /if> < if test = "record.msgBody != null" > msg_body = < /if> < if test = "record.consumerStatus != null" > consumer_status = < /if> < if test = "record.consumerTimes != null" > consumer_times = < /if> < if test = "record.consumerTimestamp != null" > consumer_timestamp = < /if> < if test = "record.remark != null" > remark = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_mq_consumer_logset group_name = msg_tag = msg_key = msg_id = msg_body = consumer_status = consumer_times = consumer_timestamp = remark = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLog" > update trade_mq_consumer_log< set > < if test = "msgId != null" > msg_id = < /if> < if test = "msgBody != null" > msg_body = < /if> < if test = "consumerStatus != null" > consumer_status = < /if> < if test = "consumerTimes != null" > consumer_times = < /if> < if test = "consumerTimestamp != null" > consumer_timestamp = < /if> < if test = "remark != null" > remark = < /if> < /set> where group_name = and msg_tag = and msg_key = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeMqConsumerLog" > update trade_mq_consumer_logset msg_id = msg_body = consumer_status = consumer_times = consumer_timestamp = remark = where group_name = and msg_tag = and msg_key = < /update>
< /mapper>
5.11、 创建 文件 application.properties
spring.application.name = dubbo-goods-provider
spring.dubbo.application.id = dubbo-goods-provider
spring.dubbo.application.name = dubbo-goods-provider
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183
spring.dubbo.server = true
spring.dubbo.protocol.name = dubbo
spring.dubbo.protocol.port = 20882
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/trade?useUnicode= true& characterEncoding = utf8
spring.datasource.username = root
spring.datasource.password = root
mybatis.type-aliases-package= com.itheima.shop.pojo
mybatis.mapper-locations= classpath:com/itheima/shop/mapper/*Mapper.xml
rocketmq.name-server= 192.168 .25.135:9876; 192.168 .25.138:9876
rocketmq.producer.group = orderProducerGroupmq.order.consumer.group.name = order_orderTopic_cancel_group
mq.order.topic = orderTopic
6、创建 shop-order-service 订单服务 工程。
6.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-order-service< /artifactId> < dependencies> < ! --mybatis-springboot--> < dependency> < groupId> org.mybatis.spring.boot< /groupId> < artifactId> mybatis-spring-boot-starter< /artifactId> < version> 1.3 .1 < /version> < /dependency> < ! -- MySQL连接驱动 --> < dependency> < groupId> mysql< /groupId> < artifactId> mysql-connector-java< /artifactId> < /dependency> < ! --common--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < ! --接口--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-order-service\ pom.xml -->
6.2、创建 接口 类 TradeOrderMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeOrder;
import com.itheima.shop.pojo.TradeOrderExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeOrderMapper { int countByExample( TradeOrderExample example) ; int deleteByExample( TradeOrderExample example) ; int deleteByPrimaryKey( Long orderId) ; int insert( TradeOrder record) ; int insertSelective( TradeOrder record) ; List< TradeOrder> selectByExample( TradeOrderExample example) ; TradeOrder selectByPrimaryKey( Long orderId) ; int updateByExampleSelective( @Param( "record" ) TradeOrder record, @Param( "example" ) TradeOrderExample example) ; int updateByExample( @Param( "record" ) TradeOrder record, @Param( "example" ) TradeOrderExample example) ; int updateByPrimaryKeySelective( TradeOrder record) ; int updateByPrimaryKey( TradeOrder record) ;
}
6.3、创建 类 CancelMQListener.java
package com.itheima.shop.mq; import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.mapper.TradeOrderMapper;
import com.itheima.shop.pojo.TradeOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException; @Slf4j
@Component
@RocketMQMessageListener( topic = "${mq.order.topic} " ,consumerGroup = "${mq.order.consumer.group.name} " ,messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener< MessageExt> { @Autowiredprivate TradeOrderMapper orderMapper; @Overridepublic void onMessage( MessageExt messageExt) { try { //1. 解析消息内容String body = new String( messageExt.getBody( ) ,"UTF-8" ) ; MQEntity mqEntity = JSON.parseObject( body, MQEntity.class) ; log.info( "接受消息成功" ) ; //2. 查询订单TradeOrder order = orderMapper.selectByPrimaryKey( mqEntity.getOrderId( )) ; //3.更新订单状态为取消order.setOrderStatus( ShopCode.SHOP_ORDER_CANCEL.getCode( )) ; orderMapper.updateByPrimaryKey( order) ; log.info( "订单状态设置为取消" ) ; } catch ( UnsupportedEncodingException e) { e.printStackTrace( ) ; log.info( "订单取消失败" ) ; } }
}
6.4、创建 类 PaymentListener.java
package com.itheima.shop.mq; import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.shop.mapper.TradeOrderMapper;
import com.itheima.shop.pojo.TradeOrder;
import com.itheima.shop.pojo.TradePay;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException; @Slf4j
@Component
@RocketMQMessageListener( topic = "${mq.pay.topic} " ,consumerGroup = "${mq.pay.consumer.group.name} " ,messageModel = MessageModel.BROADCASTING)
public class PaymentListener implements RocketMQListener< MessageExt> { @Autowiredprivate TradeOrderMapper orderMapper; @Overridepublic void onMessage( MessageExt messageExt) { log.info( "接收到支付成功消息" ) ; try { //1.解析消息内容String body = new String( messageExt.getBody( ) ,"UTF-8" ) ; TradePay tradePay = JSON.parseObject( body,TradePay.class) ; //2.根据订单ID查询订单对象TradeOrder tradeOrder = orderMapper.selectByPrimaryKey( tradePay.getOrderId( )) ; //3.更改订单支付状态为已支付tradeOrder.setPayStatus( ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode( )) ; //4.更新订单数据到数据库orderMapper.updateByPrimaryKey( tradeOrder) ; log.info( "更改订单支付状态为已支付" ) ; } catch ( UnsupportedEncodingException e) { e.printStackTrace( ) ; } }
}
6.5、创建 类 OrderServiceImpl.java
package com.itheima.shop.service; import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.itheima.api.ICouponService;
import com.itheima.api.IGoodsService;
import com.itheima.api.IOrderService;
import com.itheima.api.IUserService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.entity.Result;
import com.itheima.exception.CastException;
import com.itheima.shop.mapper.TradeOrderMapper;
import com.itheima.shop.pojo.*;
import com.itheima.utils.IDWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import java.math.BigDecimal;
import java.util.Date; @Slf4j
@Component
@Service( interfaceClass = IOrderService.class)
public class OrderServiceImpl implements IOrderService { @Referenceprivate IGoodsService goodsService; @Referenceprivate IUserService userService; @Referenceprivate ICouponService couponService; @Value( "${mq.order.topic} " ) private String topic; @Value( "${mq.order.tag.cancel} " ) private String tag; @Autowiredprivate TradeOrderMapper orderMapper; @Autowiredprivate IDWorker idWorker; @Autowiredprivate RocketMQTemplate rocketMQTemplate; @Overridepublic Result confirmOrder( TradeOrder order) { //1.校验订单checkOrder( order) ; //2.生成预订单Long orderId = savePreOrder( order) ; try { //3.扣减库存reduceGoodsNum( order) ; //4.扣减优惠券updateCouponStatus( order) ; //5.使用余额reduceMoneyPaid( order) ; //模拟异常抛出//CastException.cast( ShopCode.SHOP_FAIL) ; //6.确认订单updateOrderStatus( order) ; //7.返回成功状态return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; } catch ( Exception e) { //1.确认订单失败,发送消息MQEntity mqEntity = new MQEntity( ) ; mqEntity.setOrderId( orderId) ; mqEntity.setUserId( order.getUserId( )) ; mqEntity.setUserMoney( order.getMoneyPaid( )) ; mqEntity.setGoodsId( order.getGoodsId( )) ; mqEntity.setGoodsNum( order.getGoodsNumber( )) ; mqEntity.setCouponId( order.getCouponId( )) ; //2.返回订单确认失败消息try { sendCancelOrder( topic,tag,order.getOrderId( ) .toString( ) , JSON.toJSONString( mqEntity)) ; } catch ( Exception e1) { e1.printStackTrace( ) ; } return new Result( ShopCode.SHOP_FAIL.getSuccess( ) ,ShopCode.SHOP_FAIL.getMessage( )) ; } } /*** 发送订单确认失败消息* @param topic* @param tag* @param keys* @param body*/private void sendCancelOrder( String topic, String tag, String keys, String body) throws InterruptedException, RemotingException, MQClientException, MQBrokerException { Message message = new Message( topic,tag,keys,body.getBytes( )) ; rocketMQTemplate.getProducer( ) .send( message) ; } /*** 确认订单* @param order*/private void updateOrderStatus( TradeOrder order) { order.setOrderStatus( ShopCode.SHOP_ORDER_CONFIRM.getCode( )) ; order.setPayStatus( ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY.getCode( )) ; order.setConfirmTime( new Date( )) ; int r = orderMapper.updateByPrimaryKey( order) ; if( r<= 0 ) { CastException.cast( ShopCode.SHOP_ORDER_CONFIRM_FAIL) ; } log.info( "订单:" +order.getOrderId( ) +"确认订单成功" ) ; } /*** 扣减余额* @param order*/private void reduceMoneyPaid( TradeOrder order) { if( order.getMoneyPaid( ) != null && order.getMoneyPaid( ) .compareTo( BigDecimal.ZERO) == 1 ) { TradeUserMoneyLog userMoneyLog = new TradeUserMoneyLog( ) ; userMoneyLog.setOrderId( order.getOrderId( )) ; userMoneyLog.setUserId( order.getUserId( )) ; userMoneyLog.setUseMoney( order.getMoneyPaid( )) ; userMoneyLog.setMoneyLogType( ShopCode.SHOP_USER_MONEY_PAID.getCode( )) ; Result result = userService.updateMoneyPaid( userMoneyLog) ; if( result.getSuccess( ) .equals( ShopCode.SHOP_FAIL.getSuccess( )) ) { CastException.cast( ShopCode.SHOP_USER_MONEY_REDUCE_FAIL) ; } log.info( "订单:" +order.getOrderId( ) +",扣减余额成功" ) ; } } /*** 使用优惠券* @param order*/private void updateCouponStatus( TradeOrder order) { if( order.getCouponId( ) != null) { TradeCoupon coupon = couponService.findOne( order.getCouponId( )) ; coupon.setOrderId( order.getOrderId( )) ; coupon.setIsUsed( ShopCode.SHOP_COUPON_ISUSED.getCode( )) ; coupon.setUsedTime( new Date( )) ; //更新优惠券状态Result result = couponService.updateCouponStatus( coupon) ; if( result.getSuccess( ) .equals( ShopCode.SHOP_FAIL.getSuccess( )) ) { CastException.cast( ShopCode.SHOP_COUPON_USE_FAIL) ; } log.info( "订单:" +order.getOrderId( ) +",使用优惠券" ) ; } } /*** 扣减库存* @param order*/private void reduceGoodsNum( TradeOrder order) { TradeGoodsNumberLog goodsNumberLog = new TradeGoodsNumberLog( ) ; goodsNumberLog.setOrderId( order.getOrderId( )) ; goodsNumberLog.setGoodsId( order.getGoodsId( )) ; goodsNumberLog.setGoodsNumber( order.getGoodsNumber( )) ; Result result = goodsService.reduceGoodsNum( goodsNumberLog) ; if( result.getSuccess( ) .equals( ShopCode.SHOP_FAIL.getSuccess( )) ) { CastException.cast( ShopCode.SHOP_REDUCE_GOODS_NUM_FAIL) ; } log.info( "订单:" +order.getOrderId( ) +"扣减库存成功" ) ; } /*** 生成预订单** @param order* @return*/private Long savePreOrder( TradeOrder order) { //1. 设置订单状态为不可见order.setOrderStatus( ShopCode.SHOP_ORDER_NO_CONFIRM.getCode( )) ; //2. 设置订单IDlong orderId = idWorker.nextId( ) ; order.setOrderId( orderId) ; //3. 核算订单运费BigDecimal shippingFee = calculateShippingFee( order.getOrderAmount( )) ; if( order.getShippingFee( ) .compareTo( shippingFee) != 0 ) { CastException.cast( ShopCode.SHOP_ORDER_SHIPPINGFEE_INVALID) ; } //4. 核算订单总金额是否合法BigDecimal orderAmount = order.getGoodsPrice( ) .multiply( new BigDecimal( order.getGoodsNumber( )) ) ; orderAmount.add( shippingFee) ; if( order.getOrderAmount( ) .compareTo( orderAmount) != 0 ) { CastException.cast( ShopCode.SHOP_ORDERAMOUNT_INVALID) ; } //5.判断用户是否使用余额BigDecimal moneyPaid = order.getMoneyPaid( ) ; if( moneyPaid!= null) { //5.1 订单中余额是否合法int r = moneyPaid.compareTo( BigDecimal.ZERO) ; //余额小于0if( r== -1) { CastException.cast( ShopCode.SHOP_MONEY_PAID_LESS_ZERO) ; } //余额大于0if( r== 1 ) { TradeUser user = userService.findOne( order.getUserId( )) ; if( moneyPaid.compareTo( new BigDecimal( user.getUserMoney( )) ) == 1 ) { CastException.cast( ShopCode.SHOP_MONEY_PAID_INVALID) ; } } } else{ order.setMoneyPaid( BigDecimal.ZERO) ; } //6.判断用户是否使用优惠券Long couponId = order.getCouponId( ) ; if( couponId!= null) { TradeCoupon coupon = couponService.findOne( couponId) ; //6.1 判断优惠券是否存在if( coupon== null) { CastException.cast( ShopCode.SHOP_COUPON_NO_EXIST) ; } //6.2 判断优惠券是否已经被使用if( coupon.getIsUsed( ) .intValue( ) == ShopCode.SHOP_COUPON_ISUSED.getCode( ) .intValue( )) { CastException.cast( ShopCode.SHOP_COUPON_ISUSED) ; } order.setCouponPaid( coupon.getCouponPrice( )) ; } else{ order.setCouponPaid( BigDecimal.ZERO) ; } //7.核算订单支付金额 订单总金额-余额-优惠券金额BigDecimal payAmount = order.getOrderAmount( ) .subtract( order.getMoneyPaid( )) .subtract( order.getCouponPaid( )) ; order.setPayAmount( payAmount) ; //8.设置下单时间order.setAddTime( new Date( )) ; //9.保存订单到数据库orderMapper.insert( order) ; //10.返回订单IDreturn orderId; } /*** 核算运费* @param orderAmount* @return*/private BigDecimal calculateShippingFee( BigDecimal orderAmount) { if( orderAmount.compareTo( new BigDecimal( 100 )) == 1 ) { return BigDecimal.ZERO; } else{ return new BigDecimal( 10 ) ; } } /*** 校验订单** @param order*/private void checkOrder( TradeOrder order) { //1.校验订单是否存在if ( order == null) { CastException.cast( ShopCode.SHOP_ORDER_INVALID) ; } //2.校验订单中的商品是否存在TradeGoods goods = goodsService.findOne( order.getGoodsId( )) ; if ( goods == null) { CastException.cast( ShopCode.SHOP_GOODS_NO_EXIST) ; } //3.校验下单用户是否存在TradeUser user = userService.findOne( order.getUserId( )) ; if ( user == null) { CastException.cast( ShopCode.SHOP_USER_NO_EXIST) ; } //4.校验商品单价是否合法if ( order.getGoodsPrice( ) .compareTo( goods.getGoodsPrice( )) != 0 ) { CastException.cast( ShopCode.SHOP_GOODS_PRICE_INVALID) ; } //5.校验订单商品数量是否合法if ( order.getGoodsNumber( ) >= goods.getGoodsNumber( )) { CastException.cast( ShopCode.SHOP_GOODS_NUM_NOT_ENOUGH) ; } log.info( "校验订单通过" ) ; } }
6.6、创建 类 OrderServiceApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import com.itheima.utils.IDWorker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean; @SpringBootApplication
@EnableDubboConfiguration
public class OrderServiceApplication { public static void main( String[ ] args) { SpringApplication.run( OrderServiceApplication.class,args) ; } @Beanpublic IDWorker getBean ( ) { return new IDWorker( 1,1 ) ; } }
6.7、创建 文件 TradeOrderMapper.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.itheima.shop.mapper.TradeOrderMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeOrder" > < id column = "order_id" property = "orderId" jdbcType = "BIGINT" /> < result column = "user_id" property = "userId" jdbcType = "BIGINT" /> < result column = "order_status" property = "orderStatus" jdbcType = "INTEGER" /> < result column = "pay_status" property = "payStatus" jdbcType = "INTEGER" /> < result column = "shipping_status" property = "shippingStatus" jdbcType = "INTEGER" /> < result column = "address" property = "address" jdbcType = "VARCHAR" /> < result column = "consignee" property = "consignee" jdbcType = "VARCHAR" /> < result column = "goods_id" property = "goodsId" jdbcType = "BIGINT" /> < result column = "goods_number" property = "goodsNumber" jdbcType = "INTEGER" /> < result column = "goods_price" property = "goodsPrice" jdbcType = "DECIMAL" /> < result column = "goods_amount" property = "goodsAmount" jdbcType = "DECIMAL" /> < result column = "shipping_fee" property = "shippingFee" jdbcType = "DECIMAL" /> < result column = "order_amount" property = "orderAmount" jdbcType = "DECIMAL" /> < result column = "coupon_id" property = "couponId" jdbcType = "BIGINT" /> < result column = "coupon_paid" property = "couponPaid" jdbcType = "DECIMAL" /> < result column = "money_paid" property = "moneyPaid" jdbcType = "DECIMAL" /> < result column = "pay_amount" property = "payAmount" jdbcType = "DECIMAL" /> < result column = "add_time" property = "addTime" jdbcType = "TIMESTAMP" /> < result column = "confirm_time" property = "confirmTime" jdbcType = "TIMESTAMP" /> < result column = "pay_time" property = "payTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > order_id, user_id, order_status, pay_status, shipping_status, address, consignee, goods_id, goods_number, goods_price, goods_amount, shipping_fee, order_amount, coupon_id, coupon_paid, money_paid, pay_amount, add_time, confirm_time, pay_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeOrderExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_order< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.Long" > select < include refid = "Base_Column_List" /> from trade_orderwhere order_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.Long" > delete from trade_orderwhere order_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeOrderExample" > delete from trade_order< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeOrder" > insert into trade_order ( order_id, user_id, order_status, pay_status, shipping_status, address, consignee, goods_id, goods_number, goods_price, goods_amount, shipping_fee, order_amount, coupon_id, coupon_paid, money_paid, pay_amount, add_time, confirm_time, pay_time) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeOrder" > insert into trade_order< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "orderId != null" > order_id,< /if> < if test = "userId != null" > user_id,< /if> < if test = "orderStatus != null" > order_status,< /if> < if test = "payStatus != null" > pay_status,< /if> < if test = "shippingStatus != null" > shipping_status,< /if> < if test = "address != null" > address,< /if> < if test = "consignee != null" > consignee,< /if> < if test = "goodsId != null" > goods_id,< /if> < if test = "goodsNumber != null" > goods_number,< /if> < if test = "goodsPrice != null" > goods_price,< /if> < if test = "goodsAmount != null" > goods_amount,< /if> < if test = "shippingFee != null" > shipping_fee,< /if> < if test = "orderAmount != null" > order_amount,< /if> < if test = "couponId != null" > coupon_id,< /if> < if test = "couponPaid != null" > coupon_paid,< /if> < if test = "moneyPaid != null" > money_paid,< /if> < if test = "payAmount != null" > pay_amount,< /if> < if test = "addTime != null" > add_time,< /if> < if test = "confirmTime != null" > confirm_time,< /if> < if test = "payTime != null" > pay_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "orderId != null" > < /if> < if test = "userId != null" > < /if> < if test = "orderStatus != null" > < /if> < if test = "payStatus != null" > < /if> < if test = "shippingStatus != null" > < /if> < if test = "address != null" > < /if> < if test = "consignee != null" > < /if> < if test = "goodsId != null" > < /if> < if test = "goodsNumber != null" > < /if> < if test = "goodsPrice != null" > < /if> < if test = "goodsAmount != null" > < /if> < if test = "shippingFee != null" > < /if> < if test = "orderAmount != null" > < /if> < if test = "couponId != null" > < /if> < if test = "couponPaid != null" > < /if> < if test = "moneyPaid != null" > < /if> < if test = "payAmount != null" > < /if> < if test = "addTime != null" > < /if> < if test = "confirmTime != null" > < /if> < if test = "payTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeOrderExample" resultType = "java.lang.Integer" > select count( *) from trade_order< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_order< set > < if test = "record.orderId != null" > order_id = < /if> < if test = "record.userId != null" > user_id = < /if> < if test = "record.orderStatus != null" > order_status = < /if> < if test = "record.payStatus != null" > pay_status = < /if> < if test = "record.shippingStatus != null" > shipping_status = < /if> < if test = "record.address != null" > address = < /if> < if test = "record.consignee != null" > consignee = < /if> < if test = "record.goodsId != null" > goods_id = < /if> < if test = "record.goodsNumber != null" > goods_number = < /if> < if test = "record.goodsPrice != null" > goods_price = < /if> < if test = "record.goodsAmount != null" > goods_amount = < /if> < if test = "record.shippingFee != null" > shipping_fee = < /if> < if test = "record.orderAmount != null" > order_amount = < /if> < if test = "record.couponId != null" > coupon_id = < /if> < if test = "record.couponPaid != null" > coupon_paid = < /if> < if test = "record.moneyPaid != null" > money_paid = < /if> < if test = "record.payAmount != null" > pay_amount = < /if> < if test = "record.addTime != null" > add_time = < /if> < if test = "record.confirmTime != null" > confirm_time = < /if> < if test = "record.payTime != null" > pay_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_orderset order_id = user_id = order_status = pay_status = shipping_status = address = consignee = goods_id = goods_number = goods_price = goods_amount = shipping_fee = order_amount = coupon_id = coupon_paid = money_paid = pay_amount = add_time = confirm_time = pay_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeOrder" > update trade_order< set > < if test = "userId != null" > user_id = < /if> < if test = "orderStatus != null" > order_status = < /if> < if test = "payStatus != null" > pay_status = < /if> < if test = "shippingStatus != null" > shipping_status = < /if> < if test = "address != null" > address = < /if> < if test = "consignee != null" > consignee = < /if> < if test = "goodsId != null" > goods_id = < /if> < if test = "goodsNumber != null" > goods_number = < /if> < if test = "goodsPrice != null" > goods_price = < /if> < if test = "goodsAmount != null" > goods_amount = < /if> < if test = "shippingFee != null" > shipping_fee = < /if> < if test = "orderAmount != null" > order_amount = < /if> < if test = "couponId != null" > coupon_id = < /if> < if test = "couponPaid != null" > coupon_paid = < /if> < if test = "moneyPaid != null" > money_paid = < /if> < if test = "payAmount != null" > pay_amount = < /if> < if test = "addTime != null" > add_time = < /if> < if test = "confirmTime != null" > confirm_time = < /if> < if test = "payTime != null" > pay_time = < /if> < /set> where order_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeOrder" > update trade_orderset user_id = order_status = pay_status = shipping_status = address = consignee = goods_id = goods_number = goods_price = goods_amount = shipping_fee = order_amount = coupon_id = coupon_paid = money_paid = pay_amount = add_time = confirm_time = pay_time = where order_id = < /update>
< /mapper>
6.8、创建 文件 application.properties
spring.application.name = dubbo-order-provider
spring.dubbo.application.id = dubbo-order-provider
spring.dubbo.application.name = dubbo-order-provider
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183
spring.dubbo.server = true
spring.dubbo.protocol.name = dubbo
spring.dubbo.protocol.port = 20884
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/trade?useUnicode= true& characterEncoding = utf8
spring.datasource.username = root
spring.datasource.password = root
mybatis.type-aliases-package= com.itheima.shop.pojo
mybatis.mapper-locations= classpath:com/itheima/shop/mapper/*Mapper.xml
rocketmq.name-server= 192.168 .25.135:9876; 192.168 .25.138:9876
rocketmq.producer.group = orderProducerGroupmq.order.consumer.group.name = order_orderTopic_cancel_group
mq.order.topic = orderTopic
mq.order.tag.cancel = order_cancelmq.pay.topic = payTopic
mq.pay.consumer.group.name = pay_payTopic_group
6.9 创建 测试类 OrderServiceTest.java
package com.itheima.test; import com.itheima.api.IOrderService;
import com.itheima.shop.OrderServiceApplication;
import com.itheima.shop.pojo.TradeOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException;
import java.math.BigDecimal; @RunWith( SpringRunner.class)
@SpringBootTest( classes = OrderServiceApplication.class)
public class OrderServiceTest { @Autowiredprivate IOrderService orderService; @Testpublic void confirmOrder( ) throws IOException { Long coupouId = 345988230098857984L; Long goodsId = 345959443973935104L; Long userId = 345963634385633280L; TradeOrder order = new TradeOrder( ) ; order.setGoodsId( goodsId) ; order.setUserId( userId) ; order.setCouponId( coupouId) ; order.setAddress( "北京" ) ; order.setGoodsNumber( 1 ) ; order.setGoodsPrice( new BigDecimal( 1000 )) ; order.setShippingFee( BigDecimal.ZERO) ; order.setOrderAmount( new BigDecimal( 1000 )) ; order.setMoneyPaid( new BigDecimal( 100 )) ; orderService.confirmOrder( order) ; System.in.read( ) ; } }
7、创建 shop-pay-service 支付服务 工程。
7.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-pay-service< /artifactId> < dependencies> < ! --mybatis-springboot--> < dependency> < groupId> org.mybatis.spring.boot< /groupId> < artifactId> mybatis-spring-boot-starter< /artifactId> < version> 1.3 .1 < /version> < /dependency> < ! -- MySQL连接驱动 --> < dependency> < groupId> mysql< /groupId> < artifactId> mysql-connector-java< /artifactId> < /dependency> < ! --common--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < ! --接口--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-pay-service\ pom.xml -->
7.2、创建 接口 类 TradeMqProducerTempMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeMqProducerTemp;
import com.itheima.shop.pojo.TradeMqProducerTempExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeMqProducerTempMapper { int countByExample( TradeMqProducerTempExample example) ; int deleteByExample( TradeMqProducerTempExample example) ; int deleteByPrimaryKey( String id ) ; int insert( TradeMqProducerTemp record) ; int insertSelective( TradeMqProducerTemp record) ; List< TradeMqProducerTemp> selectByExample( TradeMqProducerTempExample example) ; TradeMqProducerTemp selectByPrimaryKey( String id ) ; int updateByExampleSelective( @Param( "record" ) TradeMqProducerTemp record, @Param( "example" ) TradeMqProducerTempExample example) ; int updateByExample( @Param( "record" ) TradeMqProducerTemp record, @Param( "example" ) TradeMqProducerTempExample example) ; int updateByPrimaryKeySelective( TradeMqProducerTemp record) ; int updateByPrimaryKey( TradeMqProducerTemp record) ;
}
7.3、创建 接口 类 TradePayMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradePay;
import com.itheima.shop.pojo.TradePayExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List;
@Mapper
public interface TradePayMapper { int countByExample( TradePayExample example) ; int deleteByExample( TradePayExample example) ; int deleteByPrimaryKey( Long payId) ; int insert( TradePay record) ; int insertSelective( TradePay record) ; List< TradePay> selectByExample( TradePayExample example) ; TradePay selectByPrimaryKey( Long payId) ; int updateByExampleSelective( @Param( "record" ) TradePay record, @Param( "example" ) TradePayExample example) ; int updateByExample( @Param( "record" ) TradePay record, @Param( "example" ) TradePayExample example) ; int updateByPrimaryKeySelective( TradePay record) ; int updateByPrimaryKey( TradePay record) ;
}
7.4、创建 类 PayServiceImpl.java
package com.itheima.shop.service.impl; import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.itheima.api.IPayService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.Result;
import com.itheima.exception.CastException;
import com.itheima.shop.mapper.TradeMqProducerTempMapper;
import com.itheima.shop.mapper.TradePayMapper;
import com.itheima.shop.pojo.TradeMqProducerTemp;
import com.itheima.shop.pojo.TradePay;
import com.itheima.shop.pojo.TradePayExample;
import com.itheima.utils.IDWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import java.util.Date; @Slf4j
@Component
@Service( interfaceClass = IPayService.class)
public class PayServiceImpl implements IPayService{ @Autowiredprivate TradePayMapper tradePayMapper; @Autowiredprivate TradeMqProducerTempMapper mqProducerTempMapper; @Autowiredprivate ThreadPoolTaskExecutor threadPoolTaskExecutor; @Autowiredprivate RocketMQTemplate rocketMQTemplate; @Autowiredprivate IDWorker idWorker; @Value( "${rocketmq.producer.group} " ) private String groupName; @Value( "${mq.topic} " ) private String topic; @Value( "${mq.pay.tag} " ) private String tag; @Overridepublic Result createPayment( TradePay tradePay) { if( tradePay== null || tradePay.getOrderId( ) == null) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } //1.判断订单支付状态TradePayExample example = new TradePayExample( ) ; TradePayExample.Criteria criteria = example.createCriteria( ) ; criteria.andOrderIdEqualTo( tradePay.getOrderId( )) ; criteria.andIsPaidEqualTo( ShopCode.SHOP_PAYMENT_IS_PAID.getCode( )) ; int r = tradePayMapper.countByExample( example) ; if( r> 0 ) { CastException.cast( ShopCode.SHOP_PAYMENT_IS_PAID) ; } //2.设置订单的状态为未支付tradePay.setIsPaid( ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY.getCode( )) ; //3.保存支付订单tradePay.setPayId( idWorker.nextId( )) ; tradePayMapper.insert( tradePay) ; return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; } @Overridepublic Result callbackPayment( TradePay tradePay) throws InterruptedException, RemotingException, MQClientException, MQBrokerException { log.info( "支付回调" ) ; //1. 判断用户支付状态if( tradePay.getIsPaid( ) .intValue( ) == ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode( ) .intValue( )) { //2. 更新支付订单状态为已支付Long payId = tradePay.getPayId( ) ; TradePay pay = tradePayMapper.selectByPrimaryKey( payId) ; //判断支付订单是否存在if( pay== null) { CastException.cast( ShopCode.SHOP_PAYMENT_NOT_FOUND) ; } pay.setIsPaid( ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode( )) ; int r = tradePayMapper.updateByPrimaryKeySelective( pay) ; log.info( "支付订单状态改为已支付" ) ; if( r== 1 ) { //3. 创建支付成功的消息TradeMqProducerTemp tradeMqProducerTemp = new TradeMqProducerTemp( ) ; tradeMqProducerTemp.setId( String.valueOf( idWorker.nextId( )) ) ; tradeMqProducerTemp.setGroupName( groupName) ; tradeMqProducerTemp.setMsgTopic( topic) ; tradeMqProducerTemp.setMsgTag( tag) ; tradeMqProducerTemp.setMsgKey( String.valueOf( tradePay.getPayId( )) ) ; tradeMqProducerTemp.setMsgBody( JSON.toJSONString( tradePay)) ; tradeMqProducerTemp.setCreateTime( new Date( )) ; //4. 将消息持久化数据库mqProducerTempMapper.insert( tradeMqProducerTemp) ; log.info( "将支付成功消息持久化到数据库" ) ; //在线程池中进行处理threadPoolTaskExecutor.submit( new Runnable ( ) { @Overridepublic void run ( ) { //5. 发送消息到MQSendResult result = null; try { result = sendMessage( topic, tag, String.valueOf( tradePay.getPayId( )) , JSON.toJSONString( tradePay)) ; } catch ( Exception e) { e.printStackTrace( ) ; } if( result.getSendStatus( ) .equals( SendStatus.SEND_OK)) { log.info( "消息发送成功" ) ; //6. 等待发送结果,如果MQ接受到消息,删除发送成功的消息mqProducerTempMapper.deleteByPrimaryKey( tradeMqProducerTemp.getId( )) ; log.info( "持久化到数据库的消息删除" ) ; } } } ) ; } return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; } else{ CastException.cast( ShopCode.SHOP_PAYMENT_PAY_ERROR) ; return new Result( ShopCode.SHOP_FAIL.getSuccess( ) ,ShopCode.SHOP_FAIL.getMessage( )) ; } } /*** 发送支付成功消息* @param topic* @param tag* @param key* @param body*/private SendResult sendMessage( String topic, String tag, String key, String body) throws InterruptedException, RemotingException, MQClientException, MQBrokerException { if( StringUtils.isEmpty( topic)) { CastException.cast( ShopCode.SHOP_MQ_TOPIC_IS_EMPTY) ; } if( StringUtils.isEmpty( body)) { CastException.cast( ShopCode.SHOP_MQ_MESSAGE_BODY_IS_EMPTY) ; } Message message = new Message( topic,tag,key,body.getBytes( )) ; SendResult sendResult = rocketMQTemplate.getProducer( ) .send( message) ; return sendResult; }
}
7.5、创建 类 PayServiceApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import com.itheima.utils.IDWorker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; @SpringBootApplication
@EnableDubboConfiguration
public class PayServiceApplication { public static void main( String[ ] args) { SpringApplication.run( PayServiceApplication.class,args) ; } @Beanpublic IDWorker getBean ( ) { return new IDWorker( 1,2 ) ; } @Beanpublic ThreadPoolTaskExecutor getThreadPool ( ) { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor( ) ; executor.setCorePoolSize( 4 ) ; executor.setMaxPoolSize( 8 ) ; executor.setQueueCapacity( 100 ) ; executor.setKeepAliveSeconds( 60 ) ; executor.setThreadNamePrefix( "Pool-A" ) ; executor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy( )) ; executor.initialize( ) ; return executor; } }
7.6、创建 文件 TradeMqProducerTempMapper.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.itheima.shop.mapper.TradeMqProducerTempMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeMqProducerTemp" > < id column = "id" property = "id" jdbcType = "VARCHAR" /> < result column = "group_name" property = "groupName" jdbcType = "VARCHAR" /> < result column = "msg_topic" property = "msgTopic" jdbcType = "VARCHAR" /> < result column = "msg_tag" property = "msgTag" jdbcType = "VARCHAR" /> < result column = "msg_key" property = "msgKey" jdbcType = "VARCHAR" /> < result column = "msg_body" property = "msgBody" jdbcType = "VARCHAR" /> < result column = "msg_status" property = "msgStatus" jdbcType = "INTEGER" /> < result column = "create_time" property = "createTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > id, group_name, msg_topic, msg_tag, msg_key, msg_body, msg_status, create_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeMqProducerTempExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_mq_producer_temp< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.String" > select < include refid = "Base_Column_List" /> from trade_mq_producer_tempwhere id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.String" > delete from trade_mq_producer_tempwhere id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeMqProducerTempExample" > delete from trade_mq_producer_temp< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeMqProducerTemp" > insert into trade_mq_producer_temp ( id, group_name, msg_topic, msg_tag, msg_key, msg_body, msg_status, create_time) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeMqProducerTemp" > insert into trade_mq_producer_temp< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "id != null" > id,< /if> < if test = "groupName != null" > group_name,< /if> < if test = "msgTopic != null" > msg_topic,< /if> < if test = "msgTag != null" > msg_tag,< /if> < if test = "msgKey != null" > msg_key,< /if> < if test = "msgBody != null" > msg_body,< /if> < if test = "msgStatus != null" > msg_status,< /if> < if test = "createTime != null" > create_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "id != null" > < /if> < if test = "groupName != null" > < /if> < if test = "msgTopic != null" > < /if> < if test = "msgTag != null" > < /if> < if test = "msgKey != null" > < /if> < if test = "msgBody != null" > < /if> < if test = "msgStatus != null" > < /if> < if test = "createTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeMqProducerTempExample" resultType = "java.lang.Integer" > select count( *) from trade_mq_producer_temp< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_mq_producer_temp< set > < if test = "record.id != null" > id = < /if> < if test = "record.groupName != null" > group_name = < /if> < if test = "record.msgTopic != null" > msg_topic = < /if> < if test = "record.msgTag != null" > msg_tag = < /if> < if test = "record.msgKey != null" > msg_key = < /if> < if test = "record.msgBody != null" > msg_body = < /if> < if test = "record.msgStatus != null" > msg_status = < /if> < if test = "record.createTime != null" > create_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_mq_producer_tempset id = group_name = msg_topic = msg_tag = msg_key = msg_body = msg_status = create_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeMqProducerTemp" > update trade_mq_producer_temp< set > < if test = "groupName != null" > group_name = < /if> < if test = "msgTopic != null" > msg_topic = < /if> < if test = "msgTag != null" > msg_tag = < /if> < if test = "msgKey != null" > msg_key = < /if> < if test = "msgBody != null" > msg_body = < /if> < if test = "msgStatus != null" > msg_status = < /if> < if test = "createTime != null" > create_time = < /if> < /set> where id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeMqProducerTemp" > update trade_mq_producer_tempset group_name = msg_topic = msg_tag = msg_key = msg_body = msg_status = create_time = where id = < /update>
< /mapper>
7.7、创建 文件 TradePayMapper.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.itheima.shop.mapper.TradePayMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradePay" > < id column = "pay_id" property = "payId" jdbcType = "BIGINT" /> < result column = "order_id" property = "orderId" jdbcType = "BIGINT" /> < result column = "pay_amount" property = "payAmount" jdbcType = "DECIMAL" /> < result column = "is_paid" property = "isPaid" jdbcType = "INTEGER" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > pay_id, order_id, pay_amount, is_paid< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradePayExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_pay< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.Long" > select < include refid = "Base_Column_List" /> from trade_paywhere pay_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.Long" > delete from trade_paywhere pay_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradePayExample" > delete from trade_pay< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradePay" > insert into trade_pay ( pay_id, order_id, pay_amount, is_paid) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradePay" > insert into trade_pay< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "payId != null" > pay_id,< /if> < if test = "orderId != null" > order_id,< /if> < if test = "payAmount != null" > pay_amount,< /if> < if test = "isPaid != null" > is_paid,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "payId != null" > < /if> < if test = "orderId != null" > < /if> < if test = "payAmount != null" > < /if> < if test = "isPaid != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradePayExample" resultType = "java.lang.Integer" > select count( *) from trade_pay< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_pay< set > < if test = "record.payId != null" > pay_id = < /if> < if test = "record.orderId != null" > order_id = < /if> < if test = "record.payAmount != null" > pay_amount = < /if> < if test = "record.isPaid != null" > is_paid = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_payset pay_id = order_id = pay_amount = is_paid = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradePay" > update trade_pay< set > < if test = "orderId != null" > order_id = < /if> < if test = "payAmount != null" > pay_amount = < /if> < if test = "isPaid != null" > is_paid = < /if> < /set> where pay_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradePay" > update trade_payset order_id = pay_amount = is_paid = where pay_id = < /update>
< /mapper>
7.8、创建 文件 application.properties
spring.application.name = dubbo-pay-provider
spring.dubbo.application.id = dubbo-pay-provider
spring.dubbo.application.name = dubbo-pay-provider
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183
spring.dubbo.server = true
spring.dubbo.protocol.name = dubbo
spring.dubbo.protocol.port = 20885
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/trade?useUnicode= true& characterEncoding = utf8
spring.datasource.username = root
spring.datasource.password = root
mybatis.type-aliases-package= com.itheima.shop.pojo
mybatis.mapper-locations= classpath:com/itheima/shop/mapper/*Mapper.xml
rocketmq.name-server= 192.168 .25.135:9876; 192.168 .25.138:9876
rocketmq.producer.group = payProducerGroupmq.topic = payTopic
mq.pay.tag = paid
7.9 创建 测试类 PayServiceTest.java
package com.itheima.test; import com.itheima.api.IPayService;
import com.itheima.constant.ShopCode;
import com.itheima.shop.PayServiceApplication;
import com.itheima.shop.pojo.TradePay;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException;
import java.math.BigDecimal; @RunWith( SpringRunner.class)
@SpringBootTest( classes = PayServiceApplication.class)
public class PayServiceTest { @Autowiredprivate IPayService payService; @Testpublic void createPayment ( ) { long orderId = 351526299216515072L; TradePay tradePay = new TradePay( ) ; tradePay.setOrderId( orderId) ; tradePay.setPayAmount( new BigDecimal( 880 )) ; payService.createPayment( tradePay) ; } @Testpublic void callbackPayment( ) throws InterruptedException, RemotingException, MQClientException, MQBrokerException, IOException { long payId = 352516176372441088L; long orderId = 351526299216515072L; TradePay tradePay = new TradePay( ) ; tradePay.setPayId( payId) ; tradePay.setOrderId( orderId) ; tradePay.setIsPaid( ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode( )) ; payService.callbackPayment( tradePay) ; System.in.read( ) ; } }
8、创建 shop-user-service 用户服务 工程。
8.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-user-service< /artifactId> < dependencies> < ! --mybatis-springboot--> < dependency> < groupId> org.mybatis.spring.boot< /groupId> < artifactId> mybatis-spring-boot-starter< /artifactId> < version> 1.3 .1 < /version> < /dependency> < ! -- MySQL连接驱动 --> < dependency> < groupId> mysql< /groupId> < artifactId> mysql-connector-java< /artifactId> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-pojo< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-user-service\ pom.xml -->
8.2、创建 接口 类 TradeUserMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeUser;
import com.itheima.shop.pojo.TradeUserExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeUserMapper { int countByExample( TradeUserExample example) ; int deleteByExample( TradeUserExample example) ; int deleteByPrimaryKey( Long userId) ; int insert( TradeUser record) ; int insertSelective( TradeUser record) ; List< TradeUser> selectByExample( TradeUserExample example) ; TradeUser selectByPrimaryKey( Long userId) ; int updateByExampleSelective( @Param( "record" ) TradeUser record, @Param( "example" ) TradeUserExample example) ; int updateByExample( @Param( "record" ) TradeUser record, @Param( "example" ) TradeUserExample example) ; int updateByPrimaryKeySelective( TradeUser record) ; int updateByPrimaryKey( TradeUser record) ;
}
8.3、创建 接口 类 TradeUserMoneyLogMapper.java
package com.itheima.shop.mapper; import com.itheima.shop.pojo.TradeUserMoneyLog;
import com.itheima.shop.pojo.TradeUserMoneyLogExample;
import com.itheima.shop.pojo.TradeUserMoneyLogKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface TradeUserMoneyLogMapper { int countByExample( TradeUserMoneyLogExample example) ; int deleteByExample( TradeUserMoneyLogExample example) ; int deleteByPrimaryKey( TradeUserMoneyLogKey key) ; int insert( TradeUserMoneyLog record) ; int insertSelective( TradeUserMoneyLog record) ; List< TradeUserMoneyLog> selectByExample( TradeUserMoneyLogExample example) ; TradeUserMoneyLog selectByPrimaryKey( TradeUserMoneyLogKey key) ; int updateByExampleSelective( @Param( "record" ) TradeUserMoneyLog record, @Param( "example" ) TradeUserMoneyLogExample example) ; int updateByExample( @Param( "record" ) TradeUserMoneyLog record, @Param( "example" ) TradeUserMoneyLogExample example) ; int updateByPrimaryKeySelective( TradeUserMoneyLog record) ; int updateByPrimaryKey( TradeUserMoneyLog record) ;
}
8.4、创建 类 CancelMQListener.java
package com.itheima.shop.mq; import com.alibaba.fastjson.JSON;
import com.itheima.api.IUserService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.pojo.TradeUserMoneyLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; @Slf4j
@Component
@RocketMQMessageListener( topic = "${mq.order.topic} " ,consumerGroup = "${mq.order.consumer.group.name} " ,messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener< MessageExt> { @Autowiredprivate IUserService userService; @Overridepublic void onMessage( MessageExt messageExt) { try { //1.解析消息String body = new String( messageExt.getBody( ) , "UTF-8" ) ; MQEntity mqEntity = JSON.parseObject( body, MQEntity.class) ; log.info( "接收到消息" ) ; if( mqEntity.getUserMoney( ) != null && mqEntity.getUserMoney( ) .compareTo( BigDecimal.ZERO) > 0 ) { //2.调用业务层,进行余额修改TradeUserMoneyLog userMoneyLog = new TradeUserMoneyLog( ) ; userMoneyLog.setUseMoney( mqEntity.getUserMoney( )) ; userMoneyLog.setMoneyLogType( ShopCode.SHOP_USER_MONEY_REFUND.getCode( )) ; userMoneyLog.setUserId( mqEntity.getUserId( )) ; userMoneyLog.setOrderId( mqEntity.getOrderId( )) ; userService.updateMoneyPaid( userMoneyLog) ; log.info( "余额回退成功" ) ; } } catch ( UnsupportedEncodingException e) { e.printStackTrace( ) ; log.error( "余额回退失败" ) ; } }
}
8.5、创建 类 UserServiceImpl.java
package com.itheima.shop.service.impl; import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.api.IUserService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.Result;
import com.itheima.exception.CastException;
import com.itheima.shop.mapper.TradeUserMapper;
import com.itheima.shop.mapper.TradeUserMoneyLogMapper;
import com.itheima.shop.pojo.TradeUser;
import com.itheima.shop.pojo.TradeUserMoneyLog;
import com.itheima.shop.pojo.TradeUserMoneyLogExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.math.BigDecimal;
import java.util.Date; @Component
@Service( interfaceClass = IUserService.class)
public class UserServiceImpl implements IUserService{ @Autowiredprivate TradeUserMapper userMapper; @Autowiredprivate TradeUserMoneyLogMapper userMoneyLogMapper; @Overridepublic TradeUser findOne( Long userId) { if( userId== null) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } return userMapper.selectByPrimaryKey( userId) ; } @Overridepublic Result updateMoneyPaid( TradeUserMoneyLog userMoneyLog) { //1.校验参数是否合法if( userMoneyLog== null || userMoneyLog.getUserId( ) == null || userMoneyLog.getOrderId( ) == null || userMoneyLog.getUseMoney( ) == null|| userMoneyLog.getUseMoney( ) .compareTo( BigDecimal.ZERO) <= 0 ) { CastException.cast( ShopCode.SHOP_REQUEST_PARAMETER_VALID) ; } //2.查询订单余额使用日志TradeUserMoneyLogExample userMoneyLogExample = new TradeUserMoneyLogExample( ) ; TradeUserMoneyLogExample.Criteria criteria = userMoneyLogExample.createCriteria( ) ; criteria.andOrderIdEqualTo( userMoneyLog.getOrderId( )) ; criteria.andUserIdEqualTo( userMoneyLog.getUserId( )) ; int r = userMoneyLogMapper.countByExample( userMoneyLogExample) ; TradeUser tradeUser = userMapper.selectByPrimaryKey( userMoneyLog.getUserId( )) ; //3.扣减余额.. .if( userMoneyLog.getMoneyLogType( ) .intValue( ) == ShopCode.SHOP_USER_MONEY_PAID.getCode( ) .intValue( )) { if( r> 0 ) { //已经付款CastException.cast( ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY) ; } //减余额tradeUser.setUserMoney( new BigDecimal( tradeUser.getUserMoney( )) .subtract( userMoneyLog.getUseMoney( )) .longValue( )) ; userMapper.updateByPrimaryKey( tradeUser) ; } //4.回退余额.. .if( userMoneyLog.getMoneyLogType( ) .intValue( ) == ShopCode.SHOP_USER_MONEY_REFUND.getCode( ) .intValue( )) { if( r< 0 ) { //如果没有支付,则不能回退余额CastException.cast( ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY) ; } //防止多次退款TradeUserMoneyLogExample userMoneyLogExample2 = new TradeUserMoneyLogExample( ) ; TradeUserMoneyLogExample.Criteria criteria1 = userMoneyLogExample2.createCriteria( ) ; criteria1.andOrderIdEqualTo( userMoneyLog.getOrderId( )) ; criteria1.andUserIdEqualTo( userMoneyLog.getUserId( )) ; criteria1.andMoneyLogTypeEqualTo( ShopCode.SHOP_USER_MONEY_REFUND.getCode( )) ; int r2 = userMoneyLogMapper.countByExample( userMoneyLogExample2) ; if( r2 >0 ) { CastException.cast( ShopCode.SHOP_USER_MONEY_REFUND_ALREADY) ; } //退款tradeUser.setUserMoney( new BigDecimal( tradeUser.getUserMoney( )) .add( userMoneyLog.getUseMoney( )) .longValue( )) ; userMapper.updateByPrimaryKey( tradeUser) ; } //5.记录订单余额使用日志userMoneyLog.setCreateTime( new Date( )) ; userMoneyLogMapper.insert( userMoneyLog) ; return new Result( ShopCode.SHOP_SUCCESS.getSuccess( ) ,ShopCode.SHOP_SUCCESS.getMessage( )) ; }
}
8.6、创建 类 UserServiceApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
@EnableDubboConfiguration
public class UserServiceApplication { public static void main( String[ ] args) { SpringApplication.run( UserServiceApplication.class,args) ; } }
8.7、创建 文件 TradeUserMapper.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.itheima.shop.mapper.TradeUserMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeUser" > < id column = "user_id" property = "userId" jdbcType = "BIGINT" /> < result column = "user_name" property = "userName" jdbcType = "VARCHAR" /> < result column = "user_password" property = "userPassword" jdbcType = "VARCHAR" /> < result column = "user_mobile" property = "userMobile" jdbcType = "VARCHAR" /> < result column = "user_score" property = "userScore" jdbcType = "INTEGER" /> < result column = "user_reg_time" property = "userRegTime" jdbcType = "TIMESTAMP" /> < result column = "user_money" property = "userMoney" jdbcType = "DECIMAL" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > user_id, user_name, user_password, user_mobile, user_score, user_reg_time, user_money< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeUserExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_user< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.Long" > select < include refid = "Base_Column_List" /> from trade_userwhere user_id = < /select> < delete id = "deleteByPrimaryKey" parameterType = "java.lang.Long" > delete from trade_userwhere user_id = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeUserExample" > delete from trade_user< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeUser" > insert into trade_user ( user_id, user_name, user_password, user_mobile, user_score, user_reg_time, user_money) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeUser" > insert into trade_user< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "userId != null" > user_id,< /if> < if test = "userName != null" > user_name,< /if> < if test = "userPassword != null" > user_password,< /if> < if test = "userMobile != null" > user_mobile,< /if> < if test = "userScore != null" > user_score,< /if> < if test = "userRegTime != null" > user_reg_time,< /if> < if test = "userMoney != null" > user_money,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "userId != null" > < /if> < if test = "userName != null" > < /if> < if test = "userPassword != null" > < /if> < if test = "userMobile != null" > < /if> < if test = "userScore != null" > < /if> < if test = "userRegTime != null" > < /if> < if test = "userMoney != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeUserExample" resultType = "java.lang.Integer" > select count( *) from trade_user< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_user< set > < if test = "record.userId != null" > user_id = < /if> < if test = "record.userName != null" > user_name = < /if> < if test = "record.userPassword != null" > user_password = < /if> < if test = "record.userMobile != null" > user_mobile = < /if> < if test = "record.userScore != null" > user_score = < /if> < if test = "record.userRegTime != null" > user_reg_time = < /if> < if test = "record.userMoney != null" > user_money = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_userset user_id = user_name = user_password = user_mobile = user_score = user_reg_time = user_money = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeUser" > update trade_user< set > < if test = "userName != null" > user_name = < /if> < if test = "userPassword != null" > user_password = < /if> < if test = "userMobile != null" > user_mobile = < /if> < if test = "userScore != null" > user_score = < /if> < if test = "userRegTime != null" > user_reg_time = < /if> < if test = "userMoney != null" > user_money = < /if> < /set> where user_id = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeUser" > update trade_userset user_name = user_password = user_mobile = user_score = user_reg_time = user_money = where user_id = < /update>
< /mapper>
8.8、创建 文件 TradeUserMoneyLogMapper.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.itheima.shop.mapper.TradeUserMoneyLogMapper" > < resultMap id = "BaseResultMap" type = "com.itheima.shop.pojo.TradeUserMoneyLog" > < id column = "user_id" property = "userId" jdbcType = "BIGINT" /> < id column = "order_id" property = "orderId" jdbcType = "BIGINT" /> < id column = "money_log_type" property = "moneyLogType" jdbcType = "INTEGER" /> < result column = "use_money" property = "useMoney" jdbcType = "DECIMAL" /> < result column = "create_time" property = "createTime" jdbcType = "TIMESTAMP" /> < /resultMap> < sql id = "Example_Where_Clause" > < where > < foreach collection = "oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Update_By_Example_Where_Clause" > < where > < foreach collection = "example.oredCriteria" item = "criteria" separator = "or" > < if test = "criteria.valid" > < trim prefix = "(" suffix = ")" prefixOverrides = "and" > < foreach collection = "criteria.criteria" item = "criterion" > < choose > < when test = "criterion.noValue" > and ${criterion.condition} < /when> < when test = "criterion.singleValue" > and ${criterion.condition} < /when> < when test = "criterion.betweenValue" > and ${criterion.condition} < /when> < when test = "criterion.listValue" > and ${criterion.condition} < foreach collection = "criterion.value" item = "listItem" open = "(" close = ")" separator = "," > < /foreach> < /when> < /choose> < /foreach> < /trim> < /if> < /foreach> < /where> < /sql> < sql id = "Base_Column_List" > user_id, order_id, money_log_type, use_money, create_time< /sql> < select id = "selectByExample" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLogExample" > select < if test = "distinct" > distinct< /if> < include refid = "Base_Column_List" /> from trade_user_money_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < if test = "orderByClause != null" > order by ${orderByClause} < /if> < /select> < select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLogKey" > select < include refid = "Base_Column_List" /> from trade_user_money_logwhere user_id = and order_id = and money_log_type = < /select> < delete id = "deleteByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLogKey" > delete from trade_user_money_logwhere user_id = and order_id = and money_log_type = < /delete> < delete id = "deleteByExample" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLogExample" > delete from trade_user_money_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /delete> < insert id = "insert" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLog" > insert into trade_user_money_log ( user_id, order_id, money_log_type, use_money, create_time) values ( < /insert> < insert id = "insertSelective" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLog" > insert into trade_user_money_log< trim prefix = "(" suffix = ")" suffixOverrides = "," > < if test = "userId != null" > user_id,< /if> < if test = "orderId != null" > order_id,< /if> < if test = "moneyLogType != null" > money_log_type,< /if> < if test = "useMoney != null" > use_money,< /if> < if test = "createTime != null" > create_time,< /if> < /trim> < trim prefix = "values (" suffix = ")" suffixOverrides = "," > < if test = "userId != null" > < /if> < if test = "orderId != null" > < /if> < if test = "moneyLogType != null" > < /if> < if test = "useMoney != null" > < /if> < if test = "createTime != null" > < /if> < /trim> < /insert> < select id = "countByExample" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLogExample" resultType = "java.lang.Integer" > select count( *) from trade_user_money_log< if test = "_parameter != null" > < include refid = "Example_Where_Clause" /> < /if> < /select> < update id = "updateByExampleSelective" parameterType = "map" > update trade_user_money_log< set > < if test = "record.userId != null" > user_id = < /if> < if test = "record.orderId != null" > order_id = < /if> < if test = "record.moneyLogType != null" > money_log_type = < /if> < if test = "record.useMoney != null" > use_money = < /if> < if test = "record.createTime != null" > create_time = < /if> < /set> < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByExample" parameterType = "map" > update trade_user_money_logset user_id = order_id = money_log_type = use_money = create_time = < if test = "_parameter != null" > < include refid = "Update_By_Example_Where_Clause" /> < /if> < /update> < update id = "updateByPrimaryKeySelective" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLog" > update trade_user_money_log< set > < if test = "useMoney != null" > use_money = < /if> < if test = "createTime != null" > create_time = < /if> < /set> where user_id = and order_id = and money_log_type = < /update> < update id = "updateByPrimaryKey" parameterType = "com.itheima.shop.pojo.TradeUserMoneyLog" > update trade_user_money_logset use_money = create_time = where user_id = and order_id = and money_log_type = < /update>
< /mapper>
8.9、创建 文件 application.properties
spring.application.name = dubbo-user-provider
spring.dubbo.application.id = dubbo-user-provider
spring.dubbo.application.name = dubbo-user-provider
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183
spring.dubbo.server = true
spring.dubbo.protocol.name = dubbo
spring.dubbo.protocol.port = 20883
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/trade?useUnicode= true& characterEncoding = utf8
spring.datasource.username = root
spring.datasource.password = root
mybatis.type-aliases-package= com.itheima.shop.pojo
mybatis.mapper-locations= classpath:com/itheima/shop/mapper/*Mapper.xml
rocketmq.name-server= 192.168 .25.135:9876; 192.168 .25.138:9876
rocketmq.producer.group = orderProducerGroupmq.order.consumer.group.name = order_orderTopic_cancel_group
mq.order.topic = orderTopic
9、创建 shop-order-web 订单系统 工程。
9.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-order-web< /artifactId> < dependencies> < ! --spring-webmvc--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < ! --API--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-order-web\ pom.xml -->
9.2、创建 类 OrderWebApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @EnableDubboConfiguration
@SpringBootApplication
public class OrderWebApplication { public static void main( String[ ] args) { SpringApplication.run( OrderWebApplication.class,args) ; } }
9.3、创建 类 OrderControllre.java
package com.itheima.shop.controller; import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.api.IOrderService;
import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradeOrder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping( "/order" )
public class OrderControllre { @Referenceprivate IOrderService orderService; @RequestMapping( "/confirm" ) public Result confirmOrder( @RequestBody TradeOrder order) { return orderService.confirmOrder( order) ; } }
9.4、创建 类 RestTemplateConfig.java
package com.itheima.shop.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List; @Configuration
public class RestTemplateConfig { @Bean@ConditionalOnMissingBean( { RestOperations.class, RestTemplate.class } ) public RestTemplate restTemplate( ClientHttpRequestFactory factory) { RestTemplate restTemplate = new RestTemplate( factory) ; // 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1" )List< HttpMessageConverter< ?>> messageConverters = restTemplate.getMessageConverters( ) ; Iterator< HttpMessageConverter< ?>> iterator = messageConverters.iterator( ) ; while ( iterator.hasNext( )) { HttpMessageConverter< ?> converter = iterator.next( ) ; if ( converter instanceof StringHttpMessageConverter) { iterator.remove( ) ; } } messageConverters.add( new StringHttpMessageConverter( Charset.forName( "UTF-8" )) ) ; return restTemplate; } @Bean@ConditionalOnMissingBean( { ClientHttpRequestFactory.class} ) public ClientHttpRequestFactory simpleClientHttpRequestFactory ( ) { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory( ) ; // msfactory.setReadTimeout( 15000 ) ; // msfactory.setConnectTimeout( 15000 ) ; return factory; } }
9.5、创建 配置文件 application.properties
server.host = http://localhost
server.servlet.path = /order-web
server.port = 8080
spring.application.name = dubbo-order-consumer
spring.dubbo.application.id = dubbo-order-consumer
spring.dubbo.application.name = dubbo-order-consumer
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183order.port = 8080
shop.order.baseURI = ${server.host} : ${order.port} ${server.servlet.path}
shop.order.confirm = /order/confirm
9.6、创建 测试 类 OrderWebTest.java
package com.itheima.test; import com.itheima.entity.Result;
import com.itheima.shop.OrderWebApplication;
import com.itheima.shop.pojo.TradeOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate; import java.math.BigDecimal; @RunWith( SpringRunner.class)
@SpringBootTest( classes = OrderWebApplication.class)
public class OrderWebTest { @Autowiredprivate RestTemplate restTemplate; @Value( "${shop.order.baseURI} " ) private String baseURI; @Value( "${shop.order.confirm} " ) private String confirmOrderPath; @Testpublic void confirmOrder ( ) { Long coupouId = 345988230098857984L; Long goodsId = 345959443973935104L; Long userId = 345963634385633280L; TradeOrder order = new TradeOrder( ) ; order.setGoodsId( goodsId) ; order.setUserId( userId) ; order.setCouponId( coupouId) ; order.setAddress( "北京" ) ; order.setGoodsNumber( 1 ) ; order.setGoodsPrice( new BigDecimal( 1000 )) ; order.setShippingFee( BigDecimal.ZERO) ; order.setOrderAmount( new BigDecimal( 1000 )) ; order.setMoneyPaid( new BigDecimal( 100 )) ; Result result = restTemplate.postForEntity( baseURI + confirmOrderPath, order, Result.class) .getBody( ) ; System.out.println( result) ; } }
10、创建 shop-pay-web 支付系统 工程。
10.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-pay-web< /artifactId> < dependencies> < ! --spring-webmvc--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < ! --API--> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-api< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < dependency> < groupId> com.iteima.shop< /groupId> < artifactId> shop-common< /artifactId> < version> 1.0 -SNAPSHOT< /version> < /dependency> < /dependencies> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-pay-web\ pom.xml -->
10.2、创建 类 PayWebApplication.java
package com.itheima.shop; import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @EnableDubboConfiguration
@SpringBootApplication
public class PayWebApplication { public static void main( String[ ] args) { SpringApplication.run( PayWebApplication.class,args) ; } }
10.3、创建 类 PayController.java
package com.itheima.shop.controller; import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.api.IPayService;
import com.itheima.entity.Result;
import com.itheima.shop.pojo.TradePay;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping( "/pay" )
public class PayController { @Referenceprivate IPayService payService; @RequestMapping( "/createPayment" ) public Result createPayment( @RequestBody TradePay pay) { return payService.createPayment( pay) ; } @RequestMapping( "/callBackPayment" ) public Result callBackPayment( @RequestBody TradePay pay) throws Exception { return payService.callbackPayment( pay) ; } }
10.4、创建 类 RestTemplateConfig.java
package com.itheima.shop.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List; @Configuration
public class RestTemplateConfig { @Bean@ConditionalOnMissingBean( { RestOperations.class, RestTemplate.class } ) public RestTemplate restTemplate( ClientHttpRequestFactory factory) { RestTemplate restTemplate = new RestTemplate( factory) ; // 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1" )List< HttpMessageConverter< ?>> messageConverters = restTemplate.getMessageConverters( ) ; Iterator< HttpMessageConverter< ?>> iterator = messageConverters.iterator( ) ; while ( iterator.hasNext( )) { HttpMessageConverter< ?> converter = iterator.next( ) ; if ( converter instanceof StringHttpMessageConverter) { iterator.remove( ) ; } } messageConverters.add( new StringHttpMessageConverter( Charset.forName( "UTF-8" )) ) ; return restTemplate; } @Bean@ConditionalOnMissingBean( { ClientHttpRequestFactory.class} ) public ClientHttpRequestFactory simpleClientHttpRequestFactory ( ) { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory( ) ; // msfactory.setReadTimeout( 15000 ) ; // msfactory.setConnectTimeout( 15000 ) ; return factory; } }
10.5、创建 配置文件 application.properties
server.host = http://localhost
server.servlet.path = /pay-web
server.port = 9090
spring.application.name = dubbo-pay-consumer
spring.dubbo.application.id = dubbo-pay-consumer
spring.dubbo.application.name = dubbo-pay-consumer
spring.dubbo.registry.address = zookeeper://192.168.25.140:2181; zookeeper://192.168.25.140:2182; zookeeper://192.168.25.140:2183pay.port = 9090 shop.pay.baseURI = ${server.host} : ${pay.port} ${server.servlet.path} shop.pay.createPayment = /pay/createPaymentshop.pay.callbackPayment = /pay/callBackPayment
10.6、创建 测试 类 PayWebTest.java
package com.itheima.test; import com.itheima.constant.ShopCode;
import com.itheima.entity.Result;
import com.itheima.shop.PayWebApplication;
import com.itheima.shop.pojo.TradePay;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate; import java.math.BigDecimal; @RunWith( SpringRunner.class)
@SpringBootTest( classes = PayWebApplication.class)
public class PayWebTest { @Autowiredprivate RestTemplate restTemplate; @Value( "${shop.pay.baseURI} " ) private String baseURI; @Value( "${shop.pay.createPayment} " ) private String createPaymentPath; @Value( "${shop.pay.callbackPayment} " ) private String callBackPaymentPath; @Testpublic void createPayment ( ) { long orderId = 352537369385242624L; TradePay tradePay = new TradePay( ) ; tradePay.setOrderId( orderId) ; tradePay.setPayAmount( new BigDecimal( 880 )) ; Result result = restTemplate.postForEntity( baseURI + createPaymentPath, tradePay, Result.class) .getBody( ) ; System.out.println( result) ; } @Testpublic void callBackPayment ( ) { long payId = 352542415984402432L; long orderId = 352537369385242624L; TradePay tradePay = new TradePay( ) ; tradePay.setPayId( payId) ; tradePay.setOrderId( orderId) ; tradePay.setIsPaid( ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode( )) ; Result result = restTemplate.postForEntity( baseURI + callBackPaymentPath, tradePay, Result.class) .getBody( ) ; System.out.println( result) ; } }
11、创建 shop-pojo 实体类 工程。
11.1、在 pom.xml 中,导入依赖坐标。
< ?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> shop-parent< /artifactId> < groupId> com.iteima.shop< /groupId> < version> 1.0 -SNAPSHOT< /version> < relativePath> .. /shop-parent/pom.xml< /relativePath> < /parent> < modelVersion> 4.0 .0 < /modelVersion> < artifactId> shop-pojo< /artifactId> < /project>
< ! -- D:\ java-test\ idea2019\ shop\ shop-pojo\ pom.xml -->
上一节关联链接请点击: # RocketMQ 实战:模拟电商网站场景综合案例(二)