增加 seata 示例
This commit is contained in:
25
examples/seata-example/account-service/pom.xml
Normal file
25
examples/seata-example/account-service/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>seata-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>account-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>account-service</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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<Account> {
|
||||
|
||||
@Update("UPDATE account SET residue = residue - #{money}, used = used + #{money} WHERE user_id = #{userId}")
|
||||
void decrease(@Param("userId") Long userId, @Param("money") BigDecimal money);
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -0,0 +1,6 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: account-service
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
25
examples/seata-example/order-service/pom.xml
Normal file
25
examples/seata-example/order-service/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>seata-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>order-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>order-service</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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 "订单状态修改成功";
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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<Order> {
|
||||
|
||||
@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);
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -0,0 +1,5 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: order-service
|
@ -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);
|
||||
}
|
||||
}
|
59
examples/seata-example/pom.xml
Normal file
59
examples/seata-example/pom.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.chinaunicom.ebtp</groupId>
|
||||
<artifactId>mall-ebtp-cloud-parent</artifactId>
|
||||
<version>0.0.1</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>seata-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>seata-example</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.chinaunicom.ebtp</groupId>
|
||||
<artifactId>mall-ebtp-cloud-eureka-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.chinaunicom.ebtp</groupId>
|
||||
<artifactId>mall-ebtp-cloud-jpa-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.chinaunicom.ebtp</groupId>
|
||||
<artifactId>mall-ebtp-cloud-feign-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-seata</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>seata-all</artifactId>
|
||||
<groupId>io.seata</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-all</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<modules>
|
||||
<module>storage-service</module>
|
||||
<module>order-service</module>
|
||||
<module>account-service</module>
|
||||
</modules>
|
||||
</project>
|
24
examples/seata-example/storage-service/pom.xml
Normal file
24
examples/seata-example/storage-service/pom.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>seata-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.chinaunicom.mall.ebtp.cloud</groupId>
|
||||
<artifactId>storage-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>storage-service</name>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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<Storage> {
|
||||
|
||||
@Update("UPDATE storage SET used = used + #{count}, residue = residue - #{count} WHERE product_id = #{productId}")
|
||||
void decrease(@Param("productId") Long productId, @Param("count") Integer count);
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.storage.service;
|
||||
|
||||
public interface StorageService {
|
||||
|
||||
void decrease(Long productId, Integer count);
|
||||
|
||||
}
|
@ -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("------->扣减库存结束");
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -0,0 +1,5 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: storage-service
|
@ -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 );
|
||||
}
|
||||
}
|
@ -1,2 +1,4 @@
|
||||
# 默认开启熔断
|
||||
feign.hystrix.enabled=true
|
||||
feign.hystrix.enabled=true
|
||||
feign.client.config.default.connectTimeout=5000
|
||||
feign.client.config.default.readTimeout=10000
|
66
mall-ebtp-cloud-jpa-starter/src/main/resoureces/file.conf
Normal file
66
mall-ebtp-cloud-jpa-starter/src/main/resoureces/file.conf
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
<druid.version>1.1.14</druid.version>
|
||||
<sharding-jdbc-core.version>2.0.3</sharding-jdbc-core.version>
|
||||
<hutool.version>5.4.1</hutool.version>
|
||||
<seata.version>1.3.0</seata.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -49,11 +50,11 @@
|
||||
<artifactId>unifast-storage</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>p6spy</groupId>
|
||||
<artifactId>p6spy</artifactId>
|
||||
<version>3.8.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>p6spy</groupId>
|
||||
<artifactId>p6spy</artifactId>
|
||||
<version>3.8.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
@ -193,6 +194,17 @@
|
||||
<artifactId>apm-toolkit-trace</artifactId>
|
||||
<version>8.1.0</version>
|
||||
</dependency>
|
||||
<!--seata -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-seata</artifactId>
|
||||
<version>2.1.0.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-all</artifactId>
|
||||
<version>${seata.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
Reference in New Issue
Block a user