spring+activemq的使用

上代码

一、生产者端:

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", 可以指定也可以不指定,不指定也会走注册的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值