<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<springcloud.version>Greenwich.RELEASEspringcloud.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${springcloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependency>
<groupId>com.codingapi.txlcngroupId>
<artifactId>txlcn-tmartifactId>
<version>${txlcn.version}version>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
server:
port: 28771
spring:
application:
name: tx-lcn-server
redis:
host: 192.168.89.4
port: 6379
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1/tx-manager?characterEncoding=utf-8&useSSL=false
cloud:
host: 127.0.0.1
port: 8500
consul:
discovery:
service-name: tx-lcn-server
health-check-path: /actuator/health
health-check-interval: 10s
prefer-ip-address: true
config:
enabled: true
format: yaml
data-key: data #表示consul上面的KEY值(或者说文件的名字) 默认是data
package com.hui.base.springcloud.lcn;
import com.codingapi.txlcn.tm.config.EnableTransactionManagerServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* LcnServerApplication
*
* Description: SpringCloud LCN-manager服务(分布式事务) 默认是8070端口
*
* Creation Time: 2019/4/1 21:15.
*
* @author HuWeihui
*/
@EnableTransactionManagerServer
@SpringBootApplication
@EnableDiscoveryClient
public class LcnServerApplication {
public static void main(String[] args) {
SpringApplication.run(LcnServerApplication.class,args);
}
}
<dependency>
<groupId>com.codingapi.txlcngroupId>
<artifactId>txlcn-tcartifactId>
<version>${txlcn.version}version>
dependency>
<dependency>
<groupId>com.codingapi.txlcngroupId>
<artifactId>txlcn-txmsg-nettyartifactId>
<version>${txlcn.version}version>
dependency>
/**
* 测试LCN-TCC
* @param order
* @param exFlag
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void testTCC(Order order, String exFlag) {
// use the tcc mode to start remote transaction
ProductDTO productDTO = new ProductDTO();
double ceil = Math.ceil(Math.random() * 100);
String productId = String.valueOf(ceil);
productDTO.setProductName("tccTest");
productDTO.setProductId(productId);
productFeignApi.tccAdd(productDTO);
// use the local transaction
orderMapper.insertSelective(order);
if (exFlag.equals("true")){
throw new RuntimeException("test txc exception");
}
}
/**
* 测试LCN-TXC
* @param order
* @param exFlag
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void testTXC(Order order, String exFlag) {
// use the local transaction
orderMapper.insertSelective(order);
// use the txc mode to start remote transaction
ProductDTO productDTO = new ProductDTO();
productDTO.setProductName("txcTest");
double ceil = Math.ceil(Math.random() * 100);
String productId = String.valueOf(ceil);
productDTO.setProductId(productId);
productFeignApi.txcAdd(productDTO);
if (exFlag.equals("true")){
throw new RuntimeException("test txc exception");
}
}
package com.hui.base.springcloud.order.config;
import com.codingapi.txlcn.common.util.Transactions;
import com.codingapi.txlcn.tc.aspect.interceptor.TxLcnInterceptor;
import com.codingapi.txlcn.tc.aspect.weave.DTXLogicWeaver;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.Properties;
/**
* Description: AOP方式声明分布式事务示例。product-server 用的注解方式,注意区分,非必须如此配置,可以注解,也可以声明式
* Date: 19-1-13 下午2:46
*
* @author ujued
*/
@Configuration
@EnableTransactionManagement
public class AopTypeDTXConfiguration {
/**
* 本地事务配置
*
* @param transactionManager
* @return
*/
@Bean
@ConditionalOnMissingBean
public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
Properties properties = new Properties();
properties.setProperty("*", "PROPAGATION_REQUIRED,-Throwable");
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
transactionInterceptor.setTransactionManager(transactionManager);
transactionInterceptor.setTransactionAttributes(properties);
return transactionInterceptor;
}
/**
* 分布式事务配置 设置为LCN模式
*
* @param dtxLogicWeaver
* @return
*/
@ConditionalOnBean(DTXLogicWeaver.class)
@Bean
public TxLcnInterceptor txLcnInterceptor(DTXLogicWeaver dtxLogicWeaver) {
TxLcnInterceptor txLcnInterceptor = new TxLcnInterceptor(dtxLogicWeaver);
Properties properties = new Properties();
properties.setProperty(Transactions.DTX_TYPE, Transactions.LCN);
properties.setProperty(Transactions.DTX_PROPAGATION, "REQUIRED");
txLcnInterceptor.setTransactionAttributes(properties);
return txLcnInterceptor;
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setInterceptorNames("txLcnInterceptor", "transactionInterceptor");
beanNameAutoProxyCreator.setBeanNames("*Impl");
return beanNameAutoProxyCreator;
}
}
@Override
@TccTransaction(propagation = DTXPropagation.SUPPORTS)
@Transactional(rollbackFor = Exception.class)
public void tccAdd(Product product) {
productMapper.insertSelective(product);
ids.putIfAbsent(TracingContext.tracing().groupId(), Sets.newHashSet(product.getProductId()));
ids.get(TracingContext.tracing().groupId()).add(product.getProductId());
}
public void confirmTccAdd (Product product) {
ids.get(TracingContext.tracing().groupId()).forEach(id -> {
log.info("tcc-confirm-{}-{}" , TracingContext.tracing().groupId(), id);
ids.get(TracingContext.tracing().groupId()).remove(id);
});
}
public void cancelTccAdd(Product product) {
ids.get(TracingContext.tracing().groupId()).forEach(id -> {
log.info("tcc-cancel-{}-{}", TracingContext.tracing().groupId(), id);
productMapper.deleteByPrimaryKey(id);
});
}
@Override
@TxcTransaction(propagation = DTXPropagation.SUPPORTS)
@Transactional(rollbackFor = Exception.class)
public void txcAdd(Product product) {
productMapper.insertSelective(product);
}
package com.hui.base.springcloud.product.api;
import com.codingapi.txlcn.tc.support.DTXUserControls;
import com.codingapi.txlcn.tracing.TracingContext;
import com.hui.base.springcloud.common.response.ResultVO;
import dto.ProductDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* ProductAPI
*
* Description:
*
* Creation Time: 2018/11/28 23:20.
*
* @author Hu Weihui
*/
@FeignClient(name = "product-server",path = "/product",fallback = ProductFeignApi.ProductFeignApiFallback.class )//如果产生服务降级就返回NULL
public interface ProductFeignApi {
@PutMapping("/lcn/tcc/products")
ResultVO tccAdd(@RequestBody ProductDTO productDTO);
@PutMapping("/lcn/txc/products")
ResultVO txcAdd(@RequestBody ProductDTO productDTO);
@Component
static class ProductFeignApiFallback implements ProductFeignApi{
@Override
public ResultVO tccAdd(ProductDTO productDTO) {
//TCC的关键点
DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
return null;
}
@Override
public ResultVO txcAdd(ProductDTO productDTO) {
return null;
}
}
}
package com.hui.base.springcloud.product.config;
import com.codingapi.txlcn.common.util.Maps;
import com.codingapi.txlcn.tc.core.transaction.txc.analy.def.PrimaryKeysProvider;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Description:
* Date: 19-1-25 下午4:29
* @author ujued
*/
@Component
public class MysqlPrimaryKeysProvider implements PrimaryKeysProvider {
@Override
public Map<String, List<String>> provide() {
return Maps.of("t_product", Collections.singletonList("product_id"),
"t_order",Collections.singletonList("order_id"));
}
}
不同版本对应不同分支
springcloud-greenwich采用了consul-config,不需要下方的hui-base-springcloud-config-repo
【SpringCloud】完整工程 https://github.com/ithuhui/hui-base-springcloud
【Config-Server】配置中心配置文件:https://github.com/ithuhui/hui-base-springcloud-config-repo
作者:HuHui
转载:欢迎一起讨论web和大数据问题,转载请注明作者和原文链接,感谢