├── transaction ├── transaction-api │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── net │ │ │ └── codingw │ │ │ ├── App.java │ │ │ └── rocketmq │ │ │ └── learning │ │ │ └── transaction │ │ │ └── api │ │ │ └── user │ │ │ ├── service │ │ │ └── UserService.java │ │ │ └── dto │ │ │ └── UserDto.java │ ├── rocketmq-learning-transaction-api.iml │ ├── transaction-api.iml │ └── pom.xml ├── transaction-gateway │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── net │ │ │ │ └── codingw │ │ │ │ ├── App.java │ │ │ │ └── rocketmq │ │ │ │ └── learning │ │ │ │ └── transaction │ │ │ │ └── gateway │ │ │ │ ├── RocketMQLearningTransactionGatewayApplication.java │ │ │ │ └── control │ │ │ │ └── UserControl.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ └── application.properties │ ├── transaction-gateway.iml │ ├── pom.xml │ └── rocketmq-learning-transaction-gateway.iml ├── transaction-service │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ └── net │ │ │ │ └── codingw │ │ │ │ └── AppTest.java │ │ └── main │ │ │ ├── java │ │ │ └── net │ │ │ │ └── codingw │ │ │ │ └── rocketmq │ │ │ │ └── learning │ │ │ │ └── transaction │ │ │ │ ├── user │ │ │ │ ├── mapper │ │ │ │ │ └── UserMapper.java │ │ │ │ ├── model │ │ │ │ │ └── User.java │ │ │ │ └── service │ │ │ │ │ └── impl │ │ │ │ │ ├── UserRegTransactionListener.java │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ ├── RocketMQLearningTransactionServiceApplication.java │ │ │ │ └── common │ │ │ │ └── config │ │ │ │ ├── MqProducerProperties.java │ │ │ │ ├── MQConfig.java │ │ │ │ └── TransactionMQProducerContainer.java │ │ │ └── resources │ │ │ ├── application.properties │ │ │ ├── application-dev.properties │ │ │ └── mapper │ │ │ └── UserMapper.xml │ ├── transaction-service.iml │ ├── pom.xml │ └── rocketmq-learning-transaction-service.iml ├── transaction.iml └── pom.xml ├── .gitignore ├── README.md └── pom.xml /transaction/transaction-api/src/main/java/net/codingw/App.java: -------------------------------------------------------------------------------- 1 | package net.codingw; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/src/main/java/net/codingw/App.java: -------------------------------------------------------------------------------- 1 | package net.codingw; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9090 3 | #字符编码 Request 和 Response 强制设为UTF-8 4 | spring: 5 | http: 6 | encoding: 7 | charset: UTF-8 8 | enabled: true 9 | force: true 10 | #日志颜色 11 | output: 12 | ansi: 13 | enabled: ALWAYS 14 | logging: 15 | level: 16 | tk.mybatis: TRACE -------------------------------------------------------------------------------- /transaction/transaction-api/src/main/java/net/codingw/rocketmq/learning/transaction/api/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.api.user.service; 2 | 3 | import net.codingw.rocketmq.learning.transaction.api.user.dto.UserDto; 4 | 5 | import java.util.Map; 6 | 7 | public interface UserService { 8 | 9 | public Map reg(UserDto userDto); 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.idea 22 | 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | 28 | target/ 29 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/test/java/net/codingw/AppTest.java: -------------------------------------------------------------------------------- 1 | package net.codingw; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = rocketmq_learning_transaction_gateway 2 | server.port = 9090 3 | 4 | dubbo.application.name = rocketmq_learning_transaction_gateway_consumer 5 | 6 | demo.service.version = 1.0.0 7 | 8 | dubbo.protocol.name = dubbo 9 | dubbo.protocol.port = 20880 10 | 11 | dubbo.registry.address = zookeeper://127.0.0.1:2181 12 | 13 | dubbo.consumer.timeout = 1000 14 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/user/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.user.mapper; 2 | 3 | 4 | import net.codingw.rocketmq.learning.transaction.user.model.User; 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | 8 | public interface UserMapper extends Mapper { 9 | 10 | // User findByUserName(String name); 11 | 12 | // void insert(User user); 13 | } 14 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/src/main/java/net/codingw/rocketmq/learning/transaction/gateway/RocketMQLearningTransactionGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | 7 | @SpringBootApplication 8 | public class RocketMQLearningTransactionGatewayApplication { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(RocketMQLearningTransactionGatewayApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | spring.mvc.view.prefix=/templates/ 3 | spring.mvc.view.suffix=.ftl 4 | 5 | spring.freemarker.cache=false 6 | spring.freemarker.request-context-attribute=request 7 | mybatis.type-aliases-package=net.codingw.rocketmq.learning.transaction.user.model 8 | mybatis.mapper-locations=classpath:mapper/*.xml 9 | mapper.not-empty=false 10 | mapper.identity=MYSQL 11 | 12 | 13 | pagehelper.helperDialect=mysql 14 | pagehelper.reasonable=true 15 | pagehelper.supportMethodsArguments=true 16 | pagehelper.params=count=countSql -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/RocketMQLearningTransactionServiceApplication.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction; 2 | 3 | import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import tk.mybatis.spring.annotation.MapperScan; 7 | 8 | @EnableDubbo 9 | @SpringBootApplication 10 | @MapperScan(basePackages = {"net.codingw.rocketmq.learning.transaction.user.mapper" }) 11 | public class RocketMQLearningTransactionServiceApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(RocketMQLearningTransactionServiceApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /transaction/transaction.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /transaction/transaction-api/rocketmq-learning-transaction-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rocketmq-learning 2 | 结合应用场景介绍如何使用rocketmq,试图打造rocketmq领域最佳的入门示例 3 | 4 | ## 代码介绍 5 | 代码组织将遵循功能,每一个功能都会结合具体使用场景。 6 | - transaction 7 | 事务消息发送。 8 | 9 | 10 | 11 | 12 | ## RocketMQ 免费电子书 13 | 14 | ![Apache RocketMQ ACL、消息轨迹、主从切换](https://img-blog.csdnimg.cn/2021030422241188.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ByZXN0aWdlZGluZw==,size_16,color_FFFFFF,t_70#pic_center) 15 | 16 | 17 | ![Apache线上故障排查与实战](https://img-blog.csdnimg.cn/20210304222419291.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ByZXN0aWdlZGluZw==,size_16,color_FFFFFF,t_70#pic_center) 18 | 19 | 获取方式:关注『中间件兴趣圈』,回复RMQPDF,**即可免费获取**。 20 | 21 | ![](https://img-blog.csdnimg.cn/20210304222446606.jpg#pic_center) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ## License 52 | 本项目本人原创!欢迎任何以学习为目的的传播,但未授权任何平台进行转载! 53 | -------------------------------------------------------------------------------- /transaction/transaction-api/transaction-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/transaction-gateway.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /transaction/transaction-service/transaction-service.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/common/config/MqProducerProperties.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.common.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "apache.rocketmq.producer") 6 | public class MqProducerProperties { 7 | 8 | private String producerGroup; 9 | private String namesrvAddr; 10 | private String transactionProducerGroupPrefix; 11 | 12 | public String getProducerGroup() { 13 | return producerGroup; 14 | } 15 | 16 | public void setProducerGroup(String producerGroup) { 17 | this.producerGroup = producerGroup; 18 | } 19 | 20 | public String getNamesrvAddr() { 21 | return namesrvAddr; 22 | } 23 | 24 | public void setNamesrvAddr(String namesrvAddr) { 25 | this.namesrvAddr = namesrvAddr; 26 | } 27 | 28 | public String getTransactionProducerGroupPrefix() { 29 | return transactionProducerGroupPrefix; 30 | } 31 | 32 | public void setTransactionProducerGroupPrefix(String transactionProducerGroupPrefix) { 33 | this.transactionProducerGroupPrefix = transactionProducerGroupPrefix; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = rocketmq_example_user_service 2 | server.port = 9091 3 | debug=true 4 | logging.level.root=info 5 | 6 | 7 | logging.level.tk.mybatis.springboot.mapper=info 8 | spring.datasource.url=jdbc:mysql://localhost:3306/demo 9 | spring.datasource.username=root 10 | spring.datasource.password=123456 11 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 12 | spring.datasource.druid.initial-size=1 13 | spring.datasource.druid.min-idle=1 14 | spring.datasource.druid.max-active=20 15 | spring.datasource.druid.test-on-borrow=true 16 | spring.datasource.druid.stat-view-servlet.allow=true 17 | 18 | 19 | 20 | 21 | dubbo.application.name = rocketmq_example_user_service_provider 22 | demo.service.version = 1.0.0 23 | dubbo.protocol.name = dubbo 24 | dubbo.protocol.port = 20880 25 | dubbo.registry.address = zookeeper://127.0.0.1:2181 26 | dubbo.provider.timeout = 1000 27 | 28 | 29 | 30 | 31 | apache.rocketmq.producer.producerGroup=rocketmq-example-service-producer 32 | apache.rocketmq.producer.transactionProducerGroupPrefix=rocketmq-example-user-service-transaction-producer 33 | apache.rocketmq.producer.namesrvAddr=127.0.0.1:9876 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /transaction/transaction-api/src/main/java/net/codingw/rocketmq/learning/transaction/api/user/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.api.user.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | public class UserDto implements Serializable { 6 | 7 | private Long id; 8 | private String password; 9 | private String userName; 10 | private int sex; 11 | private String email; 12 | 13 | public Long getId() { 14 | return id; 15 | } 16 | 17 | public void setId(Long id) { 18 | this.id = id; 19 | } 20 | 21 | public String getUserName() { 22 | return userName; 23 | } 24 | 25 | public void setUserName(String userName) { 26 | this.userName = userName; 27 | } 28 | 29 | public int getSex() { 30 | return sex; 31 | } 32 | 33 | public void setSex(int sex) { 34 | this.sex = sex; 35 | } 36 | 37 | public String getEmail() { 38 | return email; 39 | } 40 | 41 | public void setEmail(String email) { 42 | this.email = email; 43 | } 44 | 45 | public String getPassword() { 46 | return password; 47 | } 48 | 49 | public void setPassword(String password) { 50 | this.password = password; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/common/config/MQConfig.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.common.config; 2 | 3 | import org.apache.rocketmq.client.exception.MQClientException; 4 | import org.apache.rocketmq.client.producer.DefaultMQProducer; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | 11 | @Configuration 12 | @EnableConfigurationProperties(MqProducerProperties.class) 13 | public class MQConfig { 14 | 15 | /** 16 | * 生产者的组名 17 | */ 18 | @Value("${apache.rocketmq.producer.producerGroup}") 19 | private String producerGroup; 20 | 21 | @Value("${apache.rocketmq.producer.namesrvAddr}") 22 | private String namesrvAddr; 23 | @Bean 24 | public DefaultMQProducer defaultMQProducer() { 25 | //生产者的组名 26 | DefaultMQProducer producer= new DefaultMQProducer(producerGroup); 27 | //指定NameServer地址,多个地址以 ; 隔开 28 | producer.setNamesrvAddr(namesrvAddr); 29 | producer.setVipChannelEnabled(false); 30 | try { 31 | producer.start(); 32 | } catch (MQClientException e) { 33 | throw new RuntimeException("mq 配置错误", e); 34 | } 35 | 36 | return producer; 37 | } 38 | 39 | @Bean 40 | public TransactionMQProducerContainer transactionMQProducerContainer() { 41 | return new TransactionMQProducerContainer(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/user/model/User.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.user.model; 2 | 3 | import javax.persistence.GeneratedValue; 4 | import javax.persistence.GenerationType; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | @Table(name = "t_user") 11 | public class User implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.IDENTITY) 15 | private Long id; 16 | private String password; 17 | private String username; 18 | private int sex; 19 | private String email; 20 | private Date createTime; 21 | private Date updateTime; 22 | 23 | public Long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(Long id) { 28 | this.id = id; 29 | } 30 | 31 | public String getPassword() { 32 | return password; 33 | } 34 | 35 | public void setPassword(String password) { 36 | this.password = password; 37 | } 38 | 39 | public String getUsername() { 40 | return username; 41 | } 42 | 43 | public void setUsername(String username) { 44 | this.username = username; 45 | } 46 | 47 | public int getSex() { 48 | return sex; 49 | } 50 | 51 | public void setSex(int sex) { 52 | this.sex = sex; 53 | } 54 | 55 | public String getEmail() { 56 | return email; 57 | } 58 | 59 | public void setEmail(String email) { 60 | this.email = email; 61 | } 62 | 63 | public Date getCreateTime() { 64 | return createTime; 65 | } 66 | 67 | public void setCreateTime(Date createTime) { 68 | this.createTime = createTime; 69 | } 70 | 71 | public Date getUpdateTime() { 72 | return updateTime; 73 | } 74 | 75 | public void setUpdateTime(Date updateTime) { 76 | this.updateTime = updateTime; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/common/config/TransactionMQProducerContainer.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.common.config; 2 | 3 | 4 | import org.apache.rocketmq.client.producer.TransactionListener; 5 | import org.apache.rocketmq.client.producer.TransactionMQProducer; 6 | import org.springframework.beans.factory.annotation.Value; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class TransactionMQProducerContainer { 12 | private Map containers = new HashMap<>(); 13 | 14 | /** 生产者的组名*/ 15 | @Value("${apache.rocketmq.producer.producerGroup}") 16 | private String producerGroup; 17 | @Value("${apache.rocketmq.producer.transactionProducerGroupPrefix}") 18 | private String transactionProducerGroupPrefix; 19 | @Value("${apache.rocketmq.producer.namesrvAddr}") 20 | private String namesrvAddr; 21 | 22 | public TransactionMQProducer getTransactionMQProducer(String topic, TransactionListener transactionListener) { 23 | TransactionMQProducer producer = containers.get(topic); 24 | if(producer == null ) { 25 | synchronized (TransactionMQProducerContainer.class) { 26 | producer = containers.get(topic); 27 | if(producer == null ) { 28 | producer = new TransactionMQProducer(transactionProducerGroupPrefix+"-" + topic); 29 | producer.setNamesrvAddr(namesrvAddr); 30 | producer.setTransactionListener(transactionListener); 31 | try { 32 | producer.start(); 33 | }catch (Throwable e) { 34 | e.printStackTrace(); 35 | throw new RuntimeException("生产者启动异常", e); 36 | } 37 | containers.put(topic, producer); 38 | return producer; 39 | } 40 | } 41 | } 42 | return producer; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/src/main/java/net/codingw/rocketmq/learning/transaction/gateway/control/UserControl.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.gateway.control; 2 | 3 | 4 | import com.alibaba.dubbo.config.annotation.Reference; 5 | import net.codingw.rocketmq.learning.transaction.api.user.dto.UserDto; 6 | import net.codingw.rocketmq.learning.transaction.api.user.service.UserService; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | 17 | @RestController 18 | @RequestMapping("/user") 19 | public class UserControl { 20 | 21 | @Reference(check = false) 22 | private UserService userServiceProxy; 23 | 24 | 25 | @RequestMapping("/reg") 26 | @ResponseBody 27 | public Map reg(@RequestParam("username") String username, 28 | @RequestParam("pwd") String password, 29 | @RequestParam("email") String email, 30 | @RequestParam("sex") int sex){ 31 | 32 | Map result = new HashMap(); 33 | 34 | if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { 35 | result.put("code", 1); 36 | result.put("msg", "用户名与密码不能为空"); 37 | return result; 38 | } 39 | 40 | try { 41 | UserDto userDto = new UserDto(); 42 | userDto.setEmail(email); 43 | userDto.setPassword(password); 44 | userDto.setSex(sex); 45 | userDto.setUserName(username); 46 | return userServiceProxy.reg(userDto); 47 | } catch (Throwable e ) { 48 | e.printStackTrace(); 49 | result.put("code", 1); 50 | result.put("msg" , e.getMessage()); 51 | } 52 | 53 | return result; 54 | } 55 | 56 | 57 | 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/user/service/impl/UserRegTransactionListener.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.user.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import net.codingw.rocketmq.learning.transaction.api.user.dto.UserDto; 5 | import net.codingw.rocketmq.learning.transaction.user.mapper.UserMapper; 6 | import net.codingw.rocketmq.learning.transaction.user.model.User; 7 | import org.apache.rocketmq.client.producer.LocalTransactionState; 8 | import org.apache.rocketmq.client.producer.TransactionListener; 9 | import org.apache.rocketmq.common.message.Message; 10 | import org.apache.rocketmq.common.message.MessageExt; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | 16 | @Service 17 | public class UserRegTransactionListener implements TransactionListener { 18 | 19 | @Autowired 20 | private UserMapper userMapper; 21 | 22 | @Override 23 | @Transactional 24 | public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { 25 | // 从消息体中解析出数据 26 | UserDto userDto = JSON.parseObject(msg.getBody(), UserDto.class); 27 | User user = new User(); 28 | copy(userDto, user); 29 | try { 30 | userMapper.insert(user); 31 | } catch (Throwable e) { 32 | e.printStackTrace(); 33 | // 表示系统异常,向客户端返回失败,可通过明确的 ROLLBACK 指令进行判断 34 | return LocalTransactionState.ROLLBACK_MESSAGE; 35 | } 36 | // 返回 UNKNOW 因为此时事务还没有提交 37 | return LocalTransactionState.UNKNOW; 38 | } 39 | 40 | @Override 41 | public LocalTransactionState checkLocalTransaction(MessageExt msg) { 42 | UserDto userDto = JSON.parseObject(msg.getBody(), UserDto.class); 43 | User queryModel = new User(); 44 | queryModel.setUsername(userDto.getUserName()); 45 | // 根据 用户名(假设唯一,在其他业务场景下可能是订单编号或业务流水号),如果存在,说明本地事务执行成功,可以提交 46 | if(userMapper.selectOne(queryModel) != null ) { 47 | return LocalTransactionState.COMMIT_MESSAGE; 48 | } else { 49 | return LocalTransactionState.UNKNOW; 50 | } 51 | } 52 | 53 | private static void copy(UserDto userDto, User user) { 54 | user.setEmail(userDto.getEmail()); 55 | user.setPassword(userDto.getPassword()); 56 | user.setSex(userDto.getSex()); 57 | user.setUsername(userDto.getUserName()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /transaction/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | 8 | net.codingw 9 | rocketmq-learning 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 14 | transaction-api 15 | transaction-service 16 | transaction-gateway 17 | 18 | 19 | rocketmq-learning-transaction 20 | 21 | pom 22 | 23 | rocketmq-learning-transaction 24 | 25 | http://www.example.com 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | maven-clean-plugin 37 | 3.1.0 38 | 39 | 40 | 41 | maven-resources-plugin 42 | 3.0.2 43 | 44 | 45 | maven-compiler-plugin 46 | 3.8.0 47 | 48 | 49 | maven-surefire-plugin 50 | 2.22.1 51 | 52 | 53 | maven-jar-plugin 54 | 3.0.2 55 | 56 | 57 | maven-install-plugin 58 | 2.5.2 59 | 60 | 61 | maven-deploy-plugin 62 | 2.8.2 63 | 64 | 65 | 66 | maven-site-plugin 67 | 3.7.1 68 | 69 | 70 | maven-project-info-reports-plugin 71 | 3.0.0 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /transaction/transaction-service/src/main/java/net/codingw/rocketmq/learning/transaction/user/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package net.codingw.rocketmq.learning.transaction.user.service.impl; 2 | 3 | import com.alibaba.dubbo.config.annotation.Service; 4 | import com.alibaba.fastjson.JSON; 5 | import net.codingw.rocketmq.learning.transaction.api.user.dto.UserDto; 6 | import net.codingw.rocketmq.learning.transaction.api.user.service.UserService; 7 | import net.codingw.rocketmq.learning.transaction.common.config.TransactionMQProducerContainer; 8 | import net.codingw.rocketmq.learning.transaction.user.mapper.UserMapper; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.apache.rocketmq.client.producer.LocalTransactionState; 11 | import org.apache.rocketmq.client.producer.SendStatus; 12 | import org.apache.rocketmq.client.producer.TransactionSendResult; 13 | import org.apache.rocketmq.common.message.Message; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | @Service 20 | public class UserServiceImpl implements UserService { 21 | @Autowired 22 | private UserMapper userMapper; 23 | 24 | @Autowired 25 | private TransactionMQProducerContainer transactionMQProducerContainer; 26 | 27 | @Autowired 28 | private UserRegTransactionListener userLoginTransactionListener; 29 | 30 | 31 | public Map reg(UserDto userDto) { 32 | Map result = new HashMap<>(); 33 | try { 34 | // 校验参数 35 | checkParam(userDto); 36 | // 事务消息发散,为了方便对消息进行查找,建议对消息加上 key 37 | TransactionSendResult sendResult = transactionMQProducerContainer.getTransactionMQProducer("user_reg_topic", userLoginTransactionListener) 38 | .sendMessageInTransaction(new Message("user_reg_topic",null, userDto.getUserName(), JSON.toJSONString(userDto).getBytes()),null); 39 | 40 | // 事务消息发送成功,返回注册成功,因为是事务消息发送接口是同步调用纺纱,该方法调用结束后,可以根据对状态进行判断业务是否成功 41 | // userRegTransactionListener 的 executeocalTransaction 执行本地方法已经结束 42 | if(sendResult.getSendStatus().equals(SendStatus.SEND_OK) && 43 | !sendResult.getLocalTransactionState().equals(LocalTransactionState.ROLLBACK_MESSAGE)) { 44 | result.put("code", 0); 45 | } else { 46 | result.put("code", 1); 47 | result.put("msg", sendResult.getLocalTransactionState().equals(LocalTransactionState.ROLLBACK_MESSAGE) ? "业务异常" : "系统繁忙"); 48 | } 49 | 50 | } catch (Throwable e) { 51 | e.printStackTrace(); 52 | result.put("code", 1); 53 | result.put("msg", e.getMessage()); 54 | } 55 | return result; 56 | } 57 | 58 | private static void checkParam(UserDto userDto) { 59 | if(StringUtils.isEmpty(userDto.getUserName()) || 60 | StringUtils.isEmpty(userDto.getPassword())) { 61 | throw new RuntimeException("非法参数"); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /transaction/transaction-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | net.codingw 7 | rocketmq-learning-transaction 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | rocketmq-learning-transaction-api 13 | 14 | rocketmq-learning-transaction-api 15 | 16 | http://www.example.com 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | maven-clean-plugin 29 | 3.1.0 30 | 31 | 32 | 33 | maven-resources-plugin 34 | 3.0.2 35 | 36 | 37 | maven-compiler-plugin 38 | 3.8.0 39 | 40 | 41 | maven-surefire-plugin 42 | 2.22.1 43 | 44 | 45 | maven-jar-plugin 46 | 3.0.2 47 | 48 | 49 | maven-install-plugin 50 | 2.5.2 51 | 52 | 53 | maven-deploy-plugin 54 | 2.8.2 55 | 56 | 57 | 58 | maven-site-plugin 59 | 3.7.1 60 | 61 | 62 | maven-project-info-reports-plugin 63 | 3.0.0 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /transaction/transaction-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 4.0.0 7 | 8 | 9 | net.codingw 10 | rocketmq-learning-transaction 11 | 1.0-SNAPSHOT 12 | 13 | 14 | rocketmq-learning-transaction-service 15 | 16 | rocketmq-learning-transaction-service 17 | 18 | http://www.example.com 19 | 20 | 21 | 22 | 23 | 24 | net.codingw 25 | rocketmq-learning-transaction-api 26 | 1.0-SNAPSHOT 27 | 28 | 29 | 30 | com.alibaba.boot 31 | dubbo-spring-boot-starter 32 | 33 | 34 | 35 | org.apache.curator 36 | curator-framework 37 | 38 | 39 | 40 | org.apache.zookeeper 41 | zookeeper 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-web 48 | 49 | 50 | org.apache.commons 51 | commons-lang3 52 | 53 | 54 | 55 | org.apache.rocketmq 56 | rocketmq-client 57 | 58 | 59 | 60 | 61 | 62 | org.mybatis.spring.boot 63 | mybatis-spring-boot-starter 64 | 65 | 66 | 67 | tk.mybatis 68 | mapper-spring-boot-starter 69 | 70 | 71 | 72 | com.github.pagehelper 73 | pagehelper-spring-boot-starter 74 | 75 | 76 | 77 | mysql 78 | mysql-connector-java 79 | 80 | 81 | 82 | junit 83 | junit 84 | 4.11 85 | test 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | maven-clean-plugin 95 | 3.1.0 96 | 97 | 98 | 99 | maven-resources-plugin 100 | 3.0.2 101 | 102 | 103 | maven-compiler-plugin 104 | 3.8.0 105 | 106 | 107 | maven-surefire-plugin 108 | 2.22.1 109 | 110 | 111 | maven-jar-plugin 112 | 3.0.2 113 | 114 | 115 | maven-install-plugin 116 | 2.5.2 117 | 118 | 119 | maven-deploy-plugin 120 | 2.8.2 121 | 122 | 123 | 124 | maven-site-plugin 125 | 3.7.1 126 | 127 | 128 | maven-project-info-reports-plugin 129 | 3.0.0 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | 8 | net.codingw 9 | rocketmq-learning-transaction 10 | 1.0-SNAPSHOT 11 | 12 | 13 | rocketmq-learning-transaction-gateway 14 | 15 | rocketmq-learning-transaction-gateway 16 | 17 | http://www.example.com 18 | 19 | 20 | 21 | 22 | 23 | net.codingw 24 | rocketmq-learning-transaction-api 25 | 1.0-SNAPSHOT 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-tomcat 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-aop 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-test 49 | 50 | 51 | 52 | org.springframework.retry 53 | spring-retry 54 | 55 | 56 | 62 | 63 | 64 | 65 | com.fasterxml.jackson.core 66 | jackson-core 67 | 68 | 69 | com.fasterxml.jackson.core 70 | jackson-databind 71 | 72 | 73 | com.fasterxml.jackson.datatype 74 | jackson-datatype-joda 75 | 76 | 77 | com.fasterxml.jackson.module 78 | jackson-module-parameter-names 79 | 80 | 81 | 82 | 83 | com.alibaba.boot 84 | dubbo-spring-boot-starter 85 | 86 | 87 | 88 | org.apache.curator 89 | curator-framework 90 | 91 | 92 | 93 | org.apache.zookeeper 94 | zookeeper 95 | 96 | 97 | 98 | org.apache.commons 99 | commons-lang3 100 | 101 | 102 | org.springframework.boot 103 | spring-boot-autoconfigure 104 | 2.2.1.RELEASE 105 | 106 | 107 | org.springframework.boot 108 | spring-boot-autoconfigure 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | maven-clean-plugin 120 | 3.1.0 121 | 122 | 123 | 124 | maven-resources-plugin 125 | 3.0.2 126 | 127 | 128 | maven-compiler-plugin 129 | 3.8.0 130 | 131 | 132 | maven-surefire-plugin 133 | 2.22.1 134 | 135 | 136 | maven-jar-plugin 137 | 3.0.2 138 | 139 | 140 | maven-install-plugin 141 | 2.5.2 142 | 143 | 144 | maven-deploy-plugin 145 | 2.8.2 146 | 147 | 148 | 149 | maven-site-plugin 150 | 3.7.1 151 | 152 | 153 | maven-project-info-reports-plugin 154 | 3.0.0 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | net.codingw 6 | rocketmq-learning 7 | 1.0-SNAPSHOT 8 | 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.0.4.RELEASE 14 | 15 | 16 | pom 17 | 18 | rocketmq-learning 19 | http://maven.apache.org 20 | 21 | 22 | transaction 23 | 24 | 25 | 26 | UTF-8 27 | UTF-8 28 | 1.8 29 | 4.0.1 30 | 3.4.13 31 | 0.2.0 32 | 33 | 34 | 35 | 36 | 37 | junit 38 | junit 39 | 3.8.1 40 | test 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | com.alibaba.boot 52 | dubbo-spring-boot-starter 53 | ${dubbo.starter.version} 54 | 55 | 56 | 57 | org.apache.curator 58 | curator-framework 59 | ${curator-framework.version} 60 | 61 | 62 | 63 | org.apache.zookeeper 64 | zookeeper 65 | ${zookeeper.version} 66 | 67 | 68 | 69 | 70 | 71 | org.mybatis.spring.boot 72 | mybatis-spring-boot-starter 73 | 1.3.1 74 | 75 | 76 | 77 | tk.mybatis 78 | mapper-spring-boot-starter 79 | 1.2.4 80 | 81 | 82 | 83 | com.github.pagehelper 84 | pagehelper-spring-boot-starter 85 | 1.2.3 86 | 87 | 88 | 89 | 90 | io.netty 91 | netty-all 92 | 4.1.25.Final 93 | 94 | 95 | 96 | 97 | 98 | org.apache.httpcomponents 99 | httpclient 100 | 4.5.2 101 | 102 | 103 | 104 | org.apache.httpcomponents 105 | httpmime 106 | 4.5.2 107 | 108 | 109 | 110 | 111 | com.zaxxer 112 | HikariCP 113 | 3.2.0 114 | 115 | 116 | com.oracle 117 | ojdbc6 118 | 11.2.0.3 119 | 120 | 121 | 122 | 123 | 124 | commons-io 125 | commons-io 126 | 2.3 127 | 128 | 129 | org.apache.commons 130 | commons-lang3 131 | 3.5 132 | 133 | 134 | net.sourceforge.jexcelapi 135 | jxl 136 | 2.6.12 137 | 138 | 139 | log4j 140 | log4j 141 | 142 | 143 | 144 | 145 | com.alibaba 146 | fastjson 147 | 1.2.67 148 | 149 | 150 | com.thoughtworks.xstream 151 | xstream 152 | 1.4.9 153 | 154 | 155 | com.google.guava 156 | guava 157 | 19.0 158 | 159 | 160 | com.lmax 161 | disruptor 162 | 3.3.7 163 | 164 | 165 | 166 | 167 | org.apache.rocketmq 168 | rocketmq-client 169 | 4.7.1 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | org.springframework.boot 181 | spring-boot-maven-plugin 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /transaction/transaction-gateway/rocketmq-learning-transaction-gateway.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /transaction/transaction-service/rocketmq-learning-transaction-service.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | --------------------------------------------------------------------------------