项目重构

This commit is contained in:
yu199195 2018-03-01 16:45:40 +08:00
parent acb810f96a
commit 8457d8fb65
84 changed files with 1 additions and 6204 deletions

View File

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-dubbo</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-dubbo-account-api</artifactId>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-annotation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>happylifeplat-tcc-demo-dubbo-account-api</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account.api.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@Data
public class AccountDTO implements Serializable {
private static final long serialVersionUID = 7223470850578998427L;
/**
* 用户id
*/
private String userId;
/**
* 扣款金额
*/
private BigDecimal amount;
}

View File

@ -1,48 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account.api.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Data
public class AccountDO implements Serializable {
private static final long serialVersionUID = -81849676368907419L;
private Integer id;
private String userId;
private BigDecimal balance;
private BigDecimal freezeAmount;
private Date createTime;
private Date updateTime;
}

View File

@ -1,47 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account.api.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.dubbo.account.api.dto.AccountDTO;
import com.happylifeplat.tcc.demo.dubbo.account.api.entity.AccountDO;
/**
* @author xiaoyu
*/
public interface AccountService {
/**
* 扣款支付
*
* @param accountDTO 参数dto
* @return true
*/
@Tcc
boolean payment(AccountDTO accountDTO);
/**
* 获取用户账户信息
* @param userId 用户id
* @return AccountDO
*/
AccountDO findByUserId(String userId);
}

View File

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-dubbo</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-dubbo-account</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-demo-dubbo-account-api</artifactId>
</dependency>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-dubbo</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,38 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.dubbo.account.mapper")
public class DubboTccAccountApplication {
public static void main(String[] args) {
SpringApplication.run(DubboTccAccountApplication.class, args);
}
}

View File

@ -1,74 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account.mapper;
import com.happylifeplat.tcc.demo.dubbo.account.api.entity.AccountDO;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author xiaoyu
*/
public interface AccountMapper {
/**
* 扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set balance =#{balance}," +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and balance > 0 ")
int update(AccountDO accountDO);
/**
* 确认扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set " +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and freeze_amount >0 ")
int confirm(AccountDO accountDO);
/**
* 取消扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set balance =#{balance}," +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and freeze_amount >0")
int cancel(AccountDO accountDO);
/**
* 根据userId获取用户账户信息
*
* @param userId 用户id
* @return AccountDO
*/
@Select("select * from account where user_id =#{userId}")
AccountDO findByUserId(String userId);
}

View File

@ -1,113 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.account.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.annotation.TccPatternEnum;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.dubbo.account.api.dto.AccountDTO;
import com.happylifeplat.tcc.demo.dubbo.account.api.entity.AccountDO;
import com.happylifeplat.tcc.demo.dubbo.account.api.service.AccountService;
import com.happylifeplat.tcc.demo.dubbo.account.mapper.AccountMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* @author xiaoyu
*/
@Service("accountService")
public class AccountServiceImpl implements AccountService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);
private final AccountMapper accountMapper;
@Autowired(required = false)
public AccountServiceImpl(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
/**
* 扣款支付
*
* @param accountDTO 参数dto
* @return true
*/
@Override
@Tcc(confirmMethod = "confirm", cancelMethod = "cancel")
public boolean payment(AccountDTO accountDTO) {
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().subtract(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().add(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int update = accountMapper.update(accountDO);
if (update != 1) {
throw new TccRuntimeException("资金不足!");
}
return Boolean.TRUE;
}
/**
* 获取用户账户信息
*
* @param userId 用户id
* @return AccountDO
*/
@Override
public AccountDO findByUserId(String userId) {
return accountMapper.findByUserId(userId);
}
public boolean confirm(AccountDTO accountDTO) {
LOGGER.debug("============dubbo tcc 执行确认付款接口===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int rows = accountMapper.confirm(accountDO);
if(rows!=1){
throw new TccRuntimeException("确认扣减账户异常!");
}
return Boolean.TRUE;
}
public boolean cancel(AccountDTO accountDTO) {
LOGGER.debug("============ dubbo tcc 执行取消付款接口===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().add(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int rows = accountMapper.cancel(accountDO);
if(rows!=1){
throw new TccRuntimeException("取消扣减账户异常!");
}
return Boolean.TRUE;
}
}

View File

@ -1,29 +0,0 @@
server:
port: 8085
contextPath: /
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_account?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.dubbo.account.api.entity
config-location: classpath:mybatis/mybatis-config.xml
logging:
level:
root: error
org.springframework.web: info
org.apache.ibatis: info
com.happylifeplat.tcc.bonuspoint: info
com.happylifeplat.tcc.lottery: debug
com.happylifeplat.tcc: debug
io.netty: info
path: "./logs"

View File

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="4"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="3"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="repositorySupport" value="db"/>
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
</bean>
<import resource="spring-dubbo.xml"/>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/account?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/account"/>
<property name="prefix" value="account"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="account_service"/>
<dubbo:registry protocol="zookeeper" address="192.168.1.148:2181"/>
<dubbo:protocol accesslog="true" name="dubbo" port="20884"/>
<dubbo:service interface="com.happylifeplat.tcc.demo.dubbo.account.api.service.AccountService"
ref="accountService"/>
</beans>

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-dubbo</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-dubbo-inventory-api</artifactId>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-annotation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>happylifeplat-tcc-demo-dubbo-inventory-api</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,46 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author xiaoyu
*/
@Data
public class InventoryDTO implements Serializable {
private static final long serialVersionUID = 8229355519336565493L;
/**
* 商品id
*/
private String productId;
/**
* 数量
*/
private Integer count;
}

View File

@ -1,49 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory.api.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author xiaoyu
*/
@Data
public class InventoryDO implements Serializable {
private static final long serialVersionUID = 6957734749389133832L;
private Integer id;
/**
* 商品id
*/
private String productId;
/**
* 总库存
*/
private Integer totalInventory;
/**
* 锁定库存
*/
private Integer lockInventory;
}

View File

@ -1,90 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory.api.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.entity.InventoryDO;
/**
* @author xiaoyu
*/
public interface InventoryService {
/**
* 扣减库存操作
* 这一个tcc接口
*
* @param inventoryDTO 库存DTO对象
* @return true
*/
@Tcc
Boolean decrease(InventoryDTO inventoryDTO);
/**
* 获取商品库存信息
* @param productId 商品id
* @return InventoryDO
*/
InventoryDO findByProductId(String productId);
/**
* mock扣减库存异常
*
* @param inventoryDTO dto对象
* @return String
*/
@Tcc
String mockWithTryException(InventoryDTO inventoryDTO);
/**
* mock扣减库存超时
*
* @param inventoryDTO dto对象
* @return String
*/
@Tcc
Boolean mockWithTryTimeout(InventoryDTO inventoryDTO);
/**
* mock 扣减库存confirm异常
*
* @param inventoryDTO dto对象
* @return String
*/
@Tcc
String mockWithConfirmException(InventoryDTO inventoryDTO);
/**
* mock 扣减库存confirm超时
*
* @param inventoryDTO dto对象
* @return True
*/
@Tcc
Boolean mockWithConfirmTimeout(InventoryDTO inventoryDTO);
}

View File

@ -1,151 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-dubbo</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-dubbo-inventory</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-demo-dubbo-inventory-api</artifactId>
</dependency>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-dubbo</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,38 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.dubbo.inventory.mapper")
public class DubboTccInventoryApplication {
public static void main(String[] args) {
SpringApplication.run(DubboTccInventoryApplication.class, args);
}
}

View File

@ -1,75 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory.mapper;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.entity.InventoryDO;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author xiaoyu
*/
public interface InventoryMapper {
/**
* 库存扣减
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set total_inventory =#{totalInventory}," +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and total_inventory >0 ")
int decrease(InventoryDO inventory);
/**
* 库存扣减confirm
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set " +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and lock_inventory >0 ")
int confirm(InventoryDO inventory);
/**
* 库存扣减 cancel
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set total_inventory =#{totalInventory}," +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and lock_inventory >0 ")
int cancel(InventoryDO inventory);
/**
* 根据商品id找到库存信息
*
* @param productId 商品id
* @return Inventory
*/
@Select("select * from inventory where product_id =#{productId}")
InventoryDO findByProductId(String productId);
}

View File

@ -1,230 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.inventory.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.entity.InventoryDO;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.service.InventoryService;
import com.happylifeplat.tcc.demo.dubbo.inventory.mapper.InventoryMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author xiaoyu
*/
@Service("inventoryService")
public class InventoryServiceImpl implements InventoryService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(InventoryServiceImpl.class);
private final InventoryMapper inventoryMapper;
@Autowired(required = false)
public InventoryServiceImpl(InventoryMapper inventoryMapper) {
this.inventoryMapper = inventoryMapper;
}
/**
* 扣减库存操作
* 这一个tcc接口
*
* @param inventoryDTO 库存DTO对象
* @return true
*/
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
public Boolean decrease(InventoryDTO inventoryDTO) {
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
}
/**
* 获取商品库存信息
*
* @param productId 商品id
* @return InventoryDO
*/
@Override
public InventoryDO findByProductId(String productId) {
return inventoryMapper.findByProductId(productId);
}
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
public String mockWithTryException(InventoryDTO inventoryDTO) {
//这里是模拟异常所以就直接抛出异常了
throw new TccRuntimeException("库存扣减异常!");
}
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
@Transactional(rollbackFor = Exception.class)
public Boolean mockWithTryTimeout(InventoryDTO inventoryDTO) {
try {
//模拟延迟 当前线程暂停10秒
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
}
@Override
@Tcc(confirmMethod = "confirmMethodException", cancelMethod = "cancelMethod")
@Transactional(rollbackFor = Exception.class)
public String mockWithConfirmException(InventoryDTO inventoryDTO) {
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return "success";
}
@Override
@Tcc(confirmMethod = "confirmMethodTimeout", cancelMethod = "cancelMethod")
@Transactional(rollbackFor = Exception.class)
public Boolean mockWithConfirmTimeout(InventoryDTO inventoryDTO) {
LOGGER.info("==========调用扣减库存确认方法mockWithConfirmTimeout===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
}
@Transactional(rollbackFor = Exception.class)
public Boolean confirmMethodTimeout(InventoryDTO inventoryDTO) {
try {
//模拟延迟 当前线程暂停11秒
Thread.sleep(11000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("==========调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
inventoryMapper.decrease(entity);
return true;
}
@Transactional(rollbackFor = Exception.class)
public Boolean confirmMethodException(InventoryDTO inventoryDTO) {
LOGGER.info("==========调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
// throw new TccRuntimeException("库存扣减确认异常!");
}
@Transactional(rollbackFor = Exception.class)
public Boolean confirmMethod(InventoryDTO inventoryDTO) {
LOGGER.info("==========调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
final int rows = inventoryMapper.confirm(entity);
if (rows != 1) {
throw new TccRuntimeException("确认库存操作失败!");
}
return true;
}
@Transactional(rollbackFor = Exception.class)
public Boolean cancelMethod(InventoryDTO inventoryDTO) {
LOGGER.info("==========调用扣减库存取消方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() + inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
int rows = inventoryMapper.cancel(entity);
if (rows != 1) {
throw new TccRuntimeException("取消库存操作失败!");
}
return true;
}
}

View File

@ -1,29 +0,0 @@
server:
port: 8084
contextPath: /
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_stock?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.dubbo.inventory.api.entity
config-location: classpath:mybatis/mybatis-config.xml
logging:
level:
root: error
org.springframework.web: info
org.apache.ibatis: info
com.happylifeplat.bonuspoint: info
com.happylifeplat.lottery: debug
com.happylifeplat: debug
io.netty: info
path: "./logs"

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="4"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="3"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="repositorySupport" value="db"/>
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
</bean>
<import resource="spring-dubbo.xml"/>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/stock?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/inventory"/>
<property name="prefix" value="inventory"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="inventory_service"/>
<dubbo:registry protocol="zookeeper" address="192.168.1.148:2181"/>
<dubbo:protocol accesslog="true" name="dubbo" port="20885"/>
<dubbo:service interface="com.happylifeplat.tcc.demo.dubbo.inventory.api.service.InventoryService"
ref="inventoryService"/>
</beans>

View File

@ -1,187 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-dubbo</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-dubbo-order</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-demo-dubbo-inventory-api</artifactId>
</dependency>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-demo-dubbo-account-api</artifactId>
</dependency>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-dubbo</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.happylifeplat.tcc.demo.dubbo.order.DubboTccOrderApplication</mainClass>
<executable>true</executable>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,38 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.dubbo.order.mapper")
public class DubboTccOrderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboTccOrderApplication.class, args);
}
}

View File

@ -1,72 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.time.LocalDate;
import static com.google.common.collect.Lists.newArrayList;
/**
* @author xiaoyu
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
private static final String SWAGGER_SCAN_BASE_PACKAGE = "com.happylifeplat.tcc.demo.dubbo.order.controller";
private static final String VERSION = "1.0.0";
ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("dubbo分布式事务解决方案之TCC测试体验")
.license("Apache 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.termsOfServiceUrl("")
.version(VERSION)
.contact(new Contact("xiaoyu", "", "549477611@qq.com"))
.build();
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
// .paths(paths())
.build().pathMapping("/").directModelSubstitute(LocalDate.class, String.class)
.genericModelSubstitutes(ResponseEntity.class).useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder().code(500).message("500 message")
.responseModel(new ModelRef("Error")).build()));
}
}

View File

@ -1,87 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.controller;
import com.happylifeplat.tcc.demo.dubbo.order.service.OrderService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@RestController
@RequestMapping("/order")
public class OrderController {
private final OrderService orderService;
@Autowired
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping(value = "/orderPay")
@ApiOperation(value = "订单支付接口(注意这里模拟的是创建订单并进行支付扣减库存等操作)")
public String orderPay(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.orderPay(count, amount);
}
@PostMapping(value = "/mockInventoryWithTryException")
@ApiOperation(value = "模拟下单付款操作在try阶段异常此时账户系统和订单状态会回滚达到数据的一致性注意:这里模拟的是系统异常或者rpc异常")
public String mockInventoryWithTryException(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithTryException(count, amount);
}
@PostMapping(value = "/mockInventoryWithTryTimeout")
@ApiOperation(value = "模拟下单付款操作在try阶段超时异常此时账户系统和订单状态会回滚达到数据的一致性异常指的是超时异常")
public String mockInventoryWithTryTimeout(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithTryTimeout(count, amount);
}
/*@PostMapping(value = "/mockInventoryWithConfirmException")
@ApiOperation(value = "模拟下单付款操作在Confirm阶段异常此时所有的系统调用都会执行cancel方法达到数据的一致性注意:这里模拟的是系统异常或者rpc异常")
public String mockInventoryWithConfirmException(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithConfirmException(count,amount);
}
@PostMapping(value = "/mockInventoryWithConfirmTimeout")
@ApiOperation(value = "模拟下单付款操作在Confirm阶段异常此时所有的系统调用都会执行cancel方法达到数据的一致性异常指的是超时异常")
public String mockInventoryWithConfirmTimeout(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithConfirmTimeout(count,amount);
}*/
}

View File

@ -1,73 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Data
public class Order implements Serializable {
private static final long serialVersionUID = -8551347266419380333L;
private Integer id;
/**
* 创建时间
*/
private Date createTime;
/**
* 订单编号
*/
private String number;
/**
* 订单状态
*/
private Integer status;
/**
* 商品id
*/
private String productId;
/**
* 付款金额
*/
private BigDecimal totalAmount;
/**
* 购买数量
*/
private Integer count;
/**
* 购买人
*/
private String userId;
}

View File

@ -1,93 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.enums;
/**
* The enum Order status enum.
*
* @author xiaoyu
*/
public enum OrderStatusEnum {
/**
* Not pay order status enum.
*/
NOT_PAY(1, "未支付"),
/**
* Paying order status enum.
*/
PAYING(2, "支付中"),
/**
* Pay fail order status enum.
*/
PAY_FAIL(3, "支付失败"),
/**
* Pay success order status enum.
*/
PAY_SUCCESS(4, "支付成功");
private int code;
private String desc;
OrderStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* Gets code.
*
* @return the code
*/
public int getCode() {
return code;
}
/**
* Sets code.
*
* @param code the code
*/
public void setCode(int code) {
this.code = code;
}
/**
* Gets desc.
*
* @return the desc
*/
public String getDesc() {
return desc;
}
/**
* Sets desc.
*
* @param desc the desc
*/
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@ -1,60 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.mapper;
import com.happylifeplat.tcc.demo.dubbo.order.entity.Order;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/**
* @author xiaoyu
*/
public interface OrderMapper {
/**
* 保存订单
*
* @param order 订单对象
* @return rows
*/
@Insert(" insert into `order` (create_time,number,status,product_id,total_amount,count,user_id) " +
" values ( #{createTime},#{number},#{status},#{productId},#{totalAmount},#{count},#{userId})")
int save(Order order);
/**
* 更新订单
*
* @param order 订单对象
* @return rows
*/
@Update("update `order` set status = #{status} , total_amount=#{totalAmount} where number=#{number}")
int update(Order order);
/**
* 获取所有的订单
*
* @return List<Order>
*/
@Select("select * from order")
List<Order> listAll();
}

View File

@ -1,86 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.service;
import com.happylifeplat.tcc.demo.dubbo.order.entity.Order;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
public interface OrderService {
/**
* 创建订单并且进行扣除账户余额支付并进行库存扣减操作
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String orderPay(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在try阶段中的库存异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithTryException(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在try阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithTryTimeout(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在Confirm阶段中的异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithConfirmException(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在Confirm阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithConfirmTimeout(Integer count, BigDecimal amount);
/**
* 更新订单状态
*
* @param order 订单实体类
*/
void updateOrderStatus(Order order);
}

View File

@ -1,70 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.service;
import com.happylifeplat.tcc.demo.dubbo.order.entity.Order;
/**
* @author xiaoyu
*/
public interface PaymentService {
/**
* 订单支付
*
* @param order 订单实体
*/
void makePayment(Order order);
/**
* mock订单支付的时候库存异常
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithTryException(Order order);
/**
* mock订单支付的时候库存超时
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithTryTimeout(Order order);
/**
* mock订单支付的时候库存确认异常
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithConfirmException(Order order);
/**
* mock订单支付的时候库存确认超时
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithConfirmTimeout(Order order);
}

View File

@ -1,172 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.service.impl;
import com.happylifeplat.tcc.common.utils.IdWorkerUtils;
import com.happylifeplat.tcc.demo.dubbo.order.entity.Order;
import com.happylifeplat.tcc.demo.dubbo.order.enums.OrderStatusEnum;
import com.happylifeplat.tcc.demo.dubbo.order.mapper.OrderMapper;
import com.happylifeplat.tcc.demo.dubbo.order.service.OrderService;
import com.happylifeplat.tcc.demo.dubbo.order.service.PaymentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Service("orderService")
public class OrderServiceImpl implements OrderService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);
private final OrderMapper orderMapper;
private final PaymentService paymentService;
@Autowired(required = false)
public OrderServiceImpl(OrderMapper orderMapper,
PaymentService paymentService) {
this.orderMapper = orderMapper;
this.paymentService = paymentService;
}
@Override
public String orderPay(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.makePayment(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在try阶段中的库存异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithTryException(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithTryException(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在try阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithTryTimeout(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithTryTimeout(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在Confirm阶段中的异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithConfirmException(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithConfirmException(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在Confirm阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithConfirmTimeout(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithConfirmTimeout(order);
}
return "success";
}
@Override
public void updateOrderStatus(Order order) {
orderMapper.update(order);
}
private Order buildOrder(Integer count, BigDecimal amount) {
Order order = new Order();
order.setCreateTime(new Date());
order.setNumber(IdWorkerUtils.getInstance().buildPartNumber());
//demo中的表里只有商品id为1的数据
order.setProductId("1");
order.setStatus(OrderStatusEnum.NOT_PAY.getCode());
order.setTotalAmount(amount);
order.setCount(count);
//demo中 表里面存的用户id为10000
order.setUserId("10000");
return order;
}
}

View File

@ -1,190 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.dubbo.order.service.impl;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.dubbo.account.api.dto.AccountDTO;
import com.happylifeplat.tcc.demo.dubbo.account.api.entity.AccountDO;
import com.happylifeplat.tcc.demo.dubbo.account.api.service.AccountService;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.entity.InventoryDO;
import com.happylifeplat.tcc.demo.dubbo.inventory.api.service.InventoryService;
import com.happylifeplat.tcc.demo.dubbo.order.entity.Order;
import com.happylifeplat.tcc.demo.dubbo.order.enums.OrderStatusEnum;
import com.happylifeplat.tcc.demo.dubbo.order.mapper.OrderMapper;
import com.happylifeplat.tcc.demo.dubbo.order.service.OrderService;
import com.happylifeplat.tcc.demo.dubbo.order.service.PaymentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author xiaoyu
*/
@Service
public class PaymentServiceImpl implements PaymentService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PaymentServiceImpl.class);
private final OrderMapper orderMapper;
private final AccountService accountService;
private final InventoryService inventoryService;
@Autowired(required = false)
public PaymentServiceImpl(OrderMapper orderMapper,
AccountService accountService,
InventoryService inventoryService) {
this.orderMapper = orderMapper;
this.accountService = accountService;
this.inventoryService = inventoryService;
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public void makePayment(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//做库存和资金账户的检验工作 这里只是demo
final AccountDO accountDO = accountService.findByUserId(order.getUserId());
if (accountDO.getBalance().compareTo(order.getTotalAmount()) <= 0) {
throw new TccRuntimeException("余额不足!");
}
final InventoryDO inventory = inventoryService.findByProductId(order.getProductId());
if (inventory.getTotalInventory() < order.getCount()) {
throw new TccRuntimeException("库存不足!");
}
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountService.payment(accountDTO);
//进入扣减库存操作
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryService.decrease(inventoryDTO);
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithTryException(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountService.payment(accountDTO);
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryService.mockWithTryException(inventoryDTO);
return "success";
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithTryTimeout(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountService.payment(accountDTO);
//进入扣减库存操作
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryService.mockWithTryTimeout(inventoryDTO);
return "success";
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithConfirmException(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountService.payment(accountDTO);
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryService.mockWithConfirmException(inventoryDTO);
return "success";
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithConfirmTimeout(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountService.payment(accountDTO);
inventoryService.mockWithConfirmTimeout(new InventoryDTO());
return "success";
}
public void confirmOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_SUCCESS.getCode());
orderMapper.update(order);
LOGGER.info("=========进行订单confirm操作完成================");
}
public void cancelOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_FAIL.getCode());
orderMapper.update(order);
LOGGER.info("=========进行订单cancel操作完成================");
}
}

View File

@ -1,29 +0,0 @@
server:
port: 8083
contextPath: /
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_order?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.dubbo.order.entity
config-location: classpath:mybatis/mybatis-config.xml
logging:
level:
root: error
org.springframework.web: info
org.apache.ibatis: info
com.happylifeplat.bonuspoint: debug
com.happylifeplat.lottery: debug
com.happylifeplat: debug
io.netty: info
path: "./logs"

View File

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="8"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="30"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="repositorySupport" value="db"/>
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
</bean>
<import resource="spring-dubbo.xml"/>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/order?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/order"/>
<property name="prefix" value="order"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="order_service"/>
<dubbo:registry protocol="zookeeper" address="192.168.1.148:2181"/>
<dubbo:protocol accesslog="true" name="dubbo" port="20886"/>
<dubbo:reference timeout="10000"
interface="com.happylifeplat.tcc.demo.dubbo.inventory.api.service.InventoryService"
id="inventoryService"
retries="0" check="false"/>
<dubbo:reference timeout="10000"
interface="com.happylifeplat.tcc.demo.dubbo.account.api.service.AccountService"
id="accountService"
retries="0" check="false"/>
</beans>

View File

@ -1,135 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-springcloud</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-springcloud-account</artifactId>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-springcloud</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@EnableDiscoveryClient
@EnableFeignClients
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.springcloud.account.mapper")
public class SpringcloudTccAccountApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudTccAccountApplication.class, args);
}
}

View File

@ -1,60 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.controller;
import com.happylifeplat.tcc.demo.springcloud.account.dto.AccountDTO;
import com.happylifeplat.tcc.demo.springcloud.account.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
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 java.math.BigDecimal;
/**
* @author xiaoyu
*/
@RestController
@RequestMapping("/account")
public class AccountController {
private final AccountService accountService;
@Autowired
public AccountController(AccountService accountService) {
this.accountService = accountService;
}
@RequestMapping("/payment")
public Boolean save(@RequestBody AccountDTO accountDO) {
return accountService.payment(accountDO);
}
@RequestMapping("/findByUserId")
public BigDecimal findByUserId(@RequestParam("userId") String userId) {
return accountService.findByUserId(userId).getBalance();
}
}

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@Data
public class AccountDTO implements Serializable {
private static final long serialVersionUID = 7223470850578998427L;
/**
* 用户id
*/
private String userId;
/**
* 扣款金额
*/
private BigDecimal amount;
}

View File

@ -1,46 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Data
public class AccountDO implements Serializable {
private static final long serialVersionUID = -81849676368907419L;
private Integer id;
private String userId;
private BigDecimal balance;
private BigDecimal freezeAmount;
private Date createTime;
private Date updateTime;
}

View File

@ -1,75 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.mapper;
import com.happylifeplat.tcc.demo.springcloud.account.entity.AccountDO;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author xiaoyu
*/
public interface AccountMapper {
/**
* 扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set balance =#{balance}," +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and balance > 0 ")
int update(AccountDO accountDO);
/**
* 确认扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set " +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and freeze_amount >0 ")
int confirm(AccountDO accountDO);
/**
* 取消扣减账户余额
*
* @param accountDO 实体类
* @return rows
*/
@Update("update account set balance =#{balance}," +
" freeze_amount= #{freezeAmount} ,update_time = #{updateTime}" +
" where user_id =#{userId} and freeze_amount >0")
int cancel(AccountDO accountDO);
/**
* 根据userId获取用户账户信息
*
* @param userId 用户id
* @return AccountDO
*/
@Select("select * from account where user_id =#{userId}")
AccountDO findByUserId(String userId);
}

View File

@ -1,47 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.springcloud.account.dto.AccountDTO;
import com.happylifeplat.tcc.demo.springcloud.account.entity.AccountDO;
/**
* @author xiaoyu
*/
public interface AccountService {
/**
* 扣款支付
*
* @param accountDTO 参数dto
* @return true
*/
@Tcc
boolean payment(AccountDTO accountDTO);
/**
* 获取用户账户信息
* @param userId 用户id
* @return AccountDO
*/
AccountDO findByUserId(String userId);
}

View File

@ -1,114 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.account.service.impl;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.springcloud.account.dto.AccountDTO;
import com.happylifeplat.tcc.demo.springcloud.account.entity.AccountDO;
import com.happylifeplat.tcc.demo.springcloud.account.mapper.AccountMapper;
import com.happylifeplat.tcc.demo.springcloud.account.service.AccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* @author xiaoyu
*/
@Service("accountService")
public class AccountServiceImpl implements AccountService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);
private final AccountMapper accountMapper;
@Autowired(required = false)
public AccountServiceImpl(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
/**
* 扣款支付
*
* @param accountDTO 参数dto
* @return true
*/
@Override
@Tcc(confirmMethod = "confirm", cancelMethod = "cancel")
public boolean payment(AccountDTO accountDTO) {
LOGGER.debug("============springcloud执行try付款接口===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().subtract(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().add(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int update = accountMapper.update(accountDO);
if (update != 1) {
throw new TccRuntimeException("资金不足!");
}
return Boolean.TRUE;
}
/**
* 获取用户账户信息
*
* @param userId 用户id
* @return AccountDO
*/
@Override
public AccountDO findByUserId(String userId) {
return accountMapper.findByUserId(userId);
}
public boolean confirm(AccountDTO accountDTO) {
LOGGER.debug("============springcloud tcc 执行确认付款接口===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int rows = accountMapper.confirm(accountDO);
if(rows!=1){
throw new TccRuntimeException("确认扣减账户异常!");
}
return Boolean.TRUE;
}
public boolean cancel(AccountDTO accountDTO) {
LOGGER.debug("============springcloud tcc 执行取消付款接口===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().add(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int rows = accountMapper.cancel(accountDO);
if(rows!=1){
throw new TccRuntimeException("取消扣减账户异常!");
}
return Boolean.TRUE;
}
}

View File

@ -1,47 +0,0 @@
server:
port: 8882
contextPath: /account-service
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_account?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
initialSize: 20
minIdle: 20
maxActive: 100
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,wall,slf4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
application:
name: account-service
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.springcloud.account.entity
config-location: classpath:mybatis/mybatis-config.xml
#${random.int[9000,9999]}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
account-service :
ribbon.NFLoadBalancerRuleClassName : com.netflix.loadbalancer.RandomRule
logging:
level:
root: info
com.happylifeplat.tcc : debug
path: "./logs"

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="16"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="3"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="xiaoyu"/>
<property name="password" value="Wgj@555888"/>
</bean>
</property>
</bean>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/account"/>
<property name="prefix" value="account"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-springcloud</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-springcloud-eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>happylifeplat-tcc-demo-springcloud-eureka</finalName>
</build>
</project>

View File

@ -1,36 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.eureka;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author xiaoyu
*/
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaServerApplication.class).web(true).run(args);
}
}

View File

@ -1,36 +0,0 @@
server:
port: 8761
spring:
application:
name: springcloud-eureka
eureka:
instance:
hostname: ${hostname:localhost}
preferIpAddress: true
lease-renewal-interval-in-seconds: 2
lease-expiration-duration-in-seconds: 6
server:
peerEurekaNodesUpdateIntervalMs: 60000
enableSelfPreservation: false
evictionIntervalTimerInMs: 5000
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:8761/eureka/
healthcheck:
enabled: true
eurekaServiceUrlPollIntervalSeconds: 60
endpoints:
health:
sensitive: false

View File

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-springcloud</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-springcloud-inventory</artifactId>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-springcloud</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@EnableEurekaClient
@EnableFeignClients
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.springcloud.inventory.mapper")
public class SpringCloudTccInventoryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudTccInventoryApplication.class, args);
}
}

View File

@ -1,68 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.controller;
import com.happylifeplat.tcc.demo.springcloud.inventory.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.springcloud.inventory.service.InventoryService;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @author xiaoyu
*/
@RestController
@RequestMapping("/inventory")
public class InventoryController {
private final InventoryService inventoryService;
@Autowired
public InventoryController(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
@RequestMapping("/decrease")
public Boolean decrease(@RequestBody InventoryDTO inventoryDTO) {
return inventoryService.decrease(inventoryDTO);
}
@RequestMapping("/findByProductId")
public Integer findByProductId(@RequestParam("productId") String productId) {
return inventoryService.findByProductId(productId).getTotalInventory();
}
@RequestMapping("/mockWithTryException")
public Boolean mockWithTryException(@RequestBody InventoryDTO inventoryDTO) {
return inventoryService.mockWithTryException(inventoryDTO);
}
@RequestMapping("/mockWithTryTimeout")
public Boolean mockWithTryTimeout(@RequestBody InventoryDTO inventoryDTO) {
return inventoryService.mockWithTryTimeout(inventoryDTO);
}
}

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author xiaoyu
*/
@Data
public class InventoryDTO implements Serializable {
private static final long serialVersionUID = 8229355519336565493L;
/**
* 商品id
*/
private String productId;
/**
* 数量
*/
private Integer count;
}

View File

@ -1,49 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author xiaoyu
*/
@Data
public class InventoryDO implements Serializable {
private static final long serialVersionUID = 6957734749389133832L;
private Integer id;
/**
* 商品id
*/
private String productId;
/**
* 总库存
*/
private Integer totalInventory;
/**
* 锁定库存
*/
private Integer lockInventory;
}

View File

@ -1,75 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.mapper;
import com.happylifeplat.tcc.demo.springcloud.inventory.entity.InventoryDO;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author xiaoyu
*/
public interface InventoryMapper {
/**
* 库存扣减
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set total_inventory =#{totalInventory}," +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and total_inventory >0 ")
int decrease(InventoryDO inventory);
/**
* 库存扣减confirm
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set " +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and lock_inventory >0 ")
int confirm(InventoryDO inventory);
/**
* 库存扣减 cancel
*
* @param inventory 实体对象
* @return rows
*/
@Update("update inventory set total_inventory =#{totalInventory}," +
" lock_inventory= #{lockInventory} " +
" where product_id =#{productId} and lock_inventory >0 ")
int cancel(InventoryDO inventory);
/**
* 根据商品id找到库存信息
*
* @param productId 商品id
* @return Inventory
*/
@Select("select * from inventory where product_id =#{productId}")
InventoryDO findByProductId(String productId);
}

View File

@ -1,71 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.service;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.springcloud.inventory.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.springcloud.inventory.entity.InventoryDO;
/**
* @author xiaoyu
*/
public interface InventoryService {
/**
* 扣减库存操作
* 这一个tcc接口
*
* @param inventoryDTO 库存DTO对象
* @return true
*/
@Tcc
Boolean decrease(InventoryDTO inventoryDTO);
/**
* 获取商品库存信息
* @param productId 商品id
* @return InventoryDO
*/
InventoryDO findByProductId(String productId);
/**
* mock 库存扣减try阶段异常
*
* @param inventoryDTO dto
* @return true
*/
@Tcc
Boolean mockWithTryException(InventoryDTO inventoryDTO);
/**
* mock 库存扣减try阶段超时
*
* @param inventoryDTO dto
* @return true
*/
@Tcc
Boolean mockWithTryTimeout(InventoryDTO inventoryDTO);
}

View File

@ -1,200 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.inventory.service.impl;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.springcloud.inventory.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.springcloud.inventory.entity.InventoryDO;
import com.happylifeplat.tcc.demo.springcloud.inventory.mapper.InventoryMapper;
import com.happylifeplat.tcc.demo.springcloud.inventory.service.InventoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author xiaoyu
*/
@Service("inventoryService")
public class InventoryServiceImpl implements InventoryService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(InventoryServiceImpl.class);
private final InventoryMapper inventoryMapper;
@Autowired(required = false)
public InventoryServiceImpl(InventoryMapper inventoryMapper) {
this.inventoryMapper = inventoryMapper;
}
/**
* 扣减库存操作
* 这一个tcc接口
*
* @param inventoryDTO 库存DTO对象
* @return true
*/
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
public Boolean decrease(InventoryDTO inventoryDTO) {
LOGGER.info("==========springcloud调用扣减库存decrease===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
}
/**
* 获取商品库存信息
*
* @param productId 商品id
* @return InventoryDO
*/
@Override
public InventoryDO findByProductId(String productId) {
return inventoryMapper.findByProductId(productId);
}
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
public Boolean mockWithTryException(InventoryDTO inventoryDTO) {
//这里是模拟异常所以就直接抛出异常了
throw new TccRuntimeException("库存扣减异常!");
}
@Override
@Tcc(confirmMethod = "confirmMethod", cancelMethod = "cancelMethod")
@Transactional(rollbackFor = Exception.class)
public Boolean mockWithTryTimeout(InventoryDTO inventoryDTO) {
try {
//模拟延迟 当前线程暂停10秒
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("==========springcloud调用扣减库存mockWithTryTimeout===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() - inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() + inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
}
@Transactional(rollbackFor = Exception.class)
public Boolean confirmMethodTimeout(InventoryDTO inventoryDTO) {
try {
//模拟延迟 当前线程暂停11秒
Thread.sleep(11000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("==========Springcloud调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
inventoryMapper.decrease(entity);
return true;
}
@Transactional(rollbackFor = Exception.class)
public Boolean confirmMethodException(InventoryDTO inventoryDTO) {
LOGGER.info("==========Springcloud调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
final int decrease = inventoryMapper.decrease(entity);
if (decrease != 1) {
throw new TccRuntimeException("库存不足");
}
return true;
// throw new TccRuntimeException("库存扣减确认异常!");
}
public Boolean confirmMethod(InventoryDTO inventoryDTO) {
LOGGER.info("==========Springcloud调用扣减库存确认方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
final int rows = inventoryMapper.confirm(entity);
if (rows != 1) {
throw new TccRuntimeException("确认库存操作失败!");
}
return true;
}
public Boolean cancelMethod(InventoryDTO inventoryDTO) {
LOGGER.info("==========Springcloud调用扣减库存取消方法===========");
final InventoryDO entity = inventoryMapper.findByProductId(inventoryDTO.getProductId());
entity.setTotalInventory(entity.getTotalInventory() + inventoryDTO.getCount());
entity.setLockInventory(entity.getLockInventory() - inventoryDTO.getCount());
int rows= inventoryMapper.cancel(entity);
if (rows != 1) {
throw new TccRuntimeException("取消库存操作失败!");
}
return true;
}
}

View File

@ -1,48 +0,0 @@
server:
port: 8883
contextPath: /inventory-service
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_stock?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
platform: mysql
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 20
minIdle: 20
maxActive: 100
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,wall,slf4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
application:
name: inventory-service
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.springcloud.inventory.entity
config-location: classpath:mybatis/mybatis-config.xml
#${random.int[9000,9999]}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
inventory-service :
ribbon.NFLoadBalancerRuleClassName : com.netflix.loadbalancer.RandomRule
logging:
level:
root: info
com.happylifeplat.tcc : debug
path: "./logs"

View File

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="16"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="3"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="repositorySupport" value="db"/>
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="xiaoyu"/>
<property name="password" value="Wgj@555888"/>
</bean>
</property>
</bean>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/stock?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/inventory"/>
<property name="prefix" value="inventory"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -1,161 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>happylifeplat-tcc-demo-springcloud</artifactId>
<groupId>com.happylifeplat.tcc</groupId>
<version>1.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>happylifeplat-tcc-demo-springcloud-order</artifactId>
<dependencies>
<dependency>
<groupId>com.happylifeplat.tcc</groupId>
<artifactId>happylifeplat-tcc-springcloud</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
<!--spring boot的核心启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ImportResource;
/**
* @author xiaoyu
*/
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@EnableEurekaClient
@EnableFeignClients
@ImportResource({"classpath:applicationContext.xml"})
@MapperScan("com.happylifeplat.tcc.demo.springcloud.order.mapper")
public class SpringCloudTccOrderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudTccOrderApplication.class, args);
}
}

View File

@ -1,58 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.client;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.springcloud.order.configuration.MyConfiguration;
import com.happylifeplat.tcc.demo.springcloud.order.dto.AccountDTO;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@FeignClient(value = "account-service", configuration = MyConfiguration.class)
public interface AccountClient {
/**
* 用户账户付款
*
* @param accountDO 实体类
* @return true 成功
*/
@PostMapping("/account-service/account/payment")
@Tcc
Boolean payment(@RequestBody AccountDTO accountDO);
/**
* 获取用户账户信息
*
* @param userId 用户id
* @return AccountDO
*/
@PostMapping("/account-service/account/findByUserId")
BigDecimal findByUserId(@RequestParam("userId") String userId);
}

View File

@ -1,76 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.client;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.demo.springcloud.order.configuration.MyConfiguration;
import com.happylifeplat.tcc.demo.springcloud.order.dto.InventoryDTO;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author xiaoyu
*/
@FeignClient(value = "inventory-service", configuration = MyConfiguration.class)
public interface InventoryClient {
/**
* 库存扣减
*
* @param inventoryDTO 实体对象
* @return true 成功
*/
@Tcc
@RequestMapping("/inventory-service/inventory/decrease")
Boolean decrease(@RequestBody InventoryDTO inventoryDTO);
/**
* 获取商品库存
*
* @param productId 商品id
* @return InventoryDO
*/
@RequestMapping("/inventory-service/inventory/findByProductId")
Integer findByProductId(@RequestParam("productId") String productId);
/**
* 模拟库存扣减异常
*
* @param inventoryDTO 实体对象
* @return true 成功
*/
@Tcc
@RequestMapping("/inventory-service/inventory/mockWithTryException")
Boolean mockWithTryException(@RequestBody InventoryDTO inventoryDTO);
/**
* 模拟库存扣减超时
*
* @param inventoryDTO 实体对象
* @return true 成功
*/
@Tcc
@RequestMapping("/inventory-service/inventory/mockWithTryTimeout")
Boolean mockWithTryTimeout(@RequestBody InventoryDTO inventoryDTO);
}

View File

@ -1,63 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.configuration;
import com.happylifeplat.tcc.springcloud.feign.TccFeignHandler;
import com.happylifeplat.tcc.springcloud.feign.TccRestTemplateInterceptor;
import feign.Feign;
import feign.InvocationHandlerFactory;
import feign.Request;
import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* @author xiaoyu
*/
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder()
.requestInterceptor(new TccRestTemplateInterceptor())
.invocationHandlerFactory(invocationHandlerFactory());
}
@Bean
public InvocationHandlerFactory invocationHandlerFactory() {
return (target, dispatch) -> {
TccFeignHandler handler = new TccFeignHandler();
handler.setTarget(target);
handler.setHandlers(dispatch);
return handler;
};
}
@Bean
Request.Options feignOptions() {
return new Request.Options(5000, 5000);
}
@Bean
Retryer feignRetryer() {
return Retryer.NEVER_RETRY;
}
}

View File

@ -1,72 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.time.LocalDate;
import static com.google.common.collect.Lists.newArrayList;
/**
* @author xiaoyu
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
private static final String SWAGGER_SCAN_BASE_PACKAGE = "com.happylifeplat.tcc.demo.springcloud.order.controller";
private static final String VERSION = "1.0.0";
ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("Springcloud分布式事务解决方案之TCC测试体验")
.license("Apache 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.termsOfServiceUrl("")
.version(VERSION)
.contact(new Contact("xiaoyu", "", "549477611@qq.com"))
.build();
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
// .paths(paths())
.build().pathMapping("/").directModelSubstitute(LocalDate.class, String.class)
.genericModelSubstitutes(ResponseEntity.class).useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder().code(500).message("500 message")
.responseModel(new ModelRef("Error")).build()));
}
}

View File

@ -1,71 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.controller;
import com.happylifeplat.tcc.demo.springcloud.order.service.OrderService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@RestController
@RequestMapping("/order")
public class OrderController {
private final OrderService orderService;
@Autowired
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping(value = "/orderPay")
@ApiOperation(value = "订单支付接口(注意这里模拟的是创建订单并进行支付扣减库存等操作)")
public String orderPay(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.orderPay(count, amount);
}
@PostMapping(value = "/mockInventoryWithTryException")
@ApiOperation(value = "模拟下单付款操作在try阶段异常此时账户系统和订单状态会回滚达到数据的一致性注意:这里模拟的是系统异常或者rpc异常")
public String mockInventoryWithTryException(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithTryException(count, amount);
}
@PostMapping(value = "/mockInventoryWithTryTimeout")
@ApiOperation(value = "模拟下单付款操作在try阶段超时异常此时账户系统和订单状态会回滚达到数据的一致性异常指的是超时异常")
public String mockInventoryWithTryTimeout(@RequestParam(value = "count") Integer count,
@RequestParam(value = "amount") BigDecimal amount) {
return orderService.mockInventoryWithTryTimeout(count, amount);
}
}

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@Data
public class AccountDTO implements Serializable {
private static final long serialVersionUID = 7223470850578998427L;
/**
* 用户id
*/
private String userId;
/**
* 扣款金额
*/
private BigDecimal amount;
}

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author xiaoyu
*/
@Data
public class InventoryDTO implements Serializable {
private static final long serialVersionUID = 8229355519336565493L;
/**
* 商品id
*/
private String productId;
/**
* 数量
*/
private Integer count;
}

View File

@ -1,73 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Data
public class Order implements Serializable {
private static final long serialVersionUID = -8551347266419380333L;
private Integer id;
/**
* 创建时间
*/
private Date createTime;
/**
* 订单编号
*/
private String number;
/**
* 订单状态
*/
private Integer status;
/**
* 商品id
*/
private String productId;
/**
* 付款金额
*/
private BigDecimal totalAmount;
/**
* 购买数量
*/
private Integer count;
/**
* 购买人
*/
private String userId;
}

View File

@ -1,93 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.enums;
/**
* The enum Order status enum.
*
* @author xiaoyu
*/
public enum OrderStatusEnum {
/**
* Not pay order status enum.
*/
NOT_PAY(1, "未支付"),
/**
* Paying order status enum.
*/
PAYING(2, "支付中"),
/**
* Pay fail order status enum.
*/
PAY_FAIL(3, "支付失败"),
/**
* Pay success order status enum.
*/
PAY_SUCCESS(4, "支付成功");
private int code;
private String desc;
OrderStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* Gets code.
*
* @return the code
*/
public int getCode() {
return code;
}
/**
* Sets code.
*
* @param code the code
*/
public void setCode(int code) {
this.code = code;
}
/**
* Gets desc.
*
* @return the desc
*/
public String getDesc() {
return desc;
}
/**
* Sets desc.
*
* @param desc the desc
*/
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@ -1,59 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.mapper;
import com.happylifeplat.tcc.demo.springcloud.order.entity.Order;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/**
* @author xiaoyu
*/
public interface OrderMapper {
/**
* 保存订单
*
* @param order 订单对象
* @return rows
*/
@Insert(" insert into `order` (create_time,number,status,product_id,total_amount,count,user_id) " +
" values ( #{createTime},#{number},#{status},#{productId},#{totalAmount},#{count},#{userId})")
int save(Order order);
/**
* 更新订单
*
* @param order 订单对象
* @return rows
*/
@Update("update `order` set status = #{status} , total_amount=#{totalAmount} where number=#{number}")
int update(Order order);
/**
* 获取所有的订单
*
* @return List<Order>
*/
@Select("select * from order")
List<Order> listAll();
}

View File

@ -1,67 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.service;
import com.happylifeplat.tcc.demo.springcloud.order.entity.Order;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
public interface OrderService {
/**
* 创建订单并且进行扣除账户余额支付并进行库存扣减操作
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String orderPay(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在try阶段中的库存异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithTryException(Integer count, BigDecimal amount);
/**
* 模拟在订单支付操作中库存在try阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
String mockInventoryWithTryTimeout(Integer count, BigDecimal amount);
/**
* 更新订单状态
*
* @param order 订单实体类
*/
void updateOrderStatus(Order order);
}

View File

@ -1,55 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.service;
import com.happylifeplat.tcc.demo.springcloud.order.entity.Order;
/**
* @author xiaoyu
*/
public interface PaymentService {
/**
* 订单支付
*
* @param order 订单实体
*/
void makePayment(Order order);
/**
* mock订单支付的时候库存异常
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithTryException(Order order);
/**
* mock订单支付的时候库存超时
*
* @param order 订单实体
* @return String
*/
String mockPaymentInventoryWithTryTimeout(Order order);
}

View File

@ -1,133 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.service.impl;
import com.happylifeplat.tcc.common.utils.IdWorkerUtils;
import com.happylifeplat.tcc.demo.springcloud.order.entity.Order;
import com.happylifeplat.tcc.demo.springcloud.order.enums.OrderStatusEnum;
import com.happylifeplat.tcc.demo.springcloud.order.mapper.OrderMapper;
import com.happylifeplat.tcc.demo.springcloud.order.service.OrderService;
import com.happylifeplat.tcc.demo.springcloud.order.service.PaymentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xiaoyu
*/
@Service("orderService")
public class OrderServiceImpl implements OrderService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);
private final OrderMapper orderMapper;
private final PaymentService paymentService;
@Autowired(required = false)
public OrderServiceImpl(OrderMapper orderMapper, PaymentService paymentService) {
this.orderMapper = orderMapper;
this.paymentService = paymentService;
}
@Override
public String orderPay(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.makePayment(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在try阶段中的库存异常
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithTryException(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithTryException(order);
}
return "success";
}
/**
* 模拟在订单支付操作中库存在try阶段中的timeout
*
* @param count 购买数量
* @param amount 支付金额
* @return string
*/
@Override
public String mockInventoryWithTryTimeout(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentService.mockPaymentInventoryWithTryTimeout(order);
}
return "success";
}
@Override
public void updateOrderStatus(Order order) {
orderMapper.update(order);
}
private Order buildOrder(Integer count, BigDecimal amount) {
LOGGER.debug("构建订单对象");
Order order = new Order();
order.setCreateTime(new Date());
order.setNumber(IdWorkerUtils.getInstance().buildPartNumber());
//demo中的表里只有商品id为 1的数据
order.setProductId("1");
order.setStatus(OrderStatusEnum.NOT_PAY.getCode());
order.setTotalAmount(amount);
order.setCount(count);
//demo中 表里面存的用户id为10000
order.setUserId("10000");
return order;
}
}

View File

@ -1,163 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package com.happylifeplat.tcc.demo.springcloud.order.service.impl;
import com.happylifeplat.tcc.annotation.Tcc;
import com.happylifeplat.tcc.common.exception.TccRuntimeException;
import com.happylifeplat.tcc.demo.springcloud.order.client.AccountClient;
import com.happylifeplat.tcc.demo.springcloud.order.client.InventoryClient;
import com.happylifeplat.tcc.demo.springcloud.order.dto.AccountDTO;
import com.happylifeplat.tcc.demo.springcloud.order.dto.InventoryDTO;
import com.happylifeplat.tcc.demo.springcloud.order.entity.Order;
import com.happylifeplat.tcc.demo.springcloud.order.enums.OrderStatusEnum;
import com.happylifeplat.tcc.demo.springcloud.order.mapper.OrderMapper;
import com.happylifeplat.tcc.demo.springcloud.order.service.PaymentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* @author xiaoyu
*/
@Service
public class PaymentServiceImpl implements PaymentService {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PaymentServiceImpl.class);
private final OrderMapper orderMapper;
private final AccountClient accountClient;
private final InventoryClient inventoryClient;
@Autowired(required = false)
public PaymentServiceImpl(OrderMapper orderMapper,
AccountClient accountClient,
InventoryClient inventoryClient) {
this.orderMapper = orderMapper;
this.accountClient = accountClient;
this.inventoryClient = inventoryClient;
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public void makePayment(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//检查数据
final BigDecimal accountInfo = accountClient.findByUserId(order.getUserId());
final Integer inventoryInfo= inventoryClient.findByProductId(order.getProductId());
if (accountInfo.compareTo(order.getTotalAmount()) <= 0) {
throw new TccRuntimeException("余额不足!");
}
if (inventoryInfo < order.getCount()) {
throw new TccRuntimeException("库存不足!");
}
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
LOGGER.debug("===========执行springcloud扣减资金接口==========");
accountClient.payment(accountDTO);
//进入扣减库存操作
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryClient.decrease(inventoryDTO);
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithTryException(Order order) {
LOGGER.debug("===========执行springcloud mockPaymentInventoryWithTryException 扣减资金接口==========");
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountClient.payment(accountDTO);
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryClient.mockWithTryException(inventoryDTO);
return "success";
}
@Override
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public String mockPaymentInventoryWithTryTimeout(Order order) {
LOGGER.debug("===========执行springcloud mockPaymentInventoryWithTryTimeout 扣减资金接口==========");
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用户余额
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
accountClient.payment(accountDTO);
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryClient.mockWithTryTimeout(inventoryDTO);
return "success";
}
public void confirmOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_SUCCESS.getCode());
orderMapper.update(order);
LOGGER.info("=========进行订单confirm操作完成================");
}
public void cancelOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_FAIL.getCode());
orderMapper.update(order);
LOGGER.info("=========进行订单cancel操作完成================");
}
}

View File

@ -1,45 +0,0 @@
server:
port: 8884
contextPath: /
address: 0.0.0.0
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.68:3306/tcc_order?useUnicode=true&characterEncoding=utf8
username: xiaoyu
password: Wgj@555888
initialSize: 20
minIdle: 20
maxActive: 100
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,wall,slf4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
application:
name: order-service
mybatis:
type-aliases-package: com.happylifeplat.tcc.demo.springcloud.order.entity
config-location: classpath:mybatis/mybatis-config.xml
#${random.int[9000,9999]}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
logging:
level:
root: info
com.happylifeplat.tcc : debug
path: "./logs"

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright 2017-2018 549477611@qq.com(xiaoyu)
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, see <http://www.gnu.org/licenses/>.
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.happylifeplat.tcc.*"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
<bean id="tccTransactionBootstrap" class="com.happylifeplat.tcc.core.bootstrap.TccTransactionBootstrap">
<property name="serializer" value="kryo"/>
<property name="coordinatorQueueMax" value="5000"/>
<property name="coordinatorThreadMax" value="16"/>
<property name="recoverDelayTime" value="120"/>
<property name="retryMax" value="30"/>
<property name="rejectPolicy" value="Abort"/>
<property name="blockingQueueType" value="Linked"/>
<property name="scheduledDelay" value="120"/>
<property name="scheduledThreadMax" value="4"/>
<property name="repositorySupport" value="db"/>
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="xiaoyu"/>
<property name="password" value="Wgj@555888"/>
</bean>
</property>
</bean>
<!--
<property name="repositorySupport" value="db" />
<property name="tccDbConfig">
<bean class="com.happylifeplat.tcc.common.config.TccDbConfig">
<property name="url"
value="jdbc:mysql://192.168.1.68:3306/order?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="password" value="Wgj@555888"/>
<property name="username" value="xiaoyu"/>
</bean>
</property>
<property name="repositorySupport" value="redis" />
<property name="tccRedisConfig">
<bean class="com.happylifeplat.tcc.common.config.TccRedisConfig">
<property name="hostName"
value="192.168.1.68"/>
<property name="port" value="6379"/>
<property name="password" value=""/>
</bean>
</property>
<property name="repositorySupport" value="zookeeper"/>
<property name="tccZookeeperConfig">
<bean class="com.happylifeplat.tcc.common.config.TccZookeeperConfig">
<property name="host" value="192.168.1.73:2181"/>
<property name="sessionTimeOut" value="100000"/>
<property name="rootPath" value="/tcc"/>
</bean>
</property>
<property name="repositorySupport" value="mongodb"/>
<property name="tccMongoConfig">
<bean class="com.happylifeplat.tcc.common.config.TccMongoConfig">
<property name="mongoDbUrl" value="192.168.1.68:27017"/>
<property name="mongoDbName" value="happylife"/>
<property name="mongoUserName" value="xiaoyu"/>
<property name="mongoUserPwd" value="123456"/>
</bean>
</property>
<property name="repositorySupport" value="file"/>
<property name="tccFileConfig">
<bean class="com.happylifeplat.tcc.common.config.TccFileConfig">
<property name="path" value="/order"/>
<property name="prefix" value="order"/>
</bean>
</property>
-->
</beans>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page$"/>
</properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -27,7 +27,7 @@
</license>
</licenses>
<scm>
<url>https://github.com/yu199195/happylifeplat-tcc.git</url>
<url>https://github.com/yu199195/hmily.git</url>
</scm>
<developers>