开源地址
https://gitee.com/tech-famer/reliablemessage-spring-boot-starter
介绍
这是一款基于RabbitMQ的confirm和return回调机制实现的SpringBoot可靠消息组件,支持事务消息、消息回滚、失败重发等功能。
安装教程
组件有三种安装方式
- 通过maven命令:
mvn clean package deploy
将项目发布到私有仓库,在使用的项目中加入组件依赖,如下:
<depandency>
<groupId>com.farmer.reliablemessage</groupId>
<artifactId>reliablemessage-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</depandency>
- 通过maven命令:
mvn clean package install
将项目发布到本地仓库,在使用的本地项目中加入组件依赖,如下:
<depandency>
<groupId>com.farmer.reliablemessage</groupId>
<artifactId>reliablemessage-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</depandency>
- 将项目源码直接拷贝到需要的项目中直接使用。
使用说明
- 组件会将消息入库,消息数据库主键为VARCHAR()类型,使用者需要提供生成主键的spring bean,该spring bean需要实现接口
com.farmer.reliablemessage.api.IDApi
;组件内置了默认主键生成类com.farmer.reliablemessage.DefaultIDApi
,算法为UUID,使用者可以自行实现主键生成算法,如雪花算法等。以下仅为示例:
@Configuration
public class IdConfig {
@Bean
public IDApi idApi(){
return new IDApi() {
@Override
public String nextID() {
return UUID.randomUUID().toString().replace("-","");
}
};
}
}
- 在需要发送消息的类中引入可靠消息组件提供的MQTemplate,如下:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Transactional
public void test(){
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
}
}
组件只提供一个方法saveAndSendMessage,参数1为交换机名称,参数2为routingKey,参数3为消息体。
场景演示
- 普通消息
在普通方法中使用组件发送的消息即为普通消息,普通消息会立即投递到消息中间件,普通消息无法回滚。如:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
public void test(){
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
// TODO 其他代码
}
}
其他代码中出现异常,消息仍然会被投递到消息中间件。
- 事务消息
顾名思义消息支持事务。在事务中方法使用组件发送消息,消息不会立即投递,在事务提交后消息才会投递,如果事务回滚消息也将回滚而不会被投递。
2.1 简单事务方法,如下:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Transactional
public void test(){
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
// TODO 其他代码
}
}
消息在其他代码执行完事务提交后,消息投递到消息中间件;其他代码出现运行时异常时,消息会回滚而不被投递到消息中间件。
2.2 事务方法调用非事务方法,如下:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Transactional
public void test(){
//消息1
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
orther();
// TODO 其他代码
}
public void orther(){
//消息2
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
}
}
消息1、2在test方法执行完事务提交后投递到消息中间件;其他代码或者orther方法中出现运行时异常时,消息会回滚而不被投递到消息中间件。
2.3 事务方法调用事务方法情况一,如下:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Autowired
@Lazy
private TestService testService;
@Transactional
public void test(){
//消息1
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
testService.orther();
// TODO 其他代码
}
@Transactional(propagation = Propagation.REQUIRED)
public void orther(){
//消息2
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
}
}
消息1、2在test方法执行完事务提交后投递到消息中间件;其他代码或者orther方法中出现运行时异常时,消息会回滚而不被投递到消息中间件。
2.4 事务方法调用事务方法情况二,如下:
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Autowired
@Lazy
private TestService testService;
@Transactional
public void test(){
//消息1
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
testService.orther();
// TODO 其他代码
}
@Transactional(propagation = Propagation.REQUIRED_NEW)
public void orther(){
//消息2
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
}
}
消息2在orther方法执行完事务提交后投递到消息中间件;消息1在test方法执行完事务提交后投递到消息中间件;其他代码或者orther方法中出现运行时异常时,消息会回滚而不被投递到消息中间件。
2.5 消息回滚
@Service
public class TestService {
@Autowired
private MQTemplate mqTemplate;
@Autowired
@Lazy
private TestService testService;
@Transactional
public void test(){
//消息1
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
testService.orther();
// TODO 其他代码
}
@Transactional(propagation = Propagation.REQUIRED)
public void orther(){
//消息2
mqTemplate.saveAndSendMessage("exchangeName","routingKey","payload");
int i = 1/0;
}
}
语句int i = 1/0;
运行时异常导致事务回滚,消息1、2会随着事务一起回滚不会投递到消息中间件。