In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
The editor will share with you what JMS means. I hope you will get something after reading this article. Let's discuss it together.
JMS, the Java message service (Java Message Service) application program interface, is an API oriented to message middleware (MOM) in a Java platform, which is used to send messages between two applications or in distributed systems for asynchronous communication. Java message service is a platform-independent API, and most MOM providers provide support for JMS.
Current environment Mac OS 10.11.xdocker 1.12.1JDK 1.8SpringBoot 1.5foreword
Based on the previous article, "A story tells you what a message queue is," you learned about the usage scenarios and related features of message queues. This article focuses on the use of message services in JAVA.
There are many technology choices about message queue in the market. if our code framework wants to support different message implementations, under the premise of ensuring that the framework has high expansibility, we are bound to carry out certain encapsulation.
In JAVA, this is not necessarily the case. Because JAVA has developed a set of standard JMS specifications. The specification defines a common set of interfaces and related semantics, and provides message services such as persistence, authentication, and transactions. its main purpose is to allow Java applications to access existing message middleware. Just like JDBC.
Basic concept
Before introducing the specific use, let's briefly introduce some basic knowledge of JMS. Here I'm going to introduce it in three parts, namely, the connection of message queuing (MQ), message sending and message receiving.
Our technology selection here is SpringBoot, JMS, ActiveMQ.
To better understand JMS, there is no use of SpringBoot zero configuration to build the project
Connection of MQ
The first step in using MQ must be to connect to MQ first. Because the JMS specification is used here, any MQ that complies with the JMS specification will implement the corresponding ConnectionFactory interface, so we only need to create a ConnectionFactory factory class that implements the connection to MQ and the MQ parameters that encapsulate a series of features.
Example: here we take ActiveMQ as an example
Maven dependencies:
Org.springframework.bootspring-boot-starter-parent1.5.3.RELEASE org.springframework.bootspring-boot-starter- activemq
Create an ActiveMQ connection factory:
@ Beanpublic ConnectionFactory connectionFactory () {ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory (); connectionFactory.setBrokerURL (ActiveMQ_URL); connectionFactory.setUserName (ActiveMQ_USER); connectionFactory.setPassword (ActiveMQ_PASSWORD); return connectionFactory;} message delivery
The sending of messages is achieved through the JmsTemplate class in the JMS core package, which simplifies the use of JMS because it helps us handle the creation and release of resources when sending or receiving messages synchronously. It is not difficult to infer from its role that it needs to refer to the connection factory we created above, as follows:
Beanpublic JmsTemplate jmsQueueTemplate () {return new JmsTemplate (connectionFactory ());}
Once the JmsTemplate is created, we can call its methods to send the message. Here are two concepts to note:
Where will the message be sent? -> that is, you need to specify the destination of the sending queue (Destination), which is a JMS management object that can be stored and extracted in JNDI. What exactly is the body of the message sent? -> implements the object of javax.jms.Message, similar to the Remote object of JAVA RMI.
Code example:
@ Autowiredprivate JmsTemplate jmsQueueTemplate;/*** sends the original message Message*/public void send () {jmsQueueTemplate.send ("queue1", new MessageCreator () {@ Override public Message createMessage (Session session) throws JMSException {return session.createTextMessage ("I am the original message");});}
Optimization: of course, we don't have to create Message objects every time through MessageCreator anonymous classes, the JmsTemplate class provides a method to automatically convert object entities into Message objects, convertAndSend (String destinationName, final Object message).
Optimization code example:
/ * the sent message is automatically converted to the original message * / public void convertAndSend () {jmsQueueTemplate.convertAndSend ("queue1", "I am the automatically converted message");}
Note: with regard to message transformation, you can also customize the transformation content by implementing the MessageConverter interface.
Message reception
After talking about sending messages, let's finally talk about how messages are received. Since the message is sent to the specified destination in the form of a Message object, the receipt of the message is bound to go to the specified destination to receive the message. Here, the listener method is used to listen for messages in the specified location, and the annotation @ JmsListener is used to set the listening method.
Code example:
@ Componentpublic class Listener1 {@ JmsListener (destination = "queue1") public void receive (String msg) {System.out.println ("the monitored message is:" + msg);}}
With the goal and method of listening, the listener has to be associated with the MQ in order to work. There may be more than one listener here, and it would not be appropriate for each of them to establish a connection to the MQ. So you need a concept of a listening container factory, the interface JmsListenerContainerFactory, which refers to the connection factory created above to MQ, which is responsible for receiving messages and distributing them to specified listeners. Of course, it also includes transaction management, resource acquisition and release, and exception conversion.
Code example:
@ Beanpublic DefaultJmsListenerContainerFactory jmsQueueListenerContainerFactory () {DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory (); factory.setConnectionFactory (connectionFactory ()); / / set the number of connections factory.setConcurrency ("3-10"); / / reconnect interval factory.setRecoveryInterval (1000L); return factory;} scenario
Code address: https://github.com/jasonGeng88/springboot-jms
Now that we have a basic understanding of JMS, let's use it in a specific scenario.
First, we need to start ActiveMQ first, and here we start it in a Docker containerized way.
Start the command:
Docker run-d-p 8161-p 61616-name activemq webcenter/activemq
After launching successfully, view the results in the ActiveMQ visual interface (http://localhost:8161):
Peer-to-peer mode (single consumer)
The following describes one of the most common scenarios in message queuing, the peer-to-peer mode. The basic concepts are as follows:
Each message can only be consumed by one Consumer. Once the message is consumed, it no longer exists in the message queue. There is no time dependence between the sender and the receiver, that is, when the sender sends the message, it does not affect whether the receiver is running or not, it does not affect the message being sent to the queue. The receiver needs to reply successfully to the queue after successfully receiving the message.
Code implementation (to simplify the code, some of the code follows the above): startup file (Application.java)
@ SpringBootApplication@EnableJmspublic class Application {/ * template class for JMS queue * connectionFactory () is ActiveMQ connection factory * / @ Bean public JmsTemplate jmsQueueTemplate () {return new JmsTemplate (connectionFactory ());} public static void main (String [] args) {SpringApplication.run (Application.class, args);}}
The annotation @ EnableJms is set on the @ configuration class to declare support for JMS annotations.
The message producer (PtpProducer.java) @ Componentpublic class PtpProducer {@ Autowired private JmsTemplate jmsQueueTemplate; / * automatically converts the message to the original message * / public void convertAndSend () {jmsQueueTemplate.convertAndSend ("ptp", "I am the automatically converted message");}} producer invocation class (PtpController.java) @ RestController@RequestMapping (value = "/ ptp") public class PtpController {@ Autowired private PtpProducer ptpProducer @ RequestMapping (value = "/ convertAndSend") public Object convertAndSend () {ptpProducer.convertAndSend (); return "success";}} message listening Container Factory @ SpringBootApplication@EnableJmspublic class Application {/ * JMS queue listening Container Factory * / @ Bean (name = "jmsQueueListenerCF") public DefaultJmsListenerContainerFactory jmsQueueListenerContainerFactory () {DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory (); factory.setConnectionFactory (connectionFactory ()) / / set the number of connections factory.setConcurrency ("3-10"); / / reconnect interval factory.setRecoveryInterval (1000L); return factory }.} message listener @ Componentpublic class PtpListener1 {/ * message queue listener * destination queue address * containerFactory listener container factory. If there are more than two listening container factories, you need to specify * / @ JmsListener (destination = "ptp", containerFactory = "jmsQueueListenerCF") public void receive (String msg) {System.out.println ("peer-to-peer mode 1:" + msg). }} demonstration
After the startup project is started, the message producer is called through the REST API to send messages. The request is as follows:
Curl-XGET 127.0.0.1:8080/ptp/convertAndSend
Consumer console information:
ActiveMQ console information:
List description:
Name: queue name. Number Of Pending Messages: the number of messages waiting for consumption. Number Of Consumers: the number of consumers currently connected, because we are using connection pooling, and the initial number of connections is 3, so the number is displayed as 3. Messages Enqueued: the total number of messages entering the queue, including those out of the queue and those waiting to be consumed, is only increasing, not decreasing. Messages Dequeued: messages out of the queue can be understood as the number of messages that have been consumed. Peer-to-peer mode (multi-consumer)
Based on the above consumer consumption pattern, because there may be many producers and send messages like a queue at the same time, a consumer may become a bottleneck. Therefore, multiple consumers are needed to share the consumption pressure (consumption thread pool can solve some pressure, but after all, distributed distribution cannot be done on a single machine, so multiple consumers are necessary), which leads to the following scenario.
Code implementation
Add a new listener
@ Componentpublic class PtpListener2 {@ JmsListener (destination = Constant.QUEUE_NAME, containerFactory = "jmsQueueListenerCF") public void receive (String msg) {System.out.println ("peer-to-peer mode 2:" + msg);}}
Here in the demo we make 10 requests to observe how consumers spend:
Here, because the listening container sets a thread pool, the order of consumption of listeners will be different in the actual consumption process.
Publish and subscribe model
In addition to the peer-to-peer model, the publish-subscribe model is also a common use in message queues. Imagine an instant chat group in which you send a message. All people in this group (that is, those who subscribe to this group) will receive your message.
Basic concepts:
Each message can have multiple consumers. There is a time dependence between publishers and subscribers. For subscribers to a topic (Topic), it must create a subscriber before it can consume the publisher's messages. In order to consume messages, subscribers must keep running.
The code implementation modifies the JmsTemplate template class to support the publish and subscribe function
@ SpringBootApplication@EnableJmspublic class Application {... @ Bean public JmsTemplate jmsTopicTemplate () {JmsTemplate jmsTemplate = new JmsTemplate (connectionFactory ()); jmsTemplate.setPubSubDomain (true); return jmsTemplate;}.}
Message producer (PubSubProducer.java)
@ Componentpublic class PtpProducer {@ Autowired private JmsTemplate jmsTopicTemplate; public void convertAndSend () {jmsTopicTemplate.convertAndSend ("topic", "I am an automatically converted message");}}
Producer call class (PubSubController.java)
RestController@RequestMapping (value = "/ pubsub") public class PtpController {@ Autowired private PubSubProducer pubSubProducer; @ RequestMapping (value = "/ convertAndSend") public String convertAndSend () {pubSubProducer.convertAndSend (); return "success";}}
Modify the DefaultJmsListenerContainerFactory class to support publish and subscribe functionality
@ SpringBootApplication@EnableJmspublic class Application {/ * JMS queue listening container factory * / @ Bean (name = "jmsTopicListenerCF") public DefaultJmsListenerContainerFactory jmsTopicListenerContainerFactory () {DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory (); factory.setConnectionFactory (connectionFactory ()); factory.setConcurrency ("1"); factory.setPubSubDomain (true); return factory;}.}
Message listener (set up 2 subscribers here)
@ Componentpublic class PubSubListener1 {@ JmsListener (destination = "topic", containerFactory = "jmsTopicListenerCF") public void receive (String msg) {System.out.println ("subscriber 1 -" + msg);}} @ Componentpublic class PubSubListener2 {@ JmsListener (destination = "topic", containerFactory = "jmsTopicListenerCF") public void receive (String msg) {System.out.println ("subscriber 2 -" + msg);}}
Demo
Curl-XGET 127.0.0.1:8080/pubSub/convertAndSend
Consumer console information:
ActiveMQ console information:
After reading this article, I believe you have a certain understanding of "what does JMS mean?" if you want to know more about it, you are welcome to follow the industry information channel. Thank you for your reading!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.