網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Springcloud集成Seata分布式事務(wù)
一、環(huán)境
開(kāi)發(fā)工具:idea
springcloud版本:Hoxton.SR12
springboot版本:2.3.12.RELEASE
springcloud alibaba版本:2.2.7.RELEASE
seata版本:2.2.7.RELEASE
Seata單機(jī)部署、 Seata集群部署 和 nginx代理nacos集群
二、pom文件依賴(lài)
主要給出核心依賴(lài),其他依賴(lài)自行引入,不如springcloud、springcloudalibaba等等
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
……
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-seataartifactId>
<exclusions>
<exclusion>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
exclusion>
exclusions>
dependency>
dependencies>
……
project>
三、applicaton.yml配置
配置文件關(guān)于nacos的配置,可以參考Nginx代理Nacos集群進(jìn)行配置
自行配置數(shù)據(jù)配置和端口信息
# spring 相關(guān)配置
spring:
cloud:
alibaba:
seata:
# seata分組配置
tx-service-group: my_test_tx_group
# seata分布式事務(wù)配置
seata:
# 注冊(cè)中心配置
registry:
# 注冊(cè)中心類(lèi)型,這里采用alibaba的nacos
type: nacos
nacos:
# 服務(wù)名
application: seata-server
# nacos注冊(cè)中的地址,此處配置多個(gè)時(shí)默認(rèn)集群模式
server-addr: 192.168.0.28:8844,192.168.0.28:8846,192.168.0.28:8848
# nacos用戶(hù)密碼
username: nacos
password: nacos
# 分組名
group: SEATA_GROUP
# 命名空間ID值
namespace: 637b036c-75a2-4afb-9ccd-2716ece04ffd
# 配置中心
config:
# 配置中心類(lèi)型,這里采用alibaba的nacos
type: nacos
nacos:
# 配置中心地址,此處配置多個(gè)時(shí)模式集群模式
server-addr: 192.168.0.28:8844,192.168.0.28:8846,192.168.0.28:8848
# 配置中心用戶(hù)名和密碼
username: nacos
password: nacos
# 分組名
group: SEATA_GROUP
# 命名空間
namespace: 637b036c-75a2-4afb-9ccd-2716ece04ffd
四、商品服務(wù)
- OrderController.java
package com.jwssw.order.controller;
import com.jwssw.order.provider.StockServiceProvider;
import com.jwssw.order.service.OrderService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* 類(lèi)描述:對(duì)外提供服務(wù)類(lèi)
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/3/19 10:43
* @since JDK 8
*/
@RestController
@RequestMapping("/order")
public class OrderController {
/** restTemplate遠(yuǎn)程調(diào)用對(duì)象 */
private final RestTemplate restTemplate;
/** openfeign遠(yuǎn)程調(diào)用對(duì)象 */
private final StockServiceProvider stockService;
/** 訂單服務(wù)接口 */
private final OrderService orderService;
/**
* 構(gòu)造方法注入
*/
public OrderController(RestTemplate restTemplate, StockServiceProvider stockService, OrderService orderService) {
this.restTemplate = restTemplate;
this.stockService = stockService;
this.orderService = orderService;
}
/**
* 增加訂單同時(shí)減少庫(kù)存
*/
@RequestMapping("/insert")
public String insert(@RequestParam("num") int num) {
// 調(diào)用接口
return orderService.reduct(num);
}
}
- OrderService.java
package com.jwssw.order.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jwssw.order.domain.entity.JwsswOrder;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 16:26
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
public interface OrderService extends IService<JwsswOrder> {
// 增加訂單同時(shí)減少庫(kù)存
String reduct(int num);
}
- OrderServiceImpl.java
@GlobalTransactional 該注解是seata實(shí)現(xiàn)分布式事務(wù)的關(guān)鍵注解,將該注解直接作用于方法上即可。
package com.jwssw.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwssw.order.domain.entity.JwsswOrder;
import com.jwssw.order.mapper.OrderMapper;
import com.jwssw.order.provider.StockServiceProvider;
import com.jwssw.order.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Date;
import java.util.Random;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 16:26
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, JwsswOrder> implements OrderService {
/** restTemplate遠(yuǎn)程調(diào)用對(duì)象 */
private final RestTemplate restTemplate;
private final StockServiceProvider stockServiceProvider;
/**
* 構(gòu)造方法注入
*/
public OrderServiceImpl(RestTemplate restTemplate, StockServiceProvider stockServiceProvider) {
this.restTemplate = restTemplate;
this.stockServiceProvider = stockServiceProvider;
}
@GlobalTransactional // 該注解是seata實(shí)現(xiàn)分布式事務(wù)的關(guān)鍵主鍵
@Override
public String reduct(int num) {
// 本地?cái)?shù)據(jù)庫(kù)保存訂單
JwsswOrder order = new JwsswOrder();
order.setId(new Random().nextInt(100000));
order.setContext("cethis");
order.setCreateDate(new Date().toString());
baseMapper.insert(order);
// 調(diào)用庫(kù)存微服務(wù)接口(openfeign遠(yuǎn)程調(diào)用)
String reduct = stockServiceProvider.reduce(1);
// 模擬失敗,主要是除0
int i = 1 / num;
return reduct;
}
}
- StockServiceProvider.java
該類(lèi)作用就是通過(guò)openfeign調(diào)用庫(kù)存服務(wù)中的接口
package com.jwssw.order.provider;
import com.jwssw.order.provider.fallback.StockServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 類(lèi)描述:openfeign遠(yuǎn)程調(diào)用接口類(lèi)
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/3/24 09:53
* @since JDK 8
*/
@FeignClient(name = "stock-server", fallbackFactory = StockServiceFallback.class)
public interface StockServiceProvider {
/**
* 方法描述: 調(diào)用stock服務(wù)的reduct接口的方法
*
* @return {@link String}
* @author 魯浩鵬 Lu Haopeng
* @date 2022/3/25 14:23
*/
@PostMapping("/stock/reduce")
String reduce(@RequestParam("stockId") int stockId);
}
- StockServiceFallback
package com.jwssw.order.provider.fallback;
import com.jwssw.order.provider.StockServiceProvider;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 16:33
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
@Component
public class StockServiceFallback implements FallbackFactory<StockServiceFactory> {
@Override
public StockServiceFactory create(Throwable cause) {
return new StockServiceFactory();
}
}
/**
* 錯(cuò)誤回調(diào)工廠(chǎng)類(lèi)
*/
class StockServiceFactory implements StockServiceProvider {
/**
* 方法描述: 調(diào)用stock服務(wù)的reduct接口的方法
*
* @return {@link String}
* @author 魯浩鵬 Lu Haopeng
* @date 2022/3/25 14:23
*/
@Override
public String reduce(int stockId) {
return "庫(kù)存服務(wù)不可達(dá)";
}
}
- JwsswOrder.java
package com.jwssw.order.domain.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 16:02
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@TableName("jwssw_order")
public class JwsswOrder implements Serializable {
@TableId
private int id;
private String createDate;
private String context;
}
- OrderMapper.java
package com.jwssw.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jwssw.order.domain.entity.JwsswOrder;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 16:22
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
public interface OrderMapper extends BaseMapper<JwsswOrder> {
}
五、庫(kù)存服務(wù)
- StockController.java
package com.jwssw.stock.controller;
import com.jwssw.stock.domain.entity.JwsswStock;
import com.jwssw.stock.service.StockService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 類(lèi)描述:對(duì)外提供服務(wù)類(lèi)
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/3/19 10:46
* @since JDK 8
*/
@RestController
@RequestMapping("/stock")
public class StockController {
/** 獲取配置文件中的端口號(hào) */
@Value("${server.port}")
private String port;
private final StockService stockService;
public StockController(StockService stockService) {
this.stockService = stockService;
}
@PostMapping("/reduce")
public String reduce(@RequestParam("stockId") int stockId) {
// todo 為了演示方便寫(xiě)在此處了,正式項(xiàng)目中需要寫(xiě)在service中
boolean update = stockService.lambdaUpdate().setSql("stock_number=stock_number -1")
.eq(JwsswStock::getId, stockId).update();
return update ? "扣減庫(kù)存成功" : "扣減庫(kù)存失敗";
}
}
庫(kù)存的SQL語(yǔ)句
INSERT INTO `jwssw_stock` (`id`, `order_name`, `stock_number`) VALUES (1, '芬太尼', 77);
- StockService.java
package com.jwssw.stock.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jwssw.stock.domain.entity.JwsswStock;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 18:32
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
public interface StockService extends IService<JwsswStock> {
}
- StockServiceImpl.java
package com.jwssw.stock.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwssw.stock.domain.entity.JwsswStock;
import com.jwssw.stock.mapper.StockMapper;
import com.jwssw.stock.service.StockService;
import org.springframework.stereotype.Service;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 18:33
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, JwsswStock> implements StockService {
}
- StockMapper.java
package com.jwssw.stock.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jwssw.stock.domain.entity.JwsswStock;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 18:32
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
public interface StockMapper extends BaseMapper<JwsswStock> {
}
- JwsswStock.java
package com.jwssw.stock.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
/**
* 類(lèi)描述:
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/4/5 18:30
* @slogan 優(yōu)良的架構(gòu)是演進(jìn)而來(lái)的,非設(shè)計(jì)出來(lái)的
* @since JDK 8
*/
@Data
@Builder
@TableName("jwssw_stock")
public class JwsswStock {
private int id;
private String orderName;
private int stockNumber;
}
六、測(cè)試
單元測(cè)試類(lèi)是JUnti5
- OrderControllerTest.java
package com.jwssw.order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* 類(lèi)描述:?jiǎn)卧獪y(cè)試類(lèi)
*
* @author 魯浩鵬 Lu Haopeng
* @version 1.0
* @email Lu Haopeng
* @date 2022/3/24 09:26
* @since JDK 8
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
class OrderControllerTest {
@Autowired
private MockMvc mvc;
@Test
void add() throws Exception {
// 調(diào)用controller中的接口
ResultActions resultActions = mvc.perform(get("/order/insert").param("num", "1"))
.andDo(print())
.andExpect(status().isOk());
// 輸出結(jié)果
System.out.println(resultActions.andReturn().getResponse().getContentAsString());
}
}
小伙伴們自行運(yùn)行單元測(cè)試類(lèi)時(shí),需要修改num參數(shù)值(num=0是回滾)來(lái)實(shí)驗(yàn)seata分布式的回滾魅力。
原文鏈接:https://blog.csdn.net/lhp3000/article/details/124111987
相關(guān)推薦
- 2022-05-20 ASP.NET?MVC模式中應(yīng)用程序結(jié)構(gòu)詳解_基礎(chǔ)應(yīng)用
- 2023-01-13 Pytorch中關(guān)于BatchNorm2d的參數(shù)解釋_python
- 2022-03-29 C語(yǔ)言中的getchar()使用詳解_C 語(yǔ)言
- 2023-05-14 Python稀疏矩陣scipy.sparse包使用詳解_python
- 2023-02-14 C++關(guān)于字符的接收與輸出操作示例_C 語(yǔ)言
- 2022-05-12 Kotlin 擴(kuò)展函數(shù) 鏈?zhǔn)秸{(diào)用 泛型與擴(kuò)展函數(shù)
- 2022-11-16 Oracle?刪除大量表記錄操作分析總結(jié)_oracle
- 2022-05-19 redis擊穿?雪崩?穿透超詳細(xì)解決方案梳理_Redis
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支