java springAMQP-1.6 rabbitmq-3.6.3

1. spring 和 amqp版本   

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.1.RELEASE</version>
    </dependency>
</dependencies>
<dependencies>
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>1.6.0.RELEASE</version>
    </dependency>
</dependencies>

2. 配置

<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/rabbit
     http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
	<!--配置connection-factory,指定连接rabbit server参数 -->
	<rabbit:connection-factory id="connectionFactory"
		username="admin" password="111111" host="123.56.99.80" port="5672" />

	<!--定义rabbit template用于数据的接收和发送 -->
	<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
		exchange="myDirectExchange" routing-key="mq.test" />

	<!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
	<rabbit:admin connection-factory="connectionFactory" />

	<!--定义queue -->
	<rabbit:queue name="myQueue" durable="true" auto-delete="false"
		exclusive="false" />

	<!-- 定义direct exchange,绑定queueTest -->
	<rabbit:direct-exchange name="myDirectExchange"
		durable="true" auto-delete="false">
		<rabbit:bindings>
			<rabbit:binding queue="myQueue" key="mq.test" />
		</rabbit:bindings>
	</rabbit:direct-exchange>

<!-- 	<rabbit:topic-exchange name="myTopicExchange"> -->
<!-- 		<rabbit:bindings> -->
<!-- 			<rabbit:binding queue="myQueue" pattern="mq.*" /> -->
<!-- 		</rabbit:bindings> -->
<!-- 	</rabbit:topic-exchange> -->

	<!-- 消息接收者 -->
	<bean id="consumer" class="com.zybros.consumer.Consumer"></bean>

	<bean id="consumer2" class="com.zybros.consumer.Consumer2"></bean>

	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
	<rabbit:listener-container
		connection-factory="connectionFactory">
		<rabbit:listener queues="myQueue" ref="consumer" />
		<!-- consumer 若想不实现MessageListener,可以用下面的 method指定, 个人认为这方式不错,consumer只是一个普通类就可以,侵入性低 -->
		<!-- <rabbit:listener queue-names="myQueue" method="consume" ref="consumer2"/> -->
	</rabbit:listener-container>

</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">


	<import resource="classpath*:rabbitmq.xml" />
	
	
	<!-- 扫描指定package下所有带有如@controller,@services,@resource,@ods并把所注释的注册为Spring Beans -->
	<context:component-scan base-package="com.zybros.consumer,com.zybros.producer" />
	

		
	<!-- 激活annotation功能 -->
	<context:annotation-config />
	<!-- 激活annotation功能 -->
	<context:spring-configured />

    
  	
</beans>

3. 代码

package com.zybros.producer;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;

import com.zybros.bean.User;

@Service
public class Producer {

	private Logger logger = LoggerFactory.getLogger(Producer.class);

	@Resource
	private AmqpTemplate amqpTemplate;

	public void produce(User user) {
		logger.info("++++++++++++++++++++++++++");
		logger.info("****** produce user: "+user.getName());
//		//此处的routingkey 没有在xml中配置
//		amqpTemplate.convertAndSend("queueKey", user);
		//此处的routingkey 在xml中已经配置
		amqpTemplate.convertAndSend(user);
	}
}

package com.zybros.consumer;


import org.apache.commons.lang3.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import com.zybros.bean.User;


public class Consumer<E> implements MessageListener {
	
	private Logger logger = LoggerFactory.getLogger(Consumer.class);

	@Override
	public void onMessage(Message message) {
		logger.info("--------------");
		User u = SerializationUtils.deserialize(message.getBody());
		logger.info("****** consumer user: "+u.getName());
		logger.info("****** consumer messageProperties: "+message.getMessageProperties());
	}

}

package com.zybros.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zybros.bean.User;
import com.zybros.producer.Producer;

public class MQTest {

	static ApplicationContext context = null;

	public static void main(String[] s) {
		try {
			context = new ClassPathXmlApplicationContext("application.xml");
			test1();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void test1() throws Exception {
		Producer producer = (Producer) context.getBean("producer");
		int a = Integer.MAX_VALUE;
		while (a > 0) {
			User u = new User("name: " + a, "addr: " + a, a);
			producer.produce(u);
			a--;
			try {
				// 暂停一下,好让消息消费者去取消息打印出来
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
	}

	// public static void test2() throws Exception {
	// Producer2 producer = (Producer2) context.getBean("producer2");
	// int a = Integer.MAX_VALUE;
	// while (a > 0) {
	// User u = new User("name2: "+a,"addr2: "+a,a);
	// producer.produce(u);
	// try {
	// //暂停一下,好让消息消费者去取消息打印出来
	// Thread.sleep(3000);
	// } catch (InterruptedException e) {
	// e.printStackTrace();
	// }
	//
	// }
	// }
}

4:输出结果



============================================================

consumer 若想不实现MessageListener,可以用下面的 method指定, 个人认为这方式不错,consumer只是一个普通类就可以,侵入性低


如下


package com.zybros.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zybros.bean.User;

public class Consumer2<E>{
	
	private Logger logger = LoggerFactory.getLogger(Consumer2.class);

	public void consume(Object obj) {
		User u = (User) obj;
		logger.info("--------------");
		logger.info("--------------");
		logger.info(obj.toString());
		logger.info(u.getName());
	}

}


对应的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/rabbit
     http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
	<!--配置connection-factory,指定连接rabbit server参数 -->
	<rabbit:connection-factory id="connectionFactory"
		username="admin" password="111111" host="123.56.99.80" port="5672" />

	<!--定义rabbit template用于数据的接收和发送 -->
	<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
		exchange="myDirectExchange" routing-key="mq.test" />

	<!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
	<rabbit:admin connection-factory="connectionFactory" />

	<!--定义queue -->
	<rabbit:queue name="myQueue" durable="true" auto-delete="false"
		exclusive="false" />

	<!-- 定义direct exchange,绑定queueTest -->
	<rabbit:direct-exchange name="myDirectExchange"
		durable="true" auto-delete="false">
		<rabbit:bindings>
			<rabbit:binding queue="myQueue" key="mq.test" />
		</rabbit:bindings>
	</rabbit:direct-exchange>

<!-- 	<rabbit:topic-exchange name="myTopicExchange"> -->
<!-- 		<rabbit:bindings> -->
<!-- 			<rabbit:binding queue="myQueue" pattern="mq.*" /> -->
<!-- 		</rabbit:bindings> -->
<!-- 	</rabbit:topic-exchange> -->

	<!-- 消息接收者 -->
	<bean id="consumer" class="com.zybros.consumer.Consumer"></bean>

	<bean id="consumer2" class="com.zybros.consumer.Consumer2"></bean>

	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
	<rabbit:listener-container
		connection-factory="connectionFactory">
<!-- 		<rabbit:listener queues="myQueue" ref="consumer" /> -->
		<!-- consumer 若想不实现MessageListener,可以用下面的 method指定, 个人认为这方式不错,consumer只是一个普通类就可以,侵入性低 -->
		<rabbit:listener queue-names="myQueue" method="consume" ref="consumer2"/>
	</rabbit:listener-container>

</beans>


5. 总结

逻辑

1.  template  在发送消息时,指定对应的exchange,并设定routingkey。

2. 因在设置exchage时,binding中设置了 queue 同  key或者 pattern 的映射。因此会根据routingkey binding到对应的queue。

3. listenner-containner中设置的 listener 根据监听的queue 调用 consumer。


不足

这种监听模式感觉有一定的缺陷,正常情况下,producer生产到mq中的msg后,consumer监听到后调用对应的方法进行消费。 但若监听的consumer出了问题,不能正常进行消费,除了msg在mq中大量积压,造成一些消息一直在mq中,consumer却不知道,这也是一种消息的丢失。

当然可以用原始的方式去mq中主动读取msg,弥补解决这种问题,若是这样就没必要用listener。

另因本人没有细看springAMQP中的listener源码,只是在看console日志时,发现日志是每一秒执行一次Retrieving,若是这样感觉算不上好的listener。


估计应该只是日志本身的retrieving,spring的大牛不会犯这么低级的错误。

之后抽时间看下listener,再进行更正。



6. 代码 

原demo 代码地址 http://download.csdn.net/detail/stonexmx/9572076


 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值