在Spring AMQP项目中Spring也提供了对RabbitMQ的支持,这里在之前学习SpringBoot的时候也整合过,但是今天这里使用的Spring的xml配置来整个rabbit.
Spring AMQP项目地址:https://spring.io/projects/spring-amqp;
下面来看看使用方式。
1. 引入依赖
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rabbitmq.wangx</groupId> <artifactId>rabbitmq</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>rabbitmq Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <maven.test.failure.ignore>true</maven.test.failure.ignore> <spring.framework.version>4.3.9.RELEASE</spring.framework.version> <spring.amqp.version>2.1.1.RELEASE</spring.amqp.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <maven.test.failure.ignore>false</maven.test.failure.ignore> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.5.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.8.0-beta2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.8.0-beta2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.framework.version}</version> <exclusions> <!-- Exclude Commons Logging in favor of SLF4j --> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.framework.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.22</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.22</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.22</version> <scope>runtime</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-amqp</artifactId> <version>${spring.amqp.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>${spring.amqp.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <finalName>rabbitmq</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
2. 配置基础信息
rabbitMQ.xml
<?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/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配置connection--> <rabbit:connection-factory id="connectionFactory" host="127.0.0.1" port="5672" username="wangx" password="wangx" virtual-host="/wangx"/> <!--使用admin管理factory--> <rabbit:admin connection-factory="connectionFactory"/> <!--定义模板,并指定交换机或queue--> <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" exchange="spring-exchange"/> <!--定义消费者所对应的key--> <rabbit:queue name="spring-queue" auto-declare="true"/> <!--声明fanout的交换机--> <rabbit:fanout-exchange name="spring-exchange" auto-declare="true"> <rabbit:bindings> <rabbit:binding queue="spring-queue"/> </rabbit:bindings> </rabbit:fanout-exchange> <!--声明监听容器--> <rabbit:listener-container connection-factory="connectionFactory"> <!--指定监听器所对应的bean和方法--> <rabbit:listener ref="consumer" method="listen" queue-names="spring-queue"/> </rabbit:listener-container> <!--消费者监听方法--> <bean id="consumer" class="com.wangx.rabbitmq.spring.Consumer"/> </beans>
消费者:
Consumer
package com.wangx.rabbitmq.spring; public class Consumer { //对应监听器中所指定的method public void listen(String msg) { System.out.println("Spring Consumer 接收到消息:" + msg); } }
发送消息:
package com.wangx.rabbitmq.spring; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Producer { public static void main(String[] args) { //读取配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("rabbitMQ.xml"); //获取模板类 RabbitTemplate template = context.getBean(RabbitTemplate.class); String str = "Spring-message"; //构建MessageProperties对象 MessageProperties messageProperties = new MessageProperties(); //设置参数 messageProperties.setContentEncoding("UTF-8"); messageProperties.setContentType("text/plain"); //构建消息对象 Message message = new Message(str.getBytes(), messageProperties); //使用模板发送消息 template.send(message); } }
注意:
messageProperties.setContentEncoding("UTF-8"); messageProperties.setContentType("text/plain");
这两个参数必须要配置,否则会报如下异常:
D:\devsoft\jdk1.8\jdk1.8\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:58888,suspend=y,server=n -javaagent:C:\Users\xing.wang\.IntelliJIdea2018.1\system\captureAgent\debugger-agent.jar=file:/C:/Users/xing.wang/AppData/Local/Temp/capture.props -Dfile.encoding=UTF-8 -classpath "D:\devsoft\jdk1.8\jdk1.8\jre\lib\charsets.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\deploy.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\cldrdata.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\dnsns.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\jaccess.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\jfxrt.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\localedata.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\nashorn.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\sunec.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\ext\zipfs.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\javaws.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\jce.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\jfr.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\jfxswt.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\jsse.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\management-agent.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\plugin.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\resources.jar;D:\devsoft\jdk1.8\jdk1.8\jre\lib\rt.jar;D:\dev-idea\middle\rabbitmq\target\classes;D:\repository\com\rabbitmq\amqp-client\5.5.0\amqp-client-5.5.0.jar;D:\repository\org\slf4j\slf4j-api\1.7.22\slf4j-api-1.7.22.jar;D:\repository\org\slf4j\slf4j-simple\1.8.0-beta2\slf4j-simple-1.8.0-beta2.jar;D:\repository\org\springframework\spring-core\4.3.9.RELEASE\spring-core-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-context\4.3.9.RELEASE\spring-context-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-aop\4.3.9.RELEASE\spring-aop-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-beans\4.3.9.RELEASE\spring-beans-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-expression\4.3.9.RELEASE\spring-expression-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-messaging\4.3.9.RELEASE\spring-messaging-4.3.9.RELEASE.jar;D:\repository\org\springframework\spring-tx\4.3.9.RELEASE\spring-tx-4.3.9.RELEASE.jar;D:\repository\cglib\cglib-nodep\2.2\cglib-nodep-2.2.jar;D:\repository\org\slf4j\jcl-over-slf4j\1.7.22\jcl-over-slf4j-1.7.22.jar;D:\repository\org\slf4j\slf4j-log4j12\1.7.22\slf4j-log4j12-1.7.22.jar;D:\repository\log4j\log4j\1.2.14\log4j-1.2.14.jar;D:\repository\org\springframework\amqp\spring-amqp\2.1.1.RELEASE\spring-amqp-2.1.1.RELEASE.jar;D:\repository\org\springframework\retry\spring-retry\1.2.2.RELEASE\spring-retry-1.2.2.RELEASE.jar;D:\repository\org\springframework\amqp\spring-rabbit\2.1.1.RELEASE\spring-rabbit-2.1.1.RELEASE.jar;D:\devsoft\idea\IntelliJ IDEA 2018.1.4\lib\idea_rt.jar" com.wangx.rabbitmq.spring.Producer Connected to the target VM, address: '127.0.0.1:58888', transport: 'socket' INFO [t.support.ClassPathXmlApplicationContext]: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3fee9989: startup date [Mon Nov 19 16:22:38 CST 2018]; root of context hierarchy INFO [eans.factory.xml.XmlBeanDefinitionReader]: Loading XML bean definitions from class path resource [rabbitMQ.xml] INFO [ontext.support.DefaultLifecycleProcessor]: Starting beans in phase 2147483647 INFO [bbit.connection.CachingConnectionFactory]: Attempting to connect to: 127.0.0.1:5672 INFO [bbit.connection.CachingConnectionFactory]: Created new connection: connectionFactory#47caedad:0/SimpleConnection@2c4d1ac [delegate=amqp://wangx@127.0.0.1:5672//wangx, localPort= 58894] WARN [istener.ConditionalRejectingErrorHandler]: Execution of Rabbit message listener failed. org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Failed to invoke target method 'listen' with argument type = [class [B], value = [{[B@3f099764}] at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:387) at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:292) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1511) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1434) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1421) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1400) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:848) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:832) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:78) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1073) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NoSuchMethodException: com.wangx.rabbitmq.spring.Consumer.listen([B) at java.lang.Class.getMethod(Class.java:1786) at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:174) at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:365) ... 10 more WARN [ingErrorHandler$DefaultExceptionStrategy]: Fatal message conversion error; message rejected; it will be dropped or routed to a dead letter exchange, if so configured: (Body:'[B@3f099764(byte[14])' MessageProperties [headers={}, contentType=application/octet-stream, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=spring-exchange, receivedRoutingKey=, deliveryTag=1, consumerTag=amq.ctag-ZbVlvRKHCdm3KFhzW5uu8A, consumerQueue=spring-queue]) ERROR [.listener.SimpleMessageListenerContainer]: Execution of Rabbit message listener failed, and the error handler threw an exception org.springframework.amqp.AmqpRejectAndDontRequeueException: Error Handler converted exception to fatal at org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler.handleError(ConditionalRejectingErrorHandler.java:106) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeErrorHandler(AbstractMessageListenerContainer.java:1334) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.handleListenerException(AbstractMessageListenerContainer.java:1585) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1415) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:848) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:832) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:78) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1073) at java.lang.Thread.run(Thread.java:748) Caused by: org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Failed to invoke target method 'listen' with argument type = [class [B], value = [{[B@3f099764}] at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:387) at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:292) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1511) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1434) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1421) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1400) ... 5 more Caused by: java.lang.NoSuchMethodException: com.wangx.rabbitmq.spring.Consumer.listen([B) at java.lang.Class.getMethod(Class.java:1786) at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:174) at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:365) ... 10 more