使用Spring AMQP

本文使用spring boot作为框架,使用spring framework也可以参考。

前提

安装部署并启动rabbitmq,参见 http://www.jianshu.com/p/9a32dca0c6aa

配置连接

constant.properties:

spring.rabbitmq.addresses=192.168.253.133:5672,192.168.253.134:5672
spring.rabbitmq.username=rabbitmq
spring.rabbitmq.password=rabbitmq
# 每个连接缓存channel的数量
spring.rabbitmq.cachesize=25

配置maven依赖

pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<dependencyManagement>
    <dependencies>
    </dependencies>
</dependencyManagement>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.4.RELEASE</version>
</parent>

<dependencies>
    <!-- 引入spring amqp -->
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
    </dependency>

    <!-- 引入spring boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 引入spring boot单元测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency> 
    
</dependencies>

配置

RabbitConfig .java:

@Configuration
public class RabbitConfig {

    @Autowired
    private Environment env;

    /**
     * 连接工厂
     */
    @Bean
    public ConnectionFactory connectionFactory() {

        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(env.getProperty("spring.rabbitmq.addresses"));
        connectionFactory.setUsername(env.getProperty("spring.rabbitmq.username"));
        connectionFactory.setPassword(env.getProperty("spring.rabbitmq.password"));
        // connectionFactory.setCacheMode(CacheMode.CHANNEL);//默认是CHANNEL
        connectionFactory.setChannelCacheSize(
                Integer.parseInt(env.getProperty("spring.rabbitmq.cachesize")));
        // 开启发布者确认
        // connectionFactory.setPublisherConfirms(true);
        // 开启发布者返回
        // connectionFactory.setPublisherReturns(true);
        return connectionFactory;
    }

    /**
     * 自定义管理类,负责管理声明队列、交换机等管理功能,spring amqp默认开启自动声明
     */
    @Bean
    public RabbitAdmin rabbitAdmin() {

        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
        return rabbitAdmin;
    }

    /**
     * 模板类,主要负责发送接收
     */
    @Bean
    public RabbitTemplate rabbitTemplate() {

        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
        return rabbitTemplate;
    }

    /**
     * direct类型交换机,只有精确匹配routing key的队列才能收到消息,且消息按一定规则分配,即一条消息只会被其中一个队列接收到
     */
    @Bean
    public Exchange directExchange() {

        return ExchangeBuilder.directExchange("shark.direct").durable(true).build();
    }

    /**
     * fanout类型交换机,类似于广播,所有绑定的队列均收到所有消息
     */
    @Bean
    public Exchange fanoutExchange() {

        return ExchangeBuilder.fanoutExchange("shark.fanout").durable(true).build();
    }

    /**
     * topic类型交换机,与direct类型相似,不过topic类型支持模糊匹配。# *
     */
    @Bean
    public Exchange topicExchange() {

        return ExchangeBuilder.topicExchange("shark.topic").durable(true).build();
    }

    /**
     * 自定义队列1
     */
    @Bean
    public Queue infoQueue() {

        return QueueBuilder.durable("shark.info").build();
    }

    /**
     * 自定义队列2
     */
    @Bean
    public Queue errorQueue() {

        return QueueBuilder.durable("shark.error").build();
    }

    /**
     * 绑定队列1到fanout交换机
     */
    @Bean
    public Binding bindingFanoutAnony() {

        return BindingBuilder.bind(errorQueue()).to(fanoutExchange()).with("").noargs();
    }

    /**
     * 绑定队列2到fanout交换机
     */
    @Bean
    public Binding bindingFanoutAnony2() {

        return BindingBuilder.bind(infoQueue()).to(fanoutExchange()).with("").noargs();
    }

    /**
     * 绑定自定义队列1到direct交换机
     * 
     * @Primary 设置为默认的bean,注入时@Autowired 或未指定名称的@Resource将使用默认的bean
     */
    @Primary
    @Bean
    public Binding bindingDirect1() {

        return BindingBuilder.bind(infoQueue()).to(directExchange()).with("shark.info").noargs();
    }

    /**
     * 绑定自定义队列2到direct交换机
     */
    @Bean
    public Binding bindingDirect2() {

        return BindingBuilder.bind(errorQueue()).to(directExchange()).with("shark.error").noargs();
    }

    /**
     * 绑定自定义队列1到topic交换机
     */
    @Bean
    public Binding bindingTopic1() {

        return BindingBuilder.bind(errorQueue()).to(topicExchange()).with("shark.*").noargs();
    }

    /**
     * 绑定自定义队列2到topic交换机
     */
    @Bean
    public Binding bindingTopic2() {

        return BindingBuilder.bind(infoQueue()).to(topicExchange()).with("shark.*").noargs();
    }

}

启动Spring boot应用

Application.java

@SpringBootApplication(exclude = RabbitAutoConfiguration.class) //排除spring boot自动注入
@EnableAspectJAutoProxy(proxyTargetClass = true) // 激活Aspect自动代理
@PropertySource({ "classpath:/cn/com/ut/config/properties/constant.properties" })
public class Application {
    public static void main(String[] args) {

        SpringApplication application = new SpringApplication(Application.class);
        application.setBannerMode(Banner.Mode.LOG);
        application.run(args);
    }
}

测试

TestSendController.java

@RestController
@RequestMapping(value = "/test")
public class TestSendController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Resource(name = "fanoutExchange")
    private Exchange fanoutExchange;

    @Resource(name = "bindingDirect1")
    private Binding bindingDirect1;

    @Resource(name = "bindingDirect2")
    private Binding bindingDirect2;

    @Resource(name = "topicExchange")
    private Exchange topicExchange;

    /**
     * 广播消息到多个队列,所有队列均接收全部消息
     */
    @GetMapping("/sendFanout")
    public String sendFanout(@RequestParam(value = "msg", required = false) final String msg) {

        new Thread(new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i < 10; i++) {
                    rabbitTemplate.convertAndSend(fanoutExchange.getName(),
                            "msg" + i + " : " + msg);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return "success send 10 msg to fanout Exchange!";
    }

    /**
     * 均衡分配消息多个队列,队列收到的消息预其他队列不一样(精确匹配)
     */
    @GetMapping("/sendDirect")
    public String sendDirect(@RequestParam(value = "msg", required = false) final String msg) {

        // rabbitTemplate.convertAndSend(bindingDirect1.getExchange(),
        // bindingDirect1.getRoutingKey(),
        // "msg-1:" + msg);
        // rabbitTemplate.convertAndSend(bindingDirect2.getExchange(),
        // bindingDirect2.getRoutingKey(),
        // "msg-2:" + msg);

        new Thread(new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i < 10; i++) {
                    rabbitTemplate.convertAndSend(bindingDirect1.getExchange(), "shark.info",
                            "msg" + i + " : " + msg);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return "success send 10 msg to topic Exchange!";
    }

    /**
     * 均衡分配消息多个队列,队列收到的消息预其他队列不一样(模糊匹配)
     */
    @GetMapping("/sendTopic")
    public String sendTopic(@RequestParam(value = "msg", required = false) final String msg) {

        new Thread(new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i < 10; i++) {
                    rabbitTemplate.convertAndSend(topicExchange.getName(), "shark.info",
                            "msg" + i + " : " + msg);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return "success send 10 msg to topic Exchange!";
    }

    /******************** 接收(同步) ****************** */
    @GetMapping("/receive")
    public String receive(@RequestParam(value = "queue") String queueName) {

        String msg = " 收到來自队列 " + queueName + "的消息:"
                + (String) rabbitTemplate.receiveAndConvert(queueName);
        return msg;
    }
}

监听器接收

  1. RabbitConfig .java 添加@EnableRabbit注解和SimpleRabbitListenerContainerFactory 的bean
@Configuration
@EnableRabbit
public class RabbitConfig {
        /**
     * 消息接收监听器容器工厂,需要开启@EnableRabbit注解
     */
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {

        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setConcurrentConsumers(3);
        factory.setMaxConcurrentConsumers(10);
        return factory;
    }
}
  1. TestSendController.java 添加监听器
/******************** 接收监听器****************** */
@RabbitListener(queues = "#{infoQueue.name}")
public void receive3(String reciveMsg) {

    System.out.println("receive1(订阅了infoQueue) 收到信息:" + reciveMsg);
}

@RabbitListener(queues = "#{errorQueue.name}")
public void receive4(String reciveMsg) {

    System.out.println("receive2(订阅了errorQueue) 收到信息:" + reciveMsg);
}

@RabbitListener(queues = "#{infoQueue.name}")
public void receive5(String reciveMsg) {

    System.out.println("receive3(订阅了infoQueue) 收到信息:" + reciveMsg);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,300评论 6 344
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,292评论 18 399
  • 一直想提笔写点什么,又怕熟悉的人洞察,怕别人失望。今天又是凌晨4点醒来,我之害怕怕的是什么?原生家庭...
    追风的喵阅读 105评论 0 0
  • 相关标签:Shopify 收款 开店 1 :Shopfiy设置用信用卡付款时,用什么作为支持信用卡网关? 2 :S...
    Shopify_问答君阅读 6,038评论 0 2