使用三个服务来进行演示
三个服务的共同部分
pom相关依赖
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<artifactId>seata-all</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
// 1.0 之后的版本引入方式不一样
// 1.0 之后需要使用
// <artifactId>seata-spring-boot-start</artifactId>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>0.9.0</version>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
-
取消数据源的自动创建
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源的自动创建
public class SeataOrderMainApp2001
{
public static void main(String[] args)
{
SpringApplication.run(SeataOrderMainApp2001.class, args);
}
}
-
使用seata对数据源进行代理
@Configuration
public class DataSourceProxyConfig {
@Value("${mybatis.mapperLocations}")
private String mapperLocations;
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
public DataSourceProxy dataSourceProxy(DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean.getObject();
}
}
-
mybatis的配置
@Configuration
@MapperScan({"com.atguigu.springcloud.alibaba.dao"})
public class MyBatisConfig {
}
-
下订单(order)服务controller部分
@RestController
public class OrderController
{
@Resource
private OrderService orderService;
@GetMapping("/order/create")
public CommonResult create(Order order)
{
orderService.create(order);
return new CommonResult(200,"订单创建成功");
}
}
-
commresult.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T>
{
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message)
{
this(code,message,null);
}
}
-
订单部分service 关键注解 @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
@Service
@Slf4j
public class OrderServiceImpl implements OrderService
{
@Resource
private OrderDao orderDao;
@Resource
private StorageService storageService;
@Resource
private AccountService accountService;
/**
* 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态
* 简单说:下订单->扣库存->减余额->改状态
*/
@Override
// 关键注解,加上之后就能支持全局事务
@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
public void create(Order order)
{
log.info("----->开始新建订单");
//1 新建订单
orderDao.create(order);
//2 扣减库存
log.info("----->订单微服务开始调用库存,做扣减Count");
storageService.decrease(order.getProductId(),order.getCount());
log.info("----->订单微服务开始调用库存,做扣减end");
//3 扣减账户
log.info("----->订单微服务开始调用账户,做扣减Money");
accountService.decrease(order.getUserId(),order.getMoney());
log.info("----->订单微服务开始调用账户,做扣减end");
//4 修改订单状态,从零到1,1代表已经完成
log.info("----->修改订单状态开始");
orderDao.update(order.getUserId(),0);
log.info("----->修改订单状态结束");
log.info("----->下订单结束了,O(∩_∩)O哈哈~");
}
}
-
feign对另外两个服务发起远程调用
// accountService.class
@FeignClient(value = "seata-account-service")
public interface AccountService
{
@PostMapping(value = "/account/decrease")
CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
}
// storageService.class
@FeignClient(value = "seata-storage-service")
public interface StorageService
{
@PostMapping(value = "/storage/decrease")
CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
}
mapper.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.atguigu.springcloud.alibaba.dao.OrderDao">
<resultMap id="BaseResultMap" type="com.atguigu.springcloud.alibaba.domain.Order">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="user_id" property="userId" jdbcType="BIGINT"/>
<result column="product_id" property="productId" jdbcType="BIGINT"/>
<result column="count" property="count" jdbcType="INTEGER"/>
<result column="money" property="money" jdbcType="DECIMAL"/>
<result column="status" property="status" jdbcType="INTEGER"/>
</resultMap>
<insert id="create">
insert into t_order (id,user_id,product_id,count,money,status)
values (null,#{userId},#{productId},#{count},#{money},0);
</insert>
<update id="update">
update t_order set status = 1
where user_id=#{userId} and status = #{status};
</update>
</mapper>
resource 部分
server:
port: 2001
spring:
application:
name: seata-order-service
cloud:
alibaba:
#seata 的配置
seata:
#自定义事务组名称需要与seata-server中的对应
tx-service-group: fsp_tx_group
#nacos的配置
nacos:
discovery:
server-addr: localhost:8848
# 数据源的配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.4:3306/seata_order
username: root
password: root
# 关闭hystrix
feign:
hystrix:
enabled: false
logging:
level:
io:
seata: info
# 指定mapper的位置扫描
mybatis:
mapperLocations: classpath:mapper/*.xml
file.conf相对原始文件需要修改的地方
servcie部分 (此处为客户配置端)
service {
# fsp_tx_group是服务端配置的事务组名
vgroup_mapping.fsp_tx_group = "default" #修改自定义事务组名称
}
servcie部分 (此处为服务配置端)
service {
# fsp_tx_group是服务端配置的事务组名
vgroup_mapping.my_test_tx_group. = "fsp_tx_group" #修改自定义事务组名称
}
registry部分
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos" // 此处若使用nacos进行服务注册需要改成nacos
nacos {
serverAddr = "localhost:8848"
namespace = ""
cluster = "default"
}
}
雪花算法优缺点(snowflake)
解决了时钟回拨的两个算法
百度的和美团的两个id生成算法
标签:info,seata,springcloud,class,order,订单,public,分布式 From: https://www.cnblogs.com/huoziqi/p/17545987.html