直接上代码:

代码结构如下:

依次贴出相关类:

DataSource1Config:
package com.example.demo.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
//DataSource01
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "com.example.demo.test01", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {

@Bean(name = "test1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.test1")
@Primary
public DataSource testDataSource() {
return DataSourceBuilder.create().build();
}

@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// bean.setMapperLocations(
// new
// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
return bean.getObject();
}

@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean(name = "test1SqlSessionTemplate")
@Primary
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}

}

DataSource2Config:
package com.example.demo.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
//DataSource2
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "com.example.demo.test02", sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DataSource2Config {
@Bean(name = "test2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.test2")
public DataSource testDataSource() {
return DataSourceBuilder.create().build();
}

@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// bean.setMapperLocations(
// new
// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml"));
return bean.getObject();
}

@Bean(name = "test2TransactionManager")
public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean(name = "test2SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}

}
OrderConsumer:
package com.example.demo.consumer;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.DispatcherEntity;
import com.example.demo.entity.OrderEntity;
import com.example.demo.test02.DispatcherMapper;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* @description: 消费者
* @author: dfz
* @create: 2020-02-24
**/
@Service
@RocketMQMessageListener(topic = "orderTopic", consumerGroup = "springboot-consumer-group")
public class OrderConsumer implements RocketMQListener<String>{
@Autowired
private DispatcherMapper dispatcherMapper;

@Override
public void onMessage(String msg) {
OrderEntity orderEntity = JSONObject.parseObject(msg, OrderEntity.class);
String orderId = orderEntity.getOrderId();
DispatcherEntity dispatcherEntity = new DispatcherEntity(orderId, "123456");
dispatcherMapper.insertDistribute(dispatcherEntity);

}
}
ProducerController:
package com.example.demo.producer;

import com.example.demo.service.ProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
@RestController
public class ProducerController {
@Autowired
private ProducerService producerService;

@RequestMapping(value = "sendMsg")
public String insertUser(){
producerService.saveOrder();
return "success";
}
}
ProducerService:
package com.example.demo.service;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.OrderEntity;
import com.example.demo.test01.OrderMapper;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
* @description: ProducerService
* @author: dfz
* @create: 2020-02-24
**/
@Service
public class ProducerService {

@Autowired
private OrderMapper orderMapper;

@Autowired
private RocketMQTemplate rocketMQTemplate;

public String saveOrder(){
//提前生成订单id
String orderId = System.currentTimeMillis()+"";
//提前生成半消息,再执行本地事务
OrderEntity orderEntity = creatOrder(orderId);
String msg = JSONObject.toJSONString(orderEntity);
MessageBuilder<String> tMessageBuilder = MessageBuilder.withPayload(msg);
tMessageBuilder.setHeader("msg", msg);
Message message = tMessageBuilder.build();
//该消息不会被消费
rocketMQTemplate.sendMessageInTransaction("springboot-producer-group", "orderTopic", message, null);
return orderId;
}

public OrderEntity creatOrder(String orderId){
OrderEntity orderEntity = new OrderEntity();
orderEntity.setOrderId(orderId);
orderEntity.setOrderName("订单Id1234");
orderEntity.setOrderCreateDate(new Date());
orderEntity.setPrice(300d);
return orderEntity;
}

}
package com.example.demo.listener;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.OrderEntity;
import com.example.demo.test01.OrderMapper;
import com.example.demo.utils.TransactionalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
@Slf4j
@Component
@RocketMQTransactionListener(txProducerGroup = "springboot-producer-group")
public class SyncProducerListener implements RocketMQLocalTransactionListener {

@Autowired
private TransactionalUtil transactionalUtil;

@Autowired
private OrderMapper orderMapper;

//执行本地事务
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
MessageHeaders headers = message.getHeaders();
Object object = headers.get("msg");
if (object == null) {
return RocketMQLocalTransactionState.ROLLBACK;
}
String orderMessage = (String) object;
OrderEntity orderEntity = JSONObject.parseObject(orderMessage, OrderEntity.class);
TransactionStatus status = null;
try {
status = transactionalUtil.begin();
int result = orderMapper.addOrder(orderEntity);
transactionalUtil.commit(status);
if (result < 1) {
return RocketMQLocalTransactionState.ROLLBACK;
}
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
if (status != null) {
transactionalUtil.rollback(status);
return RocketMQLocalTransactionState.ROLLBACK;
}
}
return null;
}

@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
MessageHeaders headers = message.getHeaders();
Object object = headers.get("msg");
if (object == null) {
return RocketMQLocalTransactionState.ROLLBACK;
}
String orderMessage = (String) object;
OrderEntity orderEntity = JSONObject.parseObject(orderMessage, OrderEntity.class);
String orderId = orderEntity.getOrderId();
//查询数据库
OrderEntity orderEntity1 = orderMapper.findOrder(orderId);
if (null == orderEntity1) {
return RocketMQLocalTransactionState.UNKNOWN;
}
return RocketMQLocalTransactionState.COMMIT;
}
}

package com.example.demo.test01;

import com.example.demo.entity.OrderEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
public interface OrderMapper {
@Insert("insert into order values(null,#{order.orderId},#{order.orderName}, #{order.price}, #{order.orderCreateDate});")
public int addOrder(OrderEntity order);
@Insert("select * from order where orderId = ${orderId};")
public OrderEntity findOrder(String orderId);

}

package com.example.demo.test02;

import com.example.demo.entity.DispatcherEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
public interface DispatcherMapper {
@Insert("insert into order_users values(null,#{entity.name},#{entity.age});")
public int insertDistribute(DispatcherEntity entity);
}

package com.example.demo.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
@Service
public class TransactionalUtil {
@Autowired
public DataSourceTransactionManager transactionManager;

public TransactionStatus begin(){
TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionAttribute());
return transactionStatus;
}

public void commit(TransactionStatus status){
transactionManager.commit(status);
}

public void rollback(TransactionStatus status){
transactionManager.rollback(status);
}
}

package com.example.demo.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-24
**/
@Data
public class DispatcherEntity implements Serializable {
private String orderId;
private String userId;

public DispatcherEntity(String orderId, String userId) {
this.orderId = orderId;
this.userId = userId;
}
}
package com.example.demo.entity;

import java.io.Serializable;
import java.util.Date;

/**
* @description: ${description}
* @author: dfz
* @create: 2020-02-20
**/
public class OrderEntity implements Serializable{

private String orderId;
private String orderName;
private Date orderCreateDate;
private Double price;

public String getOrderId() {
return orderId;
}

public void setOrderId(String orderId) {
this.orderId = orderId;
}

public String getOrderName() {
return orderName;
}

public void setOrderName(String orderName) {
this.orderName = orderName;
}

public Date getOrderCreateDate() {
return orderCreateDate;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public void setOrderCreateDate(Date orderCreateDate) {
this.orderCreateDate = orderCreateDate;
}

public OrderEntity(String orderId, String orderName) {
this.orderId = orderId;
this.orderName = orderName;
}

public OrderEntity() {
}
}

server.port=8088
###datasource1
spring.datasource.test1.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test1.jdbc-url = jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.test1.username = root
spring.datasource.test1.password = 123456
###datasource2
spring.datasource.test2.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test2.jdbc-url = jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.test2.username = root
spring.datasource.test2.password = 123456

rocketmq.name-server=192.168.2.3:9876
rocketmq.producer.group=boot_sync_user

Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.demo</groupId>
<artifactId>rocketmq-transactional</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rocketmq-transactional</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- springboot-web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot 整合 pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!--RocketMQ -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>


Springboot整合RocketMQ解决分布式事务的更多相关文章

  1. springboot整合RocketMq(非事务)

    1.配置文件 1.yml配置文件 rocketmq: #mq配置 producer: iseffect: true type: default # (transaction,default) tran ...

  2. springboot整合多数据源解决分布式事务

    一.前言        springboot整合多数据源解决分布式事务.             1.多数据源采用分包策略              2.全局分布式事务管理:jta-atomikos. ...

  3. 搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务

    搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务 初步认识RocketMQ的核心模块 rocketmq模块 rocketmq-broker:接受生产者发来的消息并存储(通过调用rocke ...

  4. RabbitMQ解决分布式事务

    案例:经典案例,以目前流行点外卖的案例,用户下单后,调用订单服务,让后订单服务调用派单系统通知送外卖人员送单,这时候订单系统与派单系统采用MQ异步通讯. RabbitMQ解决分布式事务原理: 采用最终 ...

  5. SpringBoot(17)---SpringBoot整合RocketMQ

    SpringBoot整合RocketMQ 上篇博客讲解了服务器集群部署RocketMQ 博客地址:RocketMQ(2)---Docker部署RocketMQ集群 这篇在上篇搭建好的基础上,将Spri ...

  6. 【分布式事务】使用atomikos+jta解决分布式事务问题

    一.前言 分布式事务,这个问题困惑了小编很久,在3个月之前,就间断性的研究分布式事务.从MQ方面,数据库事务方面,jta方面.近期终于成功了,使用JTA解决了分布式事务问题.先写一下心得,后面的二级提 ...

  7. LCN解决分布式事务原理解析+项目实战(原创精华版)

    写在前面: 原创不易,如果觉得不错推荐一下,谢谢! 由于工作需要,公司的微服务项目需解决分布式事务的问题,且由我进行分布式事务框架搭建和整合工作. 那么借此机会好好的将解决分布式事务的内容进行整理一下 ...

  8. SpringCloud+RocketMQ实现分布式事务

    随着互联网公司的微服务越来越多,分布式事务已经成为了我们的经常使用的.所以我们来一步一步的实现基于RocketMQ的分布式事务.接下来,我们将要做的主题写出来. RocketMQ的分布式事务结构和说明 ...

  9. 使用kafka消息队列解决分布式事务(可靠消息最终一致性方案-本地消息服务)

    微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务 本文转自:http://skaka.me/blog/2016/04/21/springcloud1/ 不同于单一 ...

随机推荐

  1. Adversarial Examples Are Not Bugs, They Are Features

    目录 概 主要内容 符号说明及部分定义 可用特征 稳定可用特征 可用不稳定特征 标准(standard)训练 稳定(robust)训练 分离出稳定数据 分离出不稳定数据 随机选取 选取依赖于 比较重要 ...

  2. springboot中word转pdf,加盖电子印章

    概述 在开发过程中,word转pdf的方式有很多种有jar包的方式,有安装openoffice的方式,但是使用有的jar包有license认证,不然会生成水印,综合几种方法我采用了libreoffic ...

  3. SQL Server 数据库添加主键,唯一键,外键约束脚本

    -- 声明使用数据库use 数据库;go -- 添加主键(primary key)约束-- 基本语法-- 判断主键约束是否存在,如果存在则删除,不存在则添加if exists(select * fro ...

  4. CSS基础 阴影相关属性设置

    一.字体阴影属性名:text-shadow:水平偏移量 垂直偏移量 模糊度 阴影颜色: html代码: <div>农夫山泉有点甜</div>css代码: div{ font-s ...

  5. python (伪)私有属性和私有方法

    1.定义方式 在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法. 2.为什么要定义私有属性和私有方法 在实际开发中,对象的某些属性或方法只希望在对象的内部被使用,而不希 ...

  6. vue中自定义属性

    <div v-bind:id="name"></div> //v-bind:id="变量" or :id="变量"

  7. 查询 MySQL 字段注释的 5 种方法!

    很多场景下,我们需要查看 MySQL 中表注释,或者是某张表下所有字段的注释,所以本文就来盘点和对比一下查询注释的几种方式. 创建测试数据库 开始之前咱们先创建一个数据库,以备下面演示使用. -- 如 ...

  8. MySQL使用时间作为判断条件

    背景:在开发过程中,我们经常需要根据时间作为判断条件来查询数据,例如:当月,当日,当前小时,几天内...... 1. 当月 我们只需要使用一个mysql的MONTH(date)函数即可实现.(注意判断 ...

  9. MATLAB中拟合算法刚入门

    %%%1.拟合问题:(做预测,主要使用的范围是样本比较小,拟合效果会好,样本比较多,拟合的效果就不是很好) 1.应用预测的场景:已经知道10年的样本,预测第11年以内的数据 2.用拟合的到关系式:样本 ...

  10. RabbitMQ 中的分布式,普通 cluster 模式的构建

    RabbitMQ 如何做分布式 前言 集群配置方案 cluster 普通模式 镜像模式 federation shovel 节点类型 RAM node Disk node 集群的搭建 1.局域网配置 ...