RABBITMQ Java Applications (2)--using spring AMQP to develop consumer applications __RABBITMQ

Source: Internet
Author: User
Tags tag name rabbitmq

In the previous article we introduced the method of using RABBITMQ Java client to access RABBITMQ. However, in this way access to RABBITMQ, developers need to manage their own Connection,channel objects in the program, consumer object creation, destruction, this will be very inconvenient. Here we introduce the use of spring AMQP to connect RABBITMQ to receive and send messages.

Spring AMQP is a spring subproject that provides a solution to access a message server based on the AMQP protocol. It consists of two parts, SPRING-AMPQ is the high-level implementation of message sending and receiving based on AMQP protocol, Spring-rabbit is based on the concrete realization of RABBITMQ. We'll use these two parts below.

Several basic classes/interfaces are defined in the base class/interface SPRING-AMQP in SPRING-AMQP, message,exchange,queue,binding

Message

public class message implements Serializable 
{
  private final messageproperties messageproperties;
 
  Private final byte[] body;

The message class in SPRING-AMQP is similar to the Javax class of messages, encapsulating the properties and message bodies of the messaging.

Exchange SPRING-AMQP defines the Exchange interface

Public interface Exchange extends declarable {
        //exchange name
	String getName ();
        Exchange Type
	String getType ();
        Whether Exchange persisted
	Boolean isdurable ();
        When Exchange is no longer in use (without any bindings),
	Boolean isautodelete () is automatically deleted by RABBITMQ.
        Exchange-related parameters
	map<string, object> getarguments ();


This interface is similar to the Exchange class in RABBITMQ client. The Exchange inheritance relationship in SPRING-AMQP is shown in the following illustration


The Abstractexchange class is the parent class of all Exchange classes, the specific way to implement the Exchange interface. Customexchange Exchange objects that are customized for the user. Four other Exchange classes, corresponding to four types of exchange. These are the Exchange classes that are used when we configure Exchange objects in the spring configuration file.

The queue SPRING-AMQP defines the queue class, similar to the queue in the RABBITMQ client, corresponding to the message queues in the RABBITMQ.

public class Queue extends Abstractdeclarable {
 
	private final String name;
 
	Private final Boolean durable;
 
	Private final Boolean exclusive;
 
	Private Final Boolean autodelete;
 
	Private final java.util.map<java.lang.string, java.lang.object> arguments;
 
        Public Queue (String name, Boolean durable, Boolean exclusive, Boolean autodelete) {This
		(name, durable, exclusive, AUT Odelete, NULL);
	

Binding The binding class is an abstraction of the exchange-exchange and exchange-queue binding relationships in RABBITMQ.

public class Binding extends abstractdeclarable 
{public
 
	enum destinationtype {
		QUEUE, EXCHANGE;
	}
 
	Private final String destination;
 
	Private final String exchange;
 
	Private final String Routingkey;
 
	Private final map<string, object> arguments;
 
	Private final destinationtype destinationtype;
 
	Public Binding (String destination, destinationtype destinationtype, String Exchange, String Routingkey,
			map< String, object> arguments) {
		this.destination = destination;
		This.destinationtype = destinationtype;
		This.exchange = Exchange;
		This.routingkey = Routingkey;
		this.arguments = arguments;
	}

Queuebind and Exchangebind methods for channel interfaces in RABBITMQ Java client

Exchange.bindok exchangebind (string destination, string source, String Routingkey, map<string, object> arguments) 
 
Queue.bindok queuebind (String Queue, String Exchange, String Routingkey, map<string, object> arguments)

We can see that the binding class is actually a high-level abstract record class for the exchange-queue and Exchange-exchange binding relationships that are built at the bottom. It uses enum type destinationtype to differentiate between Exchange-queue and exchange-exchange two binding.

Spring AMQP builds consumer apps Consumer Application Framework we will then use SPRING-AMQP to build a RABBITMQ consumer Web application, and we'll create a Maven webapp application and add a dependency.

<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId> Spring-rabbit</artifactid>
    <version>1.6.5.RELEASE</version>
 

The Spring-rabbit library was introduced to use the Rabbitadmin class inside it, creating exchange,queue and binding objects, and introducing the SPRING-AMPQ and rabbitmq-client libraries when importing the library. You do not need to import separately.

Create a application.properties file in the Src/main/resources directory to record RABBITMQ configuration information.

Mq.ip=localhost
mq.port=5672
mq.username=rabbitmq_consumer
mq.password=123456
mq.virutalhost= Test_vhosts
To create a applicationcontext.xml file in the Src/main/resource directory:

<?xml version= "1.0" encoding= "UTF-8"?> <beans "xmlns=" xmlns:
       Xsi= "Http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "Http://www.springframework.org/schema/context" Xmlns:util= "Http://www.springframework.org/schema/util" xsi:schemalocation= "http://www.springframework.org/sc Hema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/ Schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd Http://www.springframework.org/schema /context http://www.springframework.org/schema/context/spring-context-4.0.xsd "> <context:annotation-con Fig/> <context:property-placeholder ignore-unresolvable= "true" location= CLASSPATH*:/APPLICATION.P Roperties "/> <!--Create RABBITMQ connection factory object from RABBITMQ Java client--> <bean id=" Rabbitmqconnectionfactory "Clas S= "Com.rabbitmq.client.ConnectionFActory "> <property name=" username "value=" ${mq.username} "/> <property name=" password "value=" ${mq.password} "/> <property name=" host "value=" ${mq.ip} "/> <property name=" port "value=" ${mq . Port} "/> <property name= virtualhost" value= "${mq.virutalhost}"/> </bean> <!--based on Rab BITMQ Connection factory Object build Spring-rabbit Connection factory object wrapper--> <bean id= "ConnectionFactory" Org.springframework.amqp.rabbit.connection.CachingConnectionFactory "> <constructor-arg name=" Rabbitconnectionfactory "ref=" rabbitmqconnectionfactory/> </bean> <!--build the Rabbitamdin object, which is responsible for creating queue/e Xchange/bind object--> <bean id= "rabbitadmin" class= "Org.springframework.amqp.rabbit.core.RabbitAdmin" > &L T;constructor-arg name= "ConnectionFactory" ref= "ConnectionFactory"/> <property name= "AutoStartup" value= "tr UE "></property> </bean> <!--building Rabbit TemplateObject that is used to send a RABBITMQ message that this program uses to send a return message--> <bean id= "Rabbittemplate" Org.springframework.amqp.rabbit.core.RabbitTemplate "> <constructor-arg name=" connectionfactory "ref=" Connec
    Tionfactory "/> </bean> <!--RABBITMQ message converter for converting RABBITMQ messages to AMQP messages, where we use the basic message Converter--> <bean id= "Serializermessageconverter" class= "Org.springframework.amqp.support.converter.SimpleMessageConve Rter "/> <!--message properties converter for message properties in the SPRING-AMQP message object and RABBITMQ message Propert IES objects convert--> <bean id= "Messagepropertiesconverter" class= "Org.springframework.amqp.rabbit.sup" Port. Defaultmessagepropertiesconverter "/> <!--definition amqp queue--> <bean id=" Springmessagequeue "class=
        "Org.springframework.amqp.core.Queue" > <constructor-arg name= "name" value= "Springmessagequeue"/>
      <constructor-arg name= "Autodelete" value= "false"/>  <constructor-arg name= "Durable" value= "true"/> <constructor-arg "name=" exclusive "false" value= <!--define AMQP queue to create required Rabbitadmin objects--> <property name= "Adminsthatshoulddeclare" ref= "rabbitadmin"/ > <!--determine if you want to create queue--> <property name= "Shoulddeclare" value= "true"/> After connecting RABBITMQ </ bean> <!--definition amqp exchange--> <bean id= "Springmessageexchange" class=  Irectexchange "> <constructor-arg name=" name "value=" Springmessageexchange "/> <constructor-arg  Name= "Durable" value= "true"/> <constructor-arg name= "Autodelete" value= "false"/> <!--definition Amqp The queue creates the required Rabbitadmin object--> <property name= "Adminsthatshoulddeclare" ref= "Rabbitadmin"/> <!-- Determine if you want to create exchange--> <property name= "Shoulddeclare" value= "true"/> </bean> &l after connecting RABBITMQ T;util:map id= "Emptymap" map-class= "Java.util.HashMap"/> <!--create bind--> <bean id= "Springmessagebind" between Exchange and queue class= "Org.springframework.amqp.core.Binding" > <constructor-arg name= "Destination" value= "Springmessagequeue"/&gt
        ; <constructor-arg name= "destinationtype" value= "QUEUE"/> <constructor-arg "Exchange Name=" value=  Ssageexchange "/> <constructor-arg name= routingkey" value= "Springmessage"/>
    Name= "Arguments" ref= "Emptymap"/> </bean> <!--listen for message springmessagequeue for listener--> queue messages <bean id= "Consumerlistener" class= "Com.qf.rabbitmq.listener.RabbitMQConsumer"/> <!--Create listening Springmessag Equeue Queue message Listener container--> <bean id= "Messagelistenercontainer" class=. Amqp.rabbit.listener.SimpleMessageListenerContainer "> <property name=" messageconverter "ref=" serializermess Ageconverter "/> <property name= "connectionfactory" ref= "ConnectionFactory"/> <property name= "MessageListene" R "ref=" Consumerlistener "/> <property name=" queues "ref=" Springmessagequeue "/> <!--set up the message confirmation method to Automatically confirm--> <property name= "Acknowledgemode" value= "Auto"/> </bean> </beans>
We have defined the message listener class that listens for messages queues Rabbitmqconsumer

public class Rabbitmqconsumer implements MessageListener {@Autowired private messagepropertiesconverter Messagepr
 
    Opertiesconverter; @Override the Me in the public void OnMessage (message) {a try {//SPRING-AMQP message object)             
             Ssage properties Messageproperties messageproperties = Message.getmessageproperties ();
             Use the message converter to convert the message Properties property///To RABBITMQ message Properties object in the SPRING-AMQP message object Amqp. Basicproperties rabbitmqproperties = messagepropertiesconverter.frommessageproperties (messageProperties, "UT             
             F-8 ");
             SYSTEM.OUT.PRINTLN ("The message's Correlationid is:" + Rabbitmqproperties.getcorrelationid ());
             String messagecontent = null;
             Messagecontent = new String (Message.getbody (), "UTF-8");
        SYSTEM.OUT.PRINTLN ("The message content is:" + messagecontent); catch (UnsupPortedencodingexception e) {e.printstacktrace (); }
    }
}
The Listener class above is a class that implements the MessageListener interface and automatically triggers the OnMessage method when the container receives a message. If we want to use the ordinary Pojo class as the message Listener, we need to introduce the Org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter class

public class Messagelisteneradapter extends Abstractadaptablemessagelistener {public
 
  messagelisteneradapter ( Object delegate) {
		dosetdelegate (delegate);
	}
}
The delegate object here is our Pojo object. Let's say we define a delegate class Consumerdelegate

       The Message object that is received here is the message body only for public class Consumerdelegate {public void ProcessMessage (object message) {// Does not contain messageproperties
       //If you want to get a message object with Messageproperties, you need to
       define the Messageconverter attribute in Adpater//.
       String messagecontent = message.tostring ();
       System.out.println (messagecontent);
    }
Define the adapter object in Applicationcontext.xml, referencing our delegate object.

<bean id= "Consumerdelegate" class= "com.qf.rabbitmq.listener.ConsumerDelegate"/> <bean id=
 
 " Consumerlisteneradapter "
          class=" Org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter " >
        <property name= "delegate" ref= "Consumerdelegate"/>
        <!--Specify the default method for handling messages Delegate
        < Property Name= "Defaultlistenermethod" value= "ProcessMessage"/>
 </bean>
Finally, the message Listener in the message Listener container is pointed to adapter object.

<bean id= "Messagelistenercontainer"
          class= " Org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer ">
        <property name=" Messageconverter "ref=" Serializermessageconverter "/> <property name=" connectionfactory "ref="
        ConnectionFactory "/>
        <!--set Message listener to adapter object--> <property name=
        " MessageListener "ref = "Consumerlisteneradapter"/>
        <property name= "queues" ref= "Springmessagequeue"/>
        <property Name= "Acknowledgemode" value= "AUTO"/>
 </bean>
After starting the Web application, we can see from the boot log information that the application is connected to the RABBITMQ server



From the RABBITMQ management interface (logged in with a Rabbitmq_consumer user), you can see that Springmessageexchange and Springmessagequeue have been created, and that the bindings have been created.







Consumer Tag Custom Connection Springmessagequeue consumer tag is rabbitmq randomly generated tag name


If we want to set the consumer tag as the specified tag, we can set the custom consumer tag strategy in the Message Listener container. First we need to define a consumer Tag strategy class, which implements the Consumertagstrategy interface.

public class Customconsumertagstrategy implements Consumertagstrategy
{
    @Override public
    String Createconsumertag (String queue) {
        string consumername = "Consumer1";
        Return Consumername + "_" + queue;
    }
}
Set Custom Consumertagstrategy in Applicationcontext.xml

<bean id= "Consumertagstrategy" class= "Com.qf.rabbitmq.strategy.CustomConsumerTagStrategy"/>
 <!-- Create a message Listener to listen to the Springmessagequeue queue container--> <bean id= "Messagelistenercontainer"
          Org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer ">
     <property name=" Messageconverter "ref=" Serializermessageconverter "/> <property name=" connectionfactory "ref="
     ConnectionFactory "/> <property name=" MessageListener "ref=" Consumerlistener "/> <property
     Name = "Queues" ref= "Springmessagequeue"/>
     <property name= "Acknowledgemode" value= "AUTO"/>
     < Property Name= "Consumertagstrategy" ref= "Consumertagstrategy"/>
  </bean>

Start the Web application again, see the RABBITMQ admin interface, we can see consumer tag has become "Consumer1_springmessagequeue", As we set in the Customconsumertagstrategy.



consumer applications Receive message validation we have written a producer program that sends messages to Springmessageexchange. The main code for the producer is as follows, because the Exchange,queue,bind has been created by the consumer Web application, so the producer program is no longer created.

ConnectionFactory factory = new ConnectionFactory ();
Factory.sethost ("localhost");
Factory.setport (5672);
Factory.setusername ("Rabbitmq_producer");
Factory.setpassword ("123456");
Factory.setvirtualhost ("test_vhosts");
 
Create a TCP connection to the RABBITMQ server
Connection  = Factory.newconnection ();
Channel = Connection.createchannel ();
 
String message = "A-Web rabbitmq message";
 
String Correlationid = Uuid.randomuuid (). toString ();
Amqp. Basicproperties props = new AMQP. Basicproperties
                    . Builder ()
                    . Correlationid (Correlationid)
                    . Build ();
 
Channel.basicpublish ("Springmessageexchange", "springmessage", Props, Message.getbytes ());

Starting a consumer Web application, outputting information from the console to see that the consumer has received the message sent by the producer.

Set Message manual acknowledgement mode

So far, consumer-side Web applications for message recognition is automatic recognition mode, if we want to change to manual confirmation, we need to do the following two changes:

1) The value of the Acknowledgemode property of the message Listener container in the Applicationcontext.xml file is modified to manual.

<bean id= "Messagelistenercontainer"
          class= " Org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer "> ...
    <property name= "Acknowledgemode" value= "MANUAL"/> 
</bean>

2 The custom message listener class from the implementation of the Org.springframework.amqp.core.MessageListener interface, instead of implementing Org.springframework.amqp.rabbit.core.ChannelAwareMessageListener interface to implement its onMessage (Message,channel) method.

public class Rabbitmqconsumer implements Channelawaremessagelistener {.... @Override public void onMessage (Message message, Channel Channel) {try {//spring-amqp Messag             
             The message properties attribute in E object messageproperties messageproperties = Message.getmessageproperties (); Use the message converter to convert the message Properties property////to RABBITMQ message in the SPRING-AMQP message object Propertie S object AMQP. Basicproperties rabbitmqproperties = messagepropertiesconverter.frommessageproperties (messageProperties, "U             
             TF-8 ");
             SYSTEM.OUT.PRINTLN ("The message's Correlationid is:" + Rabbitmqproperties.getcorrelationid ());
             String messagecontent = null;
             Messagecontent = new String (Message.getbody (), "UTF-8"); System.out.print 
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.