springboot整合rabbitmq

原创 2018年04月16日 17:56:36

本人通过学习rabbitmq,自己编写的demo,希望大家提出宝贵的建议微笑

模板项目整体结构:


1、配置文件:application.yml

server:
  port: 8089
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    #支持发布确认
    publisher-confirms: true
    
    #支持发布返回
    publisher-returns: true
    listener:
      simple:
      #采用手动应答
        acknowledge-mode: manual
        #当前监听容器数量
        concurrency: 1
        max-concurrency: 1
        #是否支持重试
        retry:

          enabled: true


2、RabbitMQConfig.java 文件  核心

package com.rabbitmqtemplate.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import com.rabbitmqtemplate.callback.MsgSendConfirmCallBack;
import com.rabbitmqtemplate.callback.MsgSendReturnCallback;
import com.rabbitmqtemplate.constants.RabbitMqExchange;
import com.rabbitmqtemplate.constants.RabbitMqQueue;
import com.rabbitmqtemplate.constants.RabbitMqRoutingKey;

/**
 * rabbitmq核心配置
 * @author lishilei
 *
 */
@Configuration
public class RabbitMQConfig {

    @Value("${spring.rabbitmq.host}")
    public String host;
    @Value("${spring.rabbitmq.port}")
    public int port;
    @Value("${spring.rabbitmq.username}")
    public String username;
    @Value("${spring.rabbitmq.password}")
    public String password;
    @Value("${spring.rabbitmq.virtual-host}")
    public String virtualHost;
    @Value("${spring.rabbitmq.publisher-confirms}")
    public Boolean  publisherConfirms;

    /**
     * 创建工厂,自动创建的ConnectionFactory不能完成事件的回调
     *
     * @return
     */
    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPublisherConfirms(publisherConfirms);//手动应答模式
        return connectionFactory;
    }

    /**
     * RabbitTemplate 发送消息,必须是prototype类型,
     * 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置
     *
     * @return
     */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        
        /**若使用confirm-callback或return-callback,
         * 必须要配置publisherConfirms或publisherReturns为true  
         * 每个rabbitTemplate只能有一个confirm-callback和return-callback
         * */  
        template.setConfirmCallback(msgSendConfirmCallBack());  
        template.setReturnCallback(msgSendReturnCallback());
        
        /**  
         * 使用return-callback时必须设置mandatory为true,
         * 或者在配置中设置mandatory-expression的值为true,
         * 可针对每次请求的消息去确定’mandatory’的boolean值,  
         * 只能在提供’return -callback’时使用,与mandatory互斥
         * */  
         template.setMandatory(true); //保证消息的可靠投递
        return template;
    }

    /**
     * 消息确认机制
     * Confirms给客户端一种轻量级的方式,能够跟踪哪些消息被broker处理,
     * 哪些可能因为broker宕掉或者网络失败的情况而重新发布。
     * 确认并且保证消息被送达,提供了两种方式:发布确认和事务。
     * (两者不可同时使用)在channel为事务时,
     * 不可引入确认模式;同样channel为确认模式下,不可使用事务。
     *
     */
    @Bean  
    public MsgSendConfirmCallBack msgSendConfirmCallBack(){  
        return new MsgSendConfirmCallBack();  
    }

    /**
     * 消息未发送到交换机调用
     * @return
     */
    @Bean
    public MsgSendReturnCallback msgSendReturnCallback(){
        return new MsgSendReturnCallback();
    }
    
    @Bean
    public Queue defaultQueue() {
        return new Queue(RabbitMqQueue.QUEUE, true); // 队列持久
    }

    /**
     * 针对消费者配置 FanoutExchange: 将消息分发到所有的绑定队列,
     * 无routingkey的概念 HeadersExchange
     * :通过添加属性key-value匹配 DirectExchange:按照routingkey分发到指定队列
     * TopicExchange:多关键字匹配
     */
    @Bean
    public DirectExchange defaultExchange() {
        return new DirectExchange(RabbitMqExchange.EXCHANGE);
    }

    /**
     * 通过绑定键将队列绑定到指定的交换机上
     * @return
     */
    @Bean
    public Binding binding() {
        return BindingBuilder.bind(defaultQueue()).to(defaultExchange()).with(RabbitMqRoutingKey.ROUTINGKEY);
    }

}

