上代码
一、生产者端:
1、需要的pom依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mq -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.11.1</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
2、配置application.yaml文件
spring:
application:
name: mq-provider
activemq:
broker-url: tcp://127.0.0.1:61616
user: admin
password: admin
pool:
enabled: true
max-connections: 100
3、注册配置信息
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.jms.Queue;
/**
* 生产者消息配置
*/
@Configuration
public class ActiveMQConfig {
@Value("${spring.activemq.broker-url}")
private String brokeUrl;
/**
* 多个队列的时候可以根据bean的name来区分bean
* @return
*/
@Bean(name = "defaultQueue")
public Queue queue1(){
//指定队列名,可配置
return new ActiveMQQueue("ActiveMQQueue");
}
@Bean(name = "queue2")
public Queue queue2(){
//指定队列名,可配置
return new ActiveMQQueue("MyQueue");
}
@Bean
public ActiveMQConnectionFactory connectionFactory(){
return new ActiveMQConnectionFactory(brokeUrl);
}
}
4、创建生产者任务,这里是模拟的定时执行发送消息
import com.alibaba.fastjson.JSON;
import com.kevin.dao.TblEventDao;
import com.kevin.entity.TblEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.jms.Queue;
import java.util.List;
/**
* 生产者任务
*
*/
@Component
public class ProducerTask {
@Autowired
private TblEventDao tblEventDao;
/**
* Resource注解,指定name的队列bean进行发送消息
* 如果使用Autowired注解的话,需要额外使用Qualifier注解指定name
* @Autowired
* @Qualifier("queue2")
*
*/
@Resource(name = "queue2")
private Queue queue;
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
/**
* @Scheduled 定时任务注解,这里定的是5秒一次
* @Transactional 保证事务
*/
@Scheduled(cron = "0/5 * * * * ?")
@Transactional(rollbackFor = Exception.class)
public void task(){
System.out.println("定时任务执行");
//模拟从库中查处指定状态的数据
List<TblEvent> tblEvents = tblEventDao.selectByType("1");
for(int i=0;i<tblEvents.size();i++){
TblEvent tblEvent = tblEvents.get(i);
//查出来之后更新状态表
tblEventDao.updateType(tblEvent.getType());
//发送消息
jmsMessagingTemplate.convertAndSend(queue, JSON.toJSONString(tblEvent));
System.out.println("发送成功");
}
}
}
5、在启动类中添加@EnableJms注解,因为示例中使用到了定时任务,所以也需要添加@EnableScheduling注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableJms
@EnableScheduling
public class MqProviderApplication {
public static void main(String[] args) {
SpringApplication.run(MqProviderApplication .class, args);
}
}
至此,生产者完成。
二、消费者端
1、依赖 跟生产者端一样
2、yaml文件跟生产者端一样
3、注册消费者消息配置
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.stereotype.Component;
/**
* 消费者mq配置
*
*/
@Component
public class ActiveMQConfig {
@Value("${spring.activemq.user}")
private String username;
@Value("${spring.activemq.password}")
private String password;
@Value("${spring.activemq.broker-url}")
private String brokerUrl;
/**
* 配置链接工厂
* @param redeliveryPolicy
* @return
*/
@Bean
public ActiveMQConnectionFactory activeMQConnectionFactory(RedeliveryPolicy redeliveryPolicy){
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(username, password, brokerUrl);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
return activeMQConnectionFactory;
}
/**
* 配置重发策略
* @return
*/
@Bean
public RedeliveryPolicy redeliveryPolicy(){
return new RedeliveryPolicy();
}
/**
* 配置消息监听工厂 并设置ack为手动确认机制
* @param activeMQConnectionFactory
* @return
*/
@Bean
public JmsListenerContainerFactory jmsListenerContainerFactory(ActiveMQConnectionFactory activeMQConnectionFactory){
DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
defaultJmsListenerContainerFactory.setConnectionFactory(activeMQConnectionFactory);
//指定ack模式,1:自动确认 2:客户端手动确认 3:自动批量确认 4:事务提交并确认
defaultJmsListenerContainerFactory.setSessionAcknowledgeMode(2);
//指定监听的并发数 最大处理10个并发
defaultJmsListenerContainerFactory.setConcurrency("10");
return defaultJmsListenerContainerFactory;
}
}
4、创建消费者,监听队列
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kevin.dao.TblEventDao;
import com.kevin.entity.TblEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
/**
* 消费者队列处理
*/
@Component
public class ConsumerQueue {
@Autowired
private TblEventDao tblEventDao;
/**
* 使用 @JmsListener 注解,destination指定队列名称,需要跟生产者的ActiveMQQueue的name相对应
* 可以使用${my.activemq.queuename}读取配置文件中配置的名称,也可以直接写死指定队列名
* 本例yaml中配置的是
* my:
* activemq:
* queuename: MyQueue
* containerFactory = "jmsListenerContainerFactory", 可以指定也可以不指定,不指定也会走注册的
* @param textMessage
* @param session
*/
@JmsListener(destination = "${my.activemq.queuename}")
public void receive(TextMessage textMessage, Session session) {
try {
String text = textMessage.getText();
System.out.println("收到消息:" + text);
TblEvent tblEvent = JSONObject.toJavaObject((JSON) JSONObject.parse(text), TblEvent.class);
tblEventDao.insert(tblEvent);
//业务完成,确认消息,消费成功
textMessage.acknowledge();
System.out.println("业务处理完成,已确认消息");
} catch (Exception e) {
e.printStackTrace();
String message = e.getMessage();
System.out.println("异常了:" + message);
try {
session.recover();
} catch (JMSException e1) {
e1.printStackTrace();
}
}
}
/**
* 消费死信队列(消费6次失败的消息会被放入死信队列),根据自己实际业务情况来处理
*
* @param textMessage
*/
@JmsListener(destination = "DLQ.ActiveMQQueue")
public void receiveDeadLetter(TextMessage textMessage) {
try {
System.out.println("死信队列消息: " + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
5、在启动类上添加@EnableJms
至此,消费者结束。
这里需要注意的是:
消费者使用 @JmsListener 注解,其中destination指定队列名称,需要跟生产者的ActiveMQQueue的name相对应
可以使用${my.activemq.queuename}读取配置文件中配置的名称,也可以直接写死指定队列名, containerFactory = "jmsListenerContainerFactory", 可以指定也可以不指定,不指定也会走注册的。