diff --git a/examples/seata-example/account-service/pom.xml b/examples/seata-example/account-service/pom.xml new file mode 100644 index 0000000..1d9b69f --- /dev/null +++ b/examples/seata-example/account-service/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + com.chinaunicom.mall.ebtp.cloud + seata-example + 0.0.1-SNAPSHOT + + com.chinaunicom.mall.ebtp.cloud + account-service + 0.0.1-SNAPSHOT + account-service + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/AccountSeataApplication.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/AccountSeataApplication.java new file mode 100644 index 0000000..3989520 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/AccountSeataApplication.java @@ -0,0 +1,20 @@ +package com.chinaunicom.mall.ebtp.cloud.account; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Import; + +import com.chinaunicom.mall.ebtp.cloud.eureka.starter.EurekaStarterConfiguration; + +@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) +@EnableFeignClients +@Import(EurekaStarterConfiguration.class) +public class AccountSeataApplication { + + public static void main(String[] args) { + SpringApplication.run(AccountSeataApplication.class, args); + } + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/config/SeataDatasourceConfiguration.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/config/SeataDatasourceConfiguration.java new file mode 100644 index 0000000..e14cb34 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/config/SeataDatasourceConfiguration.java @@ -0,0 +1,42 @@ +package com.chinaunicom.mall.ebtp.cloud.account.config; + +import javax.sql.DataSource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.transaction.SpringManagedTransactionFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import com.alibaba.druid.pool.DruidDataSource; + +import io.seata.rm.datasource.DataSourceProxy; + +@Configuration +public class SeataDatasourceConfiguration { + + @Bean + @ConfigurationProperties(prefix = "spring.datasource") + public DataSource druidDataSource() { + return new DruidDataSource(); + } + + @Primary + @Bean("dataSource") + public DataSourceProxy dataSource(DataSource druidDataSource) { + return new DataSourceProxy(druidDataSource); + } + + @Bean + public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception { + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + sqlSessionFactoryBean.setDataSource(dataSourceProxy); + sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); + + return sqlSessionFactoryBean.getObject(); + + } + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/controller/AccountController.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/controller/AccountController.java new file mode 100644 index 0000000..06f7818 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/controller/AccountController.java @@ -0,0 +1,24 @@ +package com.chinaunicom.mall.ebtp.cloud.account.controller; + +import java.math.BigDecimal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.chinaunicom.mall.ebtp.cloud.account.service.AccountService; + +@RestController +@RequestMapping("account") +public class AccountController { + + private @Autowired AccountService accountService; + + @RequestMapping("decrease") + public String decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money) { + accountService.decrease(userId, money); + return "Account decrease success"; + } + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/entity/Account.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/entity/Account.java new file mode 100644 index 0000000..67454ed --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/entity/Account.java @@ -0,0 +1,21 @@ +package com.chinaunicom.mall.ebtp.cloud.account.entity; + +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@TableName +@Accessors(chain = true) +public class Account { + + private Long id; + private Long userId; + private BigDecimal total; + private BigDecimal used; + private BigDecimal residue; + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/feign/OrderApi.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/feign/OrderApi.java new file mode 100644 index 0000000..837526d --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/feign/OrderApi.java @@ -0,0 +1,16 @@ +package com.chinaunicom.mall.ebtp.cloud.account.feign; + +import java.math.BigDecimal; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(value = "order-service") +public interface OrderApi { + + @RequestMapping("/order/update") + String update(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money, + @RequestParam("status") Integer status); + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/mapper/AccountMapper.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/mapper/AccountMapper.java new file mode 100644 index 0000000..f465201 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/mapper/AccountMapper.java @@ -0,0 +1,18 @@ +package com.chinaunicom.mall.ebtp.cloud.account.mapper; + +import java.math.BigDecimal; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chinaunicom.mall.ebtp.cloud.account.entity.Account; + +@Mapper +public interface AccountMapper extends BaseMapper { + + @Update("UPDATE account SET residue = residue - #{money}, used = used + #{money} WHERE user_id = #{userId}") + void decrease(@Param("userId") Long userId, @Param("money") BigDecimal money); + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/AccountService.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/AccountService.java new file mode 100644 index 0000000..a812435 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/AccountService.java @@ -0,0 +1,9 @@ +package com.chinaunicom.mall.ebtp.cloud.account.service; + +import java.math.BigDecimal; + +public interface AccountService { + + void decrease(Long userId, BigDecimal money); + +} diff --git a/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/impl/AccountServiceImpl.java b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/impl/AccountServiceImpl.java new file mode 100644 index 0000000..6f8d671 --- /dev/null +++ b/examples/seata-example/account-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/account/service/impl/AccountServiceImpl.java @@ -0,0 +1,38 @@ +package com.chinaunicom.mall.ebtp.cloud.account.service.impl; + +import java.math.BigDecimal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.chinaunicom.mall.ebtp.cloud.account.feign.OrderApi; +import com.chinaunicom.mall.ebtp.cloud.account.mapper.AccountMapper; +import com.chinaunicom.mall.ebtp.cloud.account.service.AccountService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class AccountServiceImpl implements AccountService { + + private @Autowired AccountMapper accountMapper; + private @Autowired OrderApi orderApi; + + @Override + public void decrease(Long userId, BigDecimal money) { + + log.info("--------> 扣减账户数据开始"); + + accountMapper.decrease(userId, money); + + log.info("------->扣减账户结束account中"); + + log.info("修改订单状态开始"); + + String mes = orderApi.update(userId, money.multiply(new BigDecimal("0.09")), 0); + + log.info("修改订单状态结束:{}", mes); + + } + +} diff --git a/examples/seata-example/account-service/src/main/reources/application-dev.yml b/examples/seata-example/account-service/src/main/reources/application-dev.yml new file mode 100644 index 0000000..41fbbf9 --- /dev/null +++ b/examples/seata-example/account-service/src/main/reources/application-dev.yml @@ -0,0 +1,17 @@ +logging: + level: + com.chinaunicom.mall.ebtp.cloud: info + +server: + port: 8672 + +spring: + cloud: + alibaba: + seata: + tx-service-group: test_tx_group + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://125.32.114.204:13306/ebtp_mall_bid?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + username: mall3-ebtp-dev + password: mall3-ebtp-dev diff --git a/examples/seata-example/account-service/src/main/reources/application.yml b/examples/seata-example/account-service/src/main/reources/application.yml new file mode 100644 index 0000000..c59b20c --- /dev/null +++ b/examples/seata-example/account-service/src/main/reources/application.yml @@ -0,0 +1,6 @@ +spring: + profiles: + active: dev + application: + name: account-service + \ No newline at end of file diff --git a/examples/seata-example/account-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/account/AppTest.java b/examples/seata-example/account-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/account/AppTest.java new file mode 100644 index 0000000..67c932c --- /dev/null +++ b/examples/seata-example/account-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/account/AppTest.java @@ -0,0 +1,38 @@ +package com.chinaunicom.mall.ebtp.cloud.account; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/examples/seata-example/order-service/pom.xml b/examples/seata-example/order-service/pom.xml new file mode 100644 index 0000000..fdf6947 --- /dev/null +++ b/examples/seata-example/order-service/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + com.chinaunicom.mall.ebtp.cloud + seata-example + 0.0.1-SNAPSHOT + + com.chinaunicom.mall.ebtp.cloud + order-service + 0.0.1-SNAPSHOT + order-service + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/OrderSeataApplication.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/OrderSeataApplication.java new file mode 100644 index 0000000..b9eb123 --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/OrderSeataApplication.java @@ -0,0 +1,18 @@ +package com.chinaunicom.mall.ebtp.cloud.order; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Import; + +import com.chinaunicom.mall.ebtp.cloud.eureka.starter.EurekaStarterConfiguration; + +@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) +@EnableFeignClients +@Import(EurekaStarterConfiguration.class) +public class OrderSeataApplication { + public static void main(String[] args) { + SpringApplication.run(OrderSeataApplication.class, args); + } +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/config/SeataDatasourceConfiguration.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/config/SeataDatasourceConfiguration.java new file mode 100644 index 0000000..d9d3fad --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/config/SeataDatasourceConfiguration.java @@ -0,0 +1,41 @@ +package com.chinaunicom.mall.ebtp.cloud.order.config; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import com.alibaba.druid.pool.DruidDataSource; +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; + +import io.seata.rm.datasource.DataSourceProxy; + +@Configuration +public class SeataDatasourceConfiguration { + + @Bean + @ConfigurationProperties(prefix = "spring.datasource") + public DataSource druidDataSource() { + return new DruidDataSource(); + } + + @Primary + @Bean("dataSource") + public DataSourceProxy dataSource(DataSource druidDataSource) { + return new DataSourceProxy(druidDataSource); + } + + @Bean + @ConfigurationProperties(prefix = "mybatis") + public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource) { + // 这里用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否则 MyBatisPlus 不会生效 + MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); + mybatisSqlSessionFactoryBean.setDataSource(dataSource); + + return mybatisSqlSessionFactoryBean; + } + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/controller/OrderController.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/controller/OrderController.java new file mode 100644 index 0000000..ebca2ad --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/controller/OrderController.java @@ -0,0 +1,34 @@ +package com.chinaunicom.mall.ebtp.cloud.order.controller; + +import java.math.BigDecimal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.chinaunicom.mall.ebtp.cloud.order.entity.Order; +import com.chinaunicom.mall.ebtp.cloud.order.service.OrderService; + +@RestController +@RequestMapping("order") +public class OrderController { + + private @Autowired OrderService orderService; + + @GetMapping("create") + public String create(@RequestBody Order order) { + orderService.create(order); + return "Create order success"; + } + + @RequestMapping("update") + String update(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money, + @RequestParam("status") Integer status) { + orderService.update(userId, money, status); + return "订单状态修改成功"; + } + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/entity/Order.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/entity/Order.java new file mode 100644 index 0000000..1c0ef3b --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/entity/Order.java @@ -0,0 +1,22 @@ +package com.chinaunicom.mall.ebtp.cloud.order.entity; + +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@TableName("order_tbl") +public class Order { + + private Long id; + private Long userId; + private Long productId; + private Integer count; + private BigDecimal money; + private Integer status; + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/AccountApi.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/AccountApi.java new file mode 100644 index 0000000..8f6a788 --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/AccountApi.java @@ -0,0 +1,15 @@ +package com.chinaunicom.mall.ebtp.cloud.order.feign; + +import java.math.BigDecimal; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient("account-service") +public interface AccountApi { + + @RequestMapping("/account/decrease") + String decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money); + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/StorageApi.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/StorageApi.java new file mode 100644 index 0000000..5aa0692 --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/feign/StorageApi.java @@ -0,0 +1,13 @@ +package com.chinaunicom.mall.ebtp.cloud.order.feign; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient("storage-service") +public interface StorageApi { + + @RequestMapping("/storage/decrease") + String decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count); + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/mapper/OrderMapper.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/mapper/OrderMapper.java new file mode 100644 index 0000000..6320827 --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/mapper/OrderMapper.java @@ -0,0 +1,18 @@ +package com.chinaunicom.mall.ebtp.cloud.order.mapper; + +import java.math.BigDecimal; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chinaunicom.mall.ebtp.cloud.order.entity.Order; + +@Mapper +public interface OrderMapper extends BaseMapper { + + @Update("UPDATE `order_tbl` SET money = money - #{money}, status = 1 WHERE user_id = #{userId} AND status = #{status};") + void update(@Param("userId") Long userId, @Param("money") BigDecimal money, @Param("status") Integer status); + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/OrderService.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/OrderService.java new file mode 100644 index 0000000..7ccc2d9 --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/OrderService.java @@ -0,0 +1,13 @@ +package com.chinaunicom.mall.ebtp.cloud.order.service; + +import java.math.BigDecimal; + +import com.chinaunicom.mall.ebtp.cloud.order.entity.Order; + +public interface OrderService { + + void create(Order order); + + void update(Long userId, BigDecimal money, Integer status); + +} diff --git a/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/impl/OrderServiceImpl.java b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..0297fbb --- /dev/null +++ b/examples/seata-example/order-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/order/service/impl/OrderServiceImpl.java @@ -0,0 +1,49 @@ +package com.chinaunicom.mall.ebtp.cloud.order.service.impl; + +import java.math.BigDecimal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.chinaunicom.mall.ebtp.cloud.order.entity.Order; +import com.chinaunicom.mall.ebtp.cloud.order.feign.AccountApi; +import com.chinaunicom.mall.ebtp.cloud.order.feign.StorageApi; +import com.chinaunicom.mall.ebtp.cloud.order.mapper.OrderMapper; +import com.chinaunicom.mall.ebtp.cloud.order.service.OrderService; + +import io.seata.spring.annotation.GlobalTransactional; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class OrderServiceImpl implements OrderService { + + private @Autowired OrderMapper orderMapper; + private @Autowired StorageApi storageApi; + private @Autowired AccountApi accountApi; + + @Override + @GlobalTransactional(name = "fsp-create-order", rollbackFor = Exception.class) + public void create(Order order) { + + log.info("-------->开始" + order); + + orderMapper.insert(order); + + // 扣减库存 + storageApi.decrease(order.getProductId(), order.getCount()); + + log.info("-----------> 扣减账户开始"); + accountApi.decrease(order.getUserId(), order.getMoney()); + log.info("-----------> 扣减账户结束"); + + log.info("--------> 交易结束"); + } + + @Override + public void update(Long userId, BigDecimal money, Integer status) { + log.info("修改订单状态,入参为:userId={},money={},status={}", userId, money, status); + orderMapper.update(userId, money, status); + } + +} diff --git a/examples/seata-example/order-service/src/main/resources/application-dev.yml b/examples/seata-example/order-service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..8a65607 --- /dev/null +++ b/examples/seata-example/order-service/src/main/resources/application-dev.yml @@ -0,0 +1,18 @@ +logging: + level: + com.chinaunicom.mall.ebtp.cloud: info + +server: + port: 8673 + +spring: + cloud: + alibaba: + seata: + tx-service-group: test_tx_group + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://125.32.114.204:13306/ebtp-cloud?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + username: mall3-ebtp-dev + password: mall3-ebtp-dev diff --git a/examples/seata-example/order-service/src/main/resources/application.yml b/examples/seata-example/order-service/src/main/resources/application.yml new file mode 100644 index 0000000..606750a --- /dev/null +++ b/examples/seata-example/order-service/src/main/resources/application.yml @@ -0,0 +1,5 @@ +spring: + profiles: + active: dev + application: + name: order-service \ No newline at end of file diff --git a/examples/seata-example/order-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/order/AppTest.java b/examples/seata-example/order-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/order/AppTest.java new file mode 100644 index 0000000..715c181 --- /dev/null +++ b/examples/seata-example/order-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/order/AppTest.java @@ -0,0 +1,23 @@ +package com.chinaunicom.mall.ebtp.cloud.order; + +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 com.chinaunicom.mall.ebtp.cloud.order.entity.Order; +import com.chinaunicom.mall.ebtp.cloud.order.mapper.OrderMapper; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class AppTest { + private @Autowired OrderMapper orderMapper; + +// @Test + public void testInsert() { + Order order = new Order(); + + orderMapper.insert(order); + } +} diff --git a/examples/seata-example/pom.xml b/examples/seata-example/pom.xml new file mode 100644 index 0000000..9668844 --- /dev/null +++ b/examples/seata-example/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + com.chinaunicom.ebtp + mall-ebtp-cloud-parent + 0.0.1 + + + com.chinaunicom.mall.ebtp.cloud + seata-example + 0.0.1-SNAPSHOT + pom + + seata-example + http://maven.apache.org + + + UTF-8 + + + + + com.chinaunicom.ebtp + mall-ebtp-cloud-eureka-starter + + + com.chinaunicom.ebtp + mall-ebtp-cloud-jpa-starter + + + com.chinaunicom.ebtp + mall-ebtp-cloud-feign-starter + + + mysql + mysql-connector-java + + + com.alibaba.cloud + spring-cloud-alibaba-seata + + + seata-all + io.seata + + + + + io.seata + seata-all + + + + storage-service + order-service + account-service + + \ No newline at end of file diff --git a/examples/seata-example/storage-service/pom.xml b/examples/seata-example/storage-service/pom.xml new file mode 100644 index 0000000..ba2aab1 --- /dev/null +++ b/examples/seata-example/storage-service/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.chinaunicom.mall.ebtp.cloud + seata-example + 0.0.1-SNAPSHOT + + com.chinaunicom.mall.ebtp.cloud + storage-service + 0.0.1-SNAPSHOT + storage-service + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/StorageSeataApplication.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/StorageSeataApplication.java new file mode 100644 index 0000000..b55f569 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/StorageSeataApplication.java @@ -0,0 +1,18 @@ +package com.chinaunicom.mall.ebtp.cloud.storage; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Import; + +import com.chinaunicom.mall.ebtp.cloud.eureka.starter.EurekaStarterConfiguration; + +@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) +@EnableFeignClients +@Import(EurekaStarterConfiguration.class) +public class StorageSeataApplication { + public static void main(String[] args) { + SpringApplication.run(StorageSeataApplication.class, args); + } +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/config/SeataDatasourceConfiguration.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/config/SeataDatasourceConfiguration.java new file mode 100644 index 0000000..e797709 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/config/SeataDatasourceConfiguration.java @@ -0,0 +1,42 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.config; + +import javax.sql.DataSource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.transaction.SpringManagedTransactionFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import com.alibaba.druid.pool.DruidDataSource; + +import io.seata.rm.datasource.DataSourceProxy; + +@Configuration +public class SeataDatasourceConfiguration { + + @Bean + @ConfigurationProperties(prefix = "spring.datasource") + public DataSource druidDataSource() { + return new DruidDataSource(); + } + + @Primary + @Bean("dataSource") + public DataSourceProxy dataSource(DataSource druidDataSource) { + return new DataSourceProxy(druidDataSource); + } + + @Bean + public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception { + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + sqlSessionFactoryBean.setDataSource(dataSourceProxy); + sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); + + return sqlSessionFactoryBean.getObject(); + + } + +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/controller/StorageController.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/controller/StorageController.java new file mode 100644 index 0000000..54774f2 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/controller/StorageController.java @@ -0,0 +1,22 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.chinaunicom.mall.ebtp.cloud.storage.service.StorageService; + +@RestController +@RequestMapping("storage") +public class StorageController { + + private @Autowired StorageService storageService; + + @RequestMapping("decrease") + public String decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count) { + storageService.decrease(productId, count); + return "Decrease Storage success"; + } + +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/entity/Storage.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/entity/Storage.java new file mode 100644 index 0000000..ac2892c --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/entity/Storage.java @@ -0,0 +1,19 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@TableName +@Accessors(chain = true) +public class Storage { + + private Long id; + private Long productId; + private Integer total; + private Integer used; + private Integer residue; + +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/mapper/StorageMapper.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/mapper/StorageMapper.java new file mode 100644 index 0000000..6469791 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/mapper/StorageMapper.java @@ -0,0 +1,16 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chinaunicom.mall.ebtp.cloud.storage.entity.Storage; + +@Mapper +public interface StorageMapper extends BaseMapper { + + @Update("UPDATE storage SET used = used + #{count}, residue = residue - #{count} WHERE product_id = #{productId}") + void decrease(@Param("productId") Long productId, @Param("count") Integer count); + +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/StorageService.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/StorageService.java new file mode 100644 index 0000000..7abb4ec --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/StorageService.java @@ -0,0 +1,7 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.service; + +public interface StorageService { + + void decrease(Long productId, Integer count); + +} diff --git a/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/impl/StorageServiceImpl.java b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/impl/StorageServiceImpl.java new file mode 100644 index 0000000..ca361f0 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/java/com/chinaunicom/mall/ebtp/cloud/storage/service/impl/StorageServiceImpl.java @@ -0,0 +1,24 @@ +package com.chinaunicom.mall.ebtp.cloud.storage.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.chinaunicom.mall.ebtp.cloud.storage.mapper.StorageMapper; +import com.chinaunicom.mall.ebtp.cloud.storage.service.StorageService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class StorageServiceImpl implements StorageService { + + private @Autowired StorageMapper storageMapper; + + @Override + public void decrease(Long productId, Integer count) { + log.info("------->扣减库存开始"); + storageMapper.decrease(productId, count); + log.info("------->扣减库存结束"); + } + +} diff --git a/examples/seata-example/storage-service/src/main/resources/application-dev.yml b/examples/seata-example/storage-service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..17b4e62 --- /dev/null +++ b/examples/seata-example/storage-service/src/main/resources/application-dev.yml @@ -0,0 +1,18 @@ +logging: + level: + com.chinaunicom.mall.ebtp.cloud: info + +server: + port: 8674 + +spring: + cloud: + alibaba: + seata: + tx-service-group: test_tx_group + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://125.32.114.204:13306/ebtp_mall_evaluation?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + username: mall3-ebtp-dev + password: mall3-ebtp-dev diff --git a/examples/seata-example/storage-service/src/main/resources/application.yml b/examples/seata-example/storage-service/src/main/resources/application.yml new file mode 100644 index 0000000..cd51a7a --- /dev/null +++ b/examples/seata-example/storage-service/src/main/resources/application.yml @@ -0,0 +1,5 @@ +spring: + profiles: + active: dev + application: + name: storage-service \ No newline at end of file diff --git a/examples/seata-example/storage-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/storage/AppTest.java b/examples/seata-example/storage-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/storage/AppTest.java new file mode 100644 index 0000000..2162ea7 --- /dev/null +++ b/examples/seata-example/storage-service/src/test/java/com/chinaunicom/mall/ebtp/cloud/storage/AppTest.java @@ -0,0 +1,38 @@ +package com.chinaunicom.mall.ebtp.cloud.storage; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/mall-ebtp-cloud-feign-starter/src/main/resources/feign-configuration.properties b/mall-ebtp-cloud-feign-starter/src/main/resources/feign-configuration.properties index 2f48da2..9135922 100644 --- a/mall-ebtp-cloud-feign-starter/src/main/resources/feign-configuration.properties +++ b/mall-ebtp-cloud-feign-starter/src/main/resources/feign-configuration.properties @@ -1,2 +1,4 @@ # 默认开启熔断 -feign.hystrix.enabled=true \ No newline at end of file +feign.hystrix.enabled=true +feign.client.config.default.connectTimeout=5000 +feign.client.config.default.readTimeout=10000 \ No newline at end of file diff --git a/mall-ebtp-cloud-jpa-starter/src/main/resoureces/file.conf b/mall-ebtp-cloud-jpa-starter/src/main/resoureces/file.conf new file mode 100644 index 0000000..a37e3e2 --- /dev/null +++ b/mall-ebtp-cloud-jpa-starter/src/main/resoureces/file.conf @@ -0,0 +1,66 @@ +transport { + # tcp udt unix-domain-socket + type = "TCP" + #NIO NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the client batch send request enable + enableClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size,will not be used for UDT + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + reportSuccessEnable = false + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + } + undo { + dataValidation = true + logSerialization = "jackson" + logTable = "undo_log" + } + log { + exceptionRate = 100 + } +} \ No newline at end of file diff --git a/mall-ebtp-cloud-jpa-starter/src/main/resoureces/registry.conf b/mall-ebtp-cloud-jpa-starter/src/main/resoureces/registry.conf new file mode 100644 index 0000000..4694f23 --- /dev/null +++ b/mall-ebtp-cloud-jpa-starter/src/main/resoureces/registry.conf @@ -0,0 +1,17 @@ +registry { + type = "eureka" + + eureka { + serviceUrl = "http://192.168.40.17:12093/eureka/,http://192.168.40.17:18126/eureka/,http://192.168.40.17:28641/eureka/" + application = "default" + weight = "1" + } +} + +config { + type = "file" + + file { + name = "file.conf" + } +} diff --git a/mall-ebtp-cloud-parent/pom.xml b/mall-ebtp-cloud-parent/pom.xml index 3ce3561..19ed992 100644 --- a/mall-ebtp-cloud-parent/pom.xml +++ b/mall-ebtp-cloud-parent/pom.xml @@ -25,6 +25,7 @@ 1.1.14 2.0.3 5.4.1 + 1.3.0 @@ -49,11 +50,11 @@ unifast-storage 1.0.0 - - p6spy - p6spy - 3.8.5 - + + p6spy + p6spy + 3.8.5 + commons-fileupload commons-fileupload @@ -193,6 +194,17 @@ apm-toolkit-trace 8.1.0 + + + com.alibaba.cloud + spring-cloud-alibaba-seata + 2.1.0.RELEASE + + + io.seata + seata-all + ${seata.version} +