3、constants下文件

package com.rabbitmqtemplate.constants;

/**
 * 交换机配置
 * @author lishilei
 *
 */
public interface RabbitMqExchange {
    String EXCHANGE = "default-exchange";
}

package com.rabbitmqtemplate.constants;

/**
 * 消息队列配置
 * @author lishilei
 *
 */
public interface RabbitMqQueue {
    String QUEUE = "default-queue";
}

package com.rabbitmqtemplate.constants;

/**
 * 路由配置
 * @author lishilei
 *
 */
public interface RabbitMqRoutingKey {
    String ROUTINGKEY = "direct-routingkey";
}


4、callback

package com.rabbitmqtemplate.callback;

import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.support.CorrelationData;

import lombok.extern.slf4j.Slf4j;

/**
 * 确认消息是否成功发送给交换机
 * @author lishilei
 *
 */
@Slf4j
public class MsgSendConfirmCallBack implements ConfirmCallback {

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        log.info(" 回调消息id:" + correlationData);
        if (ack) {
            log.info("消息发送确认成功");
        } else {
            log.info("消息发送确认失败:" + cause+"\n重新发送");

        }
    }
}

package com.rabbitmqtemplate.callback;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;

import lombok.extern.slf4j.Slf4j;

/**
 * 消息回调
 *
 * @author lishilei
 *
 */
@Slf4j
public class MsgSendReturnCallback implements ReturnCallback {

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        String correlationId = message.getMessageProperties().getCorrelationIdString();
        log.info("消息: {} 发送失败,应答码: {} 原因:{} 交换机:{} 路由键:{}", correlationId, replyCode,
                replyText, exchange, routingKey);

    }
}


5、Receiver 消费者

package com.rabbitmqtemplate.consumer;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;
import com.rabbitmqtemplate.constants.RabbitMqQueue;
import com.rabbitmqtemplate.dto.UserDTO;

import lombok.extern.slf4j.Slf4j;

/**
 * 消费者
 * @author lishilei
 *
 */
@Component
@Slf4j
public class Receiver {

    @RabbitListener(queues = RabbitMqQueue.QUEUE)
    public void process(Message message, Channel channel) throws Exception {

        /* 写入当前对象的二进制流   
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        ObjectOutputStream oos = new ObjectOutputStream(bos);  
        oos.writeObject(this);  

                     读出二进制流产生的新对象   
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
        ObjectInputStream ois = new ObjectInputStream(bis);  
        return ois.readObject(); */
        
        //获取传递的消息
        ByteArrayInputStream bi = new ByteArrayInputStream(message.getBody());
        ObjectInputStream oi = new ObjectInputStream(bi);
        UserDTO  obj = (UserDTO) oi.readObject();
        log.info("消费端接收到消息 : " + obj);
        
        // TODO 添加处理消息的业务逻辑
        
        //手动应答,告诉rabbitmq业务执行完成,消息可以丢弃
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        log.info("消息处理成功");

    }

}


6、Sender 生产者

package com.rabbitmqtemplate.sender;

import java.util.UUID;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.rabbitmqtemplate.constants.RabbitMqExchange;
import com.rabbitmqtemplate.constants.RabbitMqRoutingKey;

/**
 * 发送者
 * @author lishilei
 *
 * @param <E>
 */
@Component
public class Sender<E> {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 消息发送
     * @param e
     */
    public void send(E e) {

        String uuid = UUID.randomUUID().toString();
        CorrelationData correlationId = new CorrelationData(uuid);
        rabbitTemplate.convertAndSend(RabbitMqExchange.EXCHANGE, RabbitMqRoutingKey.ROUTINGKEY, e,correlationId);
    }

}


package com.rabbitmqtemplate.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.rabbitmqtemplate.dto.UserDTO;
import com.rabbitmqtemplate.sender.Sender;


7、测试controller

/**
 * 测试controller
 * @Controller 和  @ResponseBody 等价 @RestController
 * @author lishilei
 *
 */
@Controller
@RequestMapping("/rabbbit")
public class SendController{  
 
    @Autowired  
    private Sender<UserDTO> sender;  
 
    @RequestMapping("/direct")  
    @ResponseBody
    public String direct(){
        UserDTO userDTO = new UserDTO();
        userDTO.setAge(24);
        userDTO.setName("alibaba");
        sender.send(userDTO);
        return "消息处理成功";  
    }  
    
}


8、消息体,可自己定义

package com.rabbitmqtemplate.dto;

import java.io.Serializable;

import lombok.Data;

/**
 * 消息体
 * @author lishilei
 *
 */
@Data
public class UserDTO implements Serializable{

    /**
     *
     */
    private static final long serialVersionUID = 3623461501945244407L;

    private String name;
    
    private Integer age;

}

9、SpringBoot 工程启动

package com.rabbitmqtemplate;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RabbitMQApp
{
    public static void main( String[] args )
    {
        SpringApplication.run(RabbitMQApp.class, args);
    }
}

















Struts 原理与应用(一)

本文是俺在公司技术会议上的演讲提纲算是一个小教程吧。Struts 原理与应用 2003年12月1日Chapter 1: MVC Architecture 介绍Struts的理论基础,MVC架构Chap...
  • icecloud
  • icecloud
  • 2003-12-07 22:36:00
  • 1662

RabbitMQ(三)消息确认机制(事务+Confirm)

事务机制RabbitMQ中与事务机制有关的方法有三个,分别是Channel里面的txSelect(),txCommit()以及txRollback(),txSelect用于将当前Channel设置成是...
  • oYueYang1
  • oYueYang1
  • 2017-10-23 15:33:12
  • 97

rabbitmq的集群在java中的应用及源码解析

rabbitmq的集群在java中的应用及源码解析,希望各位能在IT这个行业上越走越远,来自孤独灵魂的小伙伴...
  • MRA__S__
  • MRA__S__
  • 2017-01-20 16:54:31
  • 3301

Spring-amqp 1.6.1 生产者与消费者消息确认配置与使用

1什么是Publisher Confirms and Returns? Delivery processing acknowledgements from consumers to RabbitM...
  • Revivedsun
  • Revivedsun
  • 2016-11-06 17:07:25
  • 5945

rabbitmq丢消息的处理方法

最近发现系统rabbitmq丢消息比较严重,于是想了些方案来查找原因,给将消息发送方式添加确认机制。   我们在本地模拟了wms发送打标消息的场景. 1. 有事务 2. 先发点对点队列, 再发...
  • onlyerlee
  • onlyerlee
  • 2013-12-05 11:31:56
  • 16669

Publisher Confirms and Returns(spring amqp中文翻译)

Publisher Confirms and Returns The RabbitTemplate implementation of AmqpTemplate supports...
  • hbxiang200
  • hbxiang200
  • 2016-08-27 09:53:05
  • 551

spring的RabbitTemplate 发送Message源码导读

spring的RabbitTemplate 发送Message源码导读
  • joeyon
  • joeyon
  • 2014-09-25 22:06:19
  • 7333

spring boot实战(第十二篇)整合RabbitMQ

前言 本篇主要讲述Spring Boot与RabbitMQ的整合,内容非常简单,纯API的调用操作。  消息生产者 不论是创建消息消费者或生产者都需要ConnectionFactory C...
  • liaokailin
  • liaokailin
  • 2015-11-01 16:44:07
  • 64781

【python 爬虫】selenium+phontomjs 用法

程序1:输入病员号,查询病员信息# encoding: utf-8from selenium import webdriver import sys reload(sys) sys.setdefaul...
  • u013421629
  • u013421629
  • 2017-06-15 09:41:27
  • 876

Android通过外部浏览器调用微信H5支付,Android+PHP详解

看了好多关于讲解微信H5支付开发的文章,大多数都是通过微信内部浏览器来调用支付接口(其实就是公众号支付),可能是因为H5支付接口刚开放不久吧。 微信官方体验链接:http://wxpay.wxu...
  • t6546545
  • t6546545
  • 2017-08-16 23:44:11
  • 4121
收藏助手
不良信息举报
您举报文章:springboot整合rabbitmq
举报原因:
原因补充:

(最多只允许输入30个字)