A brief introduction to JMS
The full name of JMS is the Java Message Service. That is, the Java messaging service.
It is used primarily for message delivery between producers and consumers, and producers are responsible for generating messages. And consumers are responsible for receiving messages.
To apply it to the actual business requirements, we can use the producer to generate a message and send it at a certain time, and the corresponding consumer will complete the corresponding business logic after receiving the corresponding message.
There are two types of message delivery, one point-to-point. That is, a producer and a consumer are correspondingly. Another is the Publish/subscribe model, where a producer generates a message and sends it and can be received by multiple consumers.
Spring consolidates JMS After a brief introduction to JMS, let's take a look at spring's detailed process of consolidating JMS.
JMS is just a standard, and we need to have a detailed implementation of it when we use it, and here we use Apache's ACTIVEMQ as its implementation. The dependencies used are managed using MAVEN. Detailed dependencies such as the following:
<!--JMS--><dependency><groupid>org.apache.geronimo.specs</groupid><artifactid> Geronimo-jms_1.1_spec</artifactid><version>${geronimo.version}</version></dependency> <dependency><groupid>org.apache.geronimo.specs</groupid><artifactid>geronimo-jta_1.1_ Spec</artifactid><version>${geronimo.version}</version></dependency>
<!-- ActiveMQ--><dependency><groupid>org.apache.activemq</groupid><artifactid> activemq-core</artifactid><version>${activemq.version}</version><exclusions>< Exclusion><groupid>org.apache.activemq.protobuf</groupid><artifactid>activemq-protobuf </artifactId></exclusion><exclusion><groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-core</artifactId></exclusion><exclusion><groupId> Org.osgi</groupid><artifactid>org.osgi.core</artifactid></exclusion></exclusions ></dependency><dependency><groupId>org.apache.activemq</groupId><artifactId> Activemq-pool</artifactid><version>${activemq.version}</version></dependency>
<dependency><groupid>org.springframework</groupid><artifactid>spring-jms</ Artifactid><version>${spring.version}</version></dependency>
ACTIVEMQ Preparationsince the Apache ACTIVEMQ is used as the implementation of JMS, we should first download the Apache websiteActiveMQ (http://activemq.apache.org/download.html), perform an extract after executing its bin folder under the Activemq.bat file to start Activemq.
Configure ConnectionFactory connectionfactory is used to generate links to Jmsserver, and spring provides us with multiple connectionfactory. There are singleconnectionfactory and cachingconnectionfactory. Singleconnectionfactory the request to establish a jmsserver link will always return the same link, and The Close method Call of connection will be ignored.
Cachingconnectionfactory inherited the Singleconnectionfactory. So it has the full functionality of singleconnectionfactory, and It also adds a new cache feature. It can cache sessions, MessageProducer, and Messageconsumer. Here we use Singleconnectionfactory as a demonstration sample.
<bean id= "ConnectionFactory" class= "Org.springframework.jms.connection.SingleConnectionFactory"/>
does this define the connectionfactory that generated the jmsserver link? The answer is right and wrong. The connectionfactory provided by spring is only spring for the management of ConnectionFactory, and the connectionfactory that actually generate the Jmsserver link is provided by the JMS service vendor. And it needs to be injected into the connectionfactory provided by spring. We are using JMS implemented by ACTIVEMQ, so what we can really produce connection here should be the connectionfactory provided by ACTIVEMQ. So the complete code that defines a connectionfactory should look like the following:
<!--really can produce connection connectionfactory. provided by the appropriate JMS service vendor-- <bean id= "targetconnectionfactory" class= " Org.apache.activemq.ActiveMQConnectionFactory "> <property name=" Brokerurl "value=" tcp://localhost : 61616 "/> </bean> <!--spring for managing real connectionfactory connectionfactory-- <bean Id= "ConnectionFactory" class= "Org.springframework.jms.connection.SingleConnectionFactory" > <!-- The target connectionfactory the corresponding real capable of generating the JMS connection ConnectionFactory--- <property name= " Targetconnectionfactory "ref=" targetconnectionfactory "/> </bean>
Configuring the producer configuration Well connectionfactory we need to configure the producer.The producer is responsible for generating the message and sending it to jmsserver. This usually corresponds to one of our business logic service implementation classes.
But how does our service implementation class send messages? This is generally done with the Jmstemplate class that spring provides for us, so the most important thing to configure the producer is the jmstemplate of the distribution to send the message. For a message sender, it needs to know where to go when it sends a message. To do this, we need to inject a spring-provided connectionfactory object into the surface when defining jmstemplate.
<!--the JMS tool class provided by spring, which is capable of sending messages, receiving, etc.- <bean id= "jmstemplate" class= " Org.springframework.jms.core.JmsTemplate "> <!-- This connectionfactory corresponds to the ConnectionFactory object that we defined spring provides-- <property name= "ConnectionFactory" ref= " ConnectionFactory "/> </bean>
When you really use Jmstemplate to send messages. We need to know the destination where the message was sent, namely destination.
There is a destination port in JMS that represents the destination , which is not defined in any way and is used only to make an identity.
The default Destination is used when we do not specify Destination when using Jmstemplate for message sending .
The default destination can be injected by using the attribute defaultdestination or defaultdestinationname when defining the Jmstemplate bean object. Defaultdestinationname the corresponding is a normal string. Two types of destination are implemented in ACTIVEMQ, one is point-to-point activemqqueue. There is also a subscription/announcement mode Activemqtopic. When defining both types of destination we are able to construct through a Name property, such as:
<!--This is the queue destination, point-to-point-- <bean id= "queuedestination" class= "Org.apache.activemq.command.ActiveMQQueue" > <constructor-arg> <value>queue</value> </constructor-arg> </ Bean> <!--This is the theme destination. One-to-many-- <bean id= "topicdestination" class= "Org.apache.activemq.command.ActiveMQTopic" > < Constructor-arg value= "topic"/> </bean>
If we define a producerservice with a method that sends a plain text message to the destination SendMessage, then our code is probably like this:
Package Com.somnus.jms.service.impl; Import Javax.annotation.Resource; Import javax.jms.Destination; Import javax.jms.JMSException; Import Javax.jms.Message; Import javax.jms.Session; Import Org.springframework.jms.core.JmsTemplate; Import Org.springframework.jms.core.MessageCreator; Import org.springframework.stereotype.Component; Import Com.somnus.jms.service.ProducerService; @Component public class Producerserviceimpl implements Producerservice {private jmstemplate jmstemplate; public void SendMessage (Destination Destination, final String message) {System.out.println ("---------- -----Producers to send messages-----------------"); System.out.println ("---------------producer sent a message:" + message); Jmstemplate.send (Destination, new Messagecreator () {public Message CreateMessage (session session) throws JM sexception {return session.createtextmessage (message); } }); } public jmstemplate Getjmstemplate () {returnjmstemplate; } @Resource public void Setjmstemplate (Jmstemplate jmstemplate) {this.jmstemplate = jmstemplate; } }
We can see in the SendMessage method body that we are sending messages to the corresponding destination by jmstemplate.
Here, we generate a simple text message and send it to the producer of the specified destination destination to be configured.after configuring the consumer producer to send a message to the specified destination destination, the consumer is then consumed with the message of the specified destination. So how consumers know there are producers sending messages to the specified purpose destination to listen to, you need to know where to listen, which means it needs to know which jmsserver to listen to, This is accomplished by injecting the messagelistenercontainer connectionfactory Span style= "color:red" and one is the destination messagelistener that receives messages for message processing.
Spring provides us with a total of two kindstype of Messagelistenercontainer. Simplemessagelistenercontainer and Defaultmessagelistenercontainer. Simplemessagelistenercontainer will create a conversation session and consumer consumer at the beginning, and will use the standard JMS Messageconsumer.setmessagelistener () method The register listener lets the JMS provider invoke the listener's callback function. It does not dynamically adapt to the needs and involvement of external transaction tubes when executing Management. Compatibility aspects. It is very close to the standalone JMS specification, but is generally incompatible with the JMS restrictions of Java EE . In most cases we still use the Defaultmessagelistenercontainer. Compared with Simplemessagelistenercontainer, Defaultmessagelistenercontainer will move.the adaptation of the state is required. It is also possible to participate in external transaction management.
It balances the requirements of the JMS provider with low, advanced functionality such as transactional participation and compatibility with the Java EE environment.
define messagelistener for handling messages to define the MessageListener for handling messages we just need to implement the MessageListener interface in the JMS specification.
There is only one method OnMessage method in the MessageListener interface, and the method is invoked on its own initiative when the message is received.
Package Com.somnus.jms.listener; Import javax.jms.JMSException; Import Javax.jms.Message; Import Javax.jms.MessageListener; Import Javax.jms.TextMessage; public class Consumermessagelistener implements MessageListener {public void onMessage (Message message) { // Here we know that the producer is sending a plain text message, so it can be cast directly here. or directly change the OnMessage method to the subclass of message textmessage textmessage textmsg = (textmessage) message; System.out.println ("received a plain text message. "); try { System.out.println ("Message content is:" + textmsg.gettext ()) } catch (JMSException e) { e.printstacktrace () ; } } }
with MessageListener We are able to configure a message monitoring container in the spring configuration file.
<!--This is the queue destination-- <bean id= "queuedestination" class= "Org.apache.activemq.command.ActiveMQQueue" > <constructor-arg> <value>queue</value> </constructor-arg> </bean > <!--message Listener-- <bean id= "Consumermessagelistener" class= " Com.somnus.jms.listener.ConsumerMessageListener "/> <!--message monitoring container-- <bean id=" Jmscontainer " class= "Org.springframework.jms.listener.DefaultMessageListenerContainer" > <property name= " ConnectionFactory "ref=" ConnectionFactory "/> <property name=" Destination "ref=" Queuedestination "/> <property name= "MessageListener" ref= "Consumermessagelistener"/> </bean>
We can see that we have defined a activemqqueue destination named queue, and our listener is listening for messages sent to this destination.
Now that our generators and consumers have been configured, this means that our integration is complete.
This time the full spring configuration file should be this:
<?XML version= "1.0" encoding= "UTF-8"?> <beans xmlns= "Http://www.springframework.org/schema/beans" xmlns:xsi= "HT Tp://www.w3.org/2001/xmlschema-instance "xmlns:context=" Http://www.springframework.org/schema/context "XMLNS:JMS = "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/JMS" xsi:schemalocation= "Http://www.springframework.org/schema/beans H Ttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd Http://www.springframework.org/schema/context Http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/ Beans Http://www.springframework.org/schema/beans/spring-beans-3.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/JMS Http://www.springframework.org/schema/jms/spring-jms-3.0.xsd "> <context:component-scan base-package=" COM.S Omnus "/> <!--Spring provides a JMS tool class that enables message sending, receiving, and so on <bean id=" jmstemplate "class=" Org.springframewo Rk.jms.core.JmsTemplate "> <! --This connectionfactory corresponds to the ConnectionFactory object that we define spring provides--<property name= "ConnectionFactory" ref= "C Onnectionfactory "/> </bean> <!--can actually generate connection connectionfactory, provided by the appropriate JMS service provider-- <bean id= "Targetconnectionfactory" class= "org.apache.activemq.ActiveMQConnectionFactory" > <property nam E= "Brokerurl" value= "tcp://localhost:61616"/> </bean> <!--spring is used to manage real connectionfactory con Nectionfactory--<bean id= "ConnectionFactory" class= " Org.springframework.jms.connection.SingleConnectionFactory "> <!--target connectionfactory corresponding real capable of generating JMS connectio N ConnectionFactory--<property name= "targetconnectionfactory" ref= "Targetconnectionfactory"/> &L T;/bean> <!--This is the queue destination--<bean id= "queuedestination" class= "Org.apache.activemq.command.Activ Emqqueue "> <constructor-arg> <value>queue</value> </constructor-arg> </bean> <!--message Listener--<bean id= "Consumerme Ssagelistener "class=" Com.somnus.jms.listener.ConsumerMessageListener "/> <!--message listening container--<bean id=" J Mscontainer "class=" Org.springframework.jms.listener.DefaultMessageListenerContainer "> <property n Ame= "ConnectionFactory" ref= "ConnectionFactory"/> <property name= "destination" ref= "Queuedestination"/> ; <property name= "MessageListener" ref= "Consumermessagelistener"/> </bean> </beans>
and then we'll test it. See if our integration is really successful and the test code is like this:
Package com.somnus.jms.test; Import javax.jms.Destination; Import Org.junit.Test; Import Org.junit.runner.RunWith; Import org.springframework.beans.factory.annotation.Autowired; Import Org.springframework.beans.factory.annotation.Qualifier; Import org.springframework.test.context.ContextConfiguration; Import Org.springframework.test.context.junit4.SpringJUnit4ClassRunner; Import Com.somnus.jms.service.ProducerService; @RunWith (Springjunit4classrunner.class) @ContextConfiguration ("/applicationcontext.xml") public class producerconsumertest {@Autowired private producerservice producerservice; @Autowired @Qualifier ("queuedestination") private Destination Destination; @Test public void Testsend () {for (int i=0; i<2; i++) {producerservice.sendmessage (desti Nation, "Hello, producer!" This is the message: "+ (i+1)); } } }
in the test code above we used the producer to send two messages, and normally consumers should be able to receive these two messages. After executing the test code, the console output is as follows:
Look, the console has done the right thing, which means that our integration is really successful.
Spring Consolidated JMS (i)--based on ACTIVEMQ implementation