1. 配置连接工厂bean
1.1. 我们要想发送消息到ActiveMQ, 就需要创建客户和提供者之间的连接, 连接工厂(ActiveMQConnectionFactory)可以完成这个工作。
1.2. 可以配置spring包下的org.apache.activemq.spring.ActiveMQConnectionFactory
1.3. org.apache.activemq.spring.ActiveMQConnectionFactory类在下面这个jar包中
1.4. org.apache.activemq.spring.ActiveMQConnectionFactory继承自org.apache.activemq.ActiveMQConnectionFactory
1.5. 在org.apache.activemq.spring.ActiveMQConnectionFactory中, 可以使用brokerURL属性来指定ActiveMQ的地址和端口号。
2. 配置目的地对象
2.1. 除了连接工厂外, 我们还需要消息传递的目的地。目的地可以是一个队列, 也可以是一个主题, 这取决于应用的需求。
2.2. 队列模式
2.3. 主题模式
2.4. 在org.apache.activemq.command.ActiveMQQueue或 org.apache.activemq.command.ActiveMQTopic中, 可以使用physicalName属性来指定队列或主题的名字。
2.5. 如果消息目的地是队列模式, 也可以不配置(不推荐), 在发送和接收消息的时候指定目的地名称即可。在发送和接收消息的时候设置一个名称, 但它只是一个名称, 它并没有说明你所处理的目的地是什么类型, 如果已经存在该名称的队列或主题的话, 就会使用已有的; 如果尚未存在的话, 将会创建一个新的目的地, 通常会是队列。
3. 配置模板类
3.1. 针对如何消除冗长和重复的JMS代码, Spring给出的解决方案是JmsTemplate。JmsTemplate可以创建连接、获得会话、发送和接收消息。
3.2. 因为JmsTemplate需要知道如何连接到消息提供者, 所以我们必须为connection-Factory属性设置实现了JMS的ConnectionFactory接口的bean引用。
3.3. 在org.springframework.jms.core.JmsTemplate中, 可以使用defaultDestination属性来指定默认目的地。这样就不必在每次发送和接收消息的时候指定目的地。当然我们这里也可以不必配置目的地, 然后在发送和接收消息的时候指定目的地。
3.4. org.springframework.jms.core.JmsTemplate类实现了org.springframework.jms.core.JmsOperations接口。
3.5. 另外, JmsTemplate可以处理所有抛出的笨拙的JMSException异常。如果在使用JmsTemplate时抛出JMSException异常, JmsTemplate将捕获该异常, 然后抛出一个非检查型异常(JMSException都是检查型异常, 因此必须捕获), 该异常是Spring自带的, 是JmsException异常的子类。
4. 发送消息
4.1. send()方法发送消息, 第一个是消息的目的地(可选参数), 第二个便是具体的消息。我们使用MessageCreator(在这里的实现是作为一个匿名内部类)来构造消息, 在MessageCreator的createMessage()方法中, 有一个session对象, session对象可以创建各种各样的消息(文本消息、流消息、映射消息、对象消息等), 然后返回消息对象。
4.2. JmsTemplate还提供了convertAndSend()方法, 发送消息时, 对消息进行转换。与send()方法不同, convertAndSend()方法并不需要MessageCreator作为参数, 这是因convertAndSend()会使用内置的消息转换器(message converter)为我们创建消息。
4.3. 在发送之前转换为Message, JmsTemplate内部会进行一些处理, 它使用一个MessageConverter的实现类将对象转换为Message。MessageConverter是Spring定义的接口, 只有两个需要实现的方法:
4.4. 默认的转换器
4.5. MappingJackson2MessageConverter: 使用Jackson JSON库实现消息和JSON格式之间的相互转换。
4.6. MarshallingMessageConverter: 使用JAXB库实现消息和XML格式之间的相互转换。
4.7. SimpleMessageConverter: 实现String和TextMessage之间的转换、字节数组和BytesMessage之间的转换、Map和MapMessage之间的转换、Serializable对象和ObjectMessage之间的转换。
4.8. 默认情况下, JmsTemplate在convertAndSend()方法中会使用SimpleMessageConverter。如果你想使用JSON消息的话, 那么可以声明一个MappingJackson2MessageConverter类型的Bean, 然后把它注入到JmsTemplate的messageConverter属性中。
5. 接收消息
5.1. receive()方法接收消息, 它有一个可选的消息目地参数。当调用JmsTemplate的receive()方法时, JmsTemplate会尝试从消息代理中获取一个消息, 如果没有可用的消息, receive()方法会一直等待, 直到获得消息为止。
5.2. 这里有一点需要注意, 当调用message.getText()方法时会抛出JMSException, 这个异常是属于JMS API的。JMSException是一个检查异常, 在JMS *** 作中会抛出各种各样的JMSException, 但是前面我们使用JmsTemplate时并没有捕获任何JMSException, 是因为JmsTemplate内部已经将需要检查的JMSException转换成了非检查的Spring自己的JmsException。在上面代码中因为调用的是message.getText()方法而不是JmsTemplate的方法, 所以我们需要捕获JMSException。但是按照Spring的设计理念, 我们应该尽量减少检查异常, 所以在catch块里面我们又通过JmsUtils工具把JMSException转换成了非检查的JmsException。
5.3. JmsTemplate同样提供了receiveAndConvert()方法, 在接收消息时, 对消息进行转换。因为使用的是JmsTemplate的方法, 所以我们不需要再捕获JMSException检查异常。这个接收消息代码只有一行有效代码, 非常简洁。
5.4. 不管使用msTemplate的receive()还是receiveAndConvert()方法消费消息, 它们都是同步的, 也就是说接收者在消息到达时需要等待。
6. 异步接收消息
6.1. 要想在消息出现时得到通知, 那么就需要一个监听器监听queue或者topic。Spring提供了以POJO的方式处理消息的能力, 不需要依赖任何接口。在EJB中, message driven bean(MDB)就可以实现异步的处理消息。Spring在这方面参考了EJB3对MDB的实现, 不过在Spring中我们把它称作消息驱动POJO, 也就是message-driven POJO(MDP)。
6.2. 赋予上面POJO接收消息能力的关键在于将其配置成一个Spring消息监听器, Spring的jms命名空间提供了所有相关配置。首先, 我们现需要把上面的POJO对象声明成一个bean。其次, 把MessageHandler变成一个消息驱动POJO, 即把这个bean声明成一个listener。
7. 异步接收消息-实现MessageListener接口
7.1. MessageListener接口
7.2. 我们的MessageHandler还可以实现一个MessageListener接口, 这样的话就不需要再单独指定消息处理的方法了, MyMessageListener的onMessage()方法会自动被调用。
7.3. 然后直接配置listener即可(不用再配置method方法属性)。
8. 对象序列化包名的白名单限制
8.1. ActiveMQ对序列化有包名的白名单限制, 可以把包名加入到配置中, 或者关闭掉白名单限制。
9. SpringJMS发送文本消息例子
9.1. 新建一个名为SpringJMSText的Java项目, 拷入相关jar包。
9.2. 新建JmsQueueSender.java
package com.lywgames.jms; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.Session; import org.springframework.jms.core.JmsOperations; import org.springframework.jms.core.MessageCreator; public class JmsQueueSender { private JmsOperations jmsOperations; public void setJmsOperations(JmsOperations jmsOperations) { this.jmsOperations = jmsOperations; } public void sendMessage(String message) { jmsOperations.send("myspringjmsqueue", new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { return session.createTextMessage(message); } }); } }
9.3. 新建JmsQueueReceiver.java
package com.lywgames.jms; import javax.jms.JMSException; import javax.jms.TextMessage; import org.springframework.jms.core.JmsOperations; import org.springframework.jms.support.JmsUtils; public class JmsQueueReceiver { private JmsOperations jmsOperations; public void setJmsOperations(JmsOperations jmsOperations) { this.jmsOperations = jmsOperations; } public void receiveMessage() { TextMessage msg = (TextMessage) jmsOperations.receive("myspringjmsqueue"); try { // 非jms模板抛出的异常 System.out.println(msg.getText()); } catch (JMSException e) { e.printStackTrace(); JmsUtils.convertJmsAccessException(e); } } }
9.4. 在src目录下配置applicationContext.xml
9.5. 新建Test.java
package com.lywgames.jms; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // 1. 类路径加载配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 获取JmsQueueSender JmsQueueSender jmsQueueSender = context.getBean(JmsQueueSender.class); // 3. 调用JmsQueueSender的sendMessage方法, 发送消息 jmsQueueSender.sendMessage("Spring JMS发送文本消息。"); // 4. 获取JmsQueueReceiver JmsQueueReceiver jmsQueueReceiver = context.getBean(JmsQueueReceiver.class); // 5. 调用JmsQueueReceiver的receiveMessage方法, 获取消息 jmsQueueReceiver.receiveMessage(); // 6. 关闭应用程序上下文 context.close(); } }
9.6. 运行项目效果图
10. SpringJMS发送对象消息例子
10.1. 新建一个名为SpringJMSObject的Java项目, 拷入相关jar包。
10.2. 新建User.java
package com.lywgames.jms; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String userName; private String password; public User() { } public User(String userName, String password) { this.userName = userName; this.password = password; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [userName=" + userName + ", password=" + password + "]"; } }
10.3. 新建JmsQueueSender.java
package com.lywgames.jms; import org.springframework.jms.core.JmsTemplate; public class JmsQueueSender { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendMessage(Object message) { jmsTemplate.convertAndSend(message); } }
10.4. 新建JmsQueueReceiver.java
package com.lywgames.jms; import org.springframework.jms.core.JmsTemplate; public class JmsQueueReceiver { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void receiveMessage() { User user = (User) jmsTemplate.receiveAndConvert(); System.out.println(user); } }
10.5. 在src目录下配置applicationContext.xml
10.6. 新建Test.java
package com.lywgames.jms; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // 1. 类路径加载配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 获取JmsQueueSender JmsQueueSender jmsQueueSender = context.getBean(JmsQueueSender.class); // 3. 调用JmsQueueSender的sendMessage方法, 发送消息 jmsQueueSender.sendMessage(new User("zhangsan", "123456")); // 4. 获取JmsQueueReceiver JmsQueueReceiver jmsQueueReceiver = context.getBean(JmsQueueReceiver.class); // 5. 调用JmsQueueReceiver的receiveMessage方法, 获取消息 jmsQueueReceiver.receiveMessage(); // 6. 关闭应用程序上下文 context.close(); } }
10.7. 运行项目效果图
11. SpringJMS消息和JSON格式转换例子
11.1. 新建一个名为SpringJMSJson的Java项目, 拷入相关jar包。
11.2. 新建User.java
package com.lywgames.jms; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String userName; private String password; public User() { } public User(String userName, String password) { this.userName = userName; this.password = password; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [userName=" + userName + ", password=" + password + "]"; } }
11.3. 新建Product.java
package com.lywgames.jms; import java.io.Serializable; public class Product implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String name; public Product() { } public Product(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
11.4. 新建MyJsonConverter.java
package com.lywgames.jms; import java.util.HashMap; import java.util.Map; import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageType; public class MyJsonConverter extends MappingJackson2MessageConverter { public MyJsonConverter() { // 定义typeId到Class的映射 Map> typeIdMappings = new HashMap >(); typeIdMappings.put(User.class.getName(), User.class); typeIdMappings.put(Product.class.getName(), Product.class); // 消息是文本类型 this.setTargetType(MessageType.TEXT); // 设置typeId和Class的映射 this.setTypeIdMappings(typeIdMappings); // 发送到目的地的TypeId的名称 // this.setTypeIdPropertyName(Product.class.getName()); } }
11.5. 新建JmsQueueSender.java
package com.lywgames.jms; import org.springframework.jms.core.JmsTemplate; public class JmsQueueSender { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendMessage(Object message, String typeIdPropertyName) { MyJsonConverter converter = (MyJsonConverter) jmsTemplate.getMessageConverter(); converter.setTypeIdPropertyName(typeIdPropertyName); jmsTemplate.convertAndSend(message); } }
11.6. 新建JmsQueueReceiver.java
package com.lywgames.jms; import javax.jms.JMSException; import org.apache.activemq.command.ActiveMQTextMessage; import org.springframework.jms.core.JmsTemplate; public class JmsQueueReceiver { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void receiveMessage(String typeIdPropertyName) { try { MyJsonConverter converter = (MyJsonConverter) jmsTemplate.getMessageConverter(); converter.setTypeIdPropertyName(typeIdPropertyName); // 这里不能使用receiveAndConvert()方法 ActiveMQTextMessage obj = (ActiveMQTextMessage) jmsTemplate.receive(); System.out.println(obj.getText()); } catch (JMSException e) { e.printStackTrace(); } } }
11.7. 在src目录下配置applicationContext.xml
11.8. 新建Test.java
package com.lywgames.jms; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // 1. 类路径加载配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 获取JmsQueueSender JmsQueueSender jmsQueueSender = context.getBean(JmsQueueSender.class); // 3. 调用JmsQueueSender的sendMessage方法, 发送消息 jmsQueueSender.sendMessage(new User("李四", "123456"), User.class.getName()); // jmsQueueSender.sendMessage(new Product(1001, "牛奶"), Product.class.getName()); // 4. 获取JmsQueueReceiver JmsQueueReceiver jmsQueueReceiver = context.getBean(JmsQueueReceiver.class); // 5. 调用JmsQueueReceiver的receiveMessage方法, 获取消息 jmsQueueReceiver.receiveMessage(User.class.getName()); // 6. 关闭应用程序上下文 context.close(); } }
11.9. 运行项目效果图
12. SpringJMS异步接收消息例子
12.1. 新建一个名为SpringJMSMap的Java项目, 拷入相关jar包。
12.2. 新建JmsQueueSender.java
package com.lywgames.jms; import org.springframework.jms.core.JmsTemplate; public class JmsQueueSender { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendMessage(Object message) { jmsTemplate.convertAndSend(message); } }
12.3. 新建AnsyJmsQueueReceiver.java
package com.lywgames.jms; import java.util.Map; public class AnsyJmsQueueReceiver { public void handleMessage(Mapmessage){ System.out.println(message); } }
12.4. 在src目录下配置applicationContext.xml
12.5. 新建Test.java
package com.lywgames.jms; import java.util.HashMap; import java.util.Map; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // 1. 类路径加载配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 获取JmsQueueSender JmsQueueSender jmsQueueSender = context.getBean(JmsQueueSender.class); Mapmap = new HashMap (); map.put("id", 100000000000L); map.put("name", "lisi"); // 3. 调用JmsQueueSender的sendMessage方法, 发送消息 jmsQueueSender.sendMessage(map); // 4. 关闭应用程序上下文 context.close(); } }
12.6. 运行项目效果图
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)