6.ActiveMQ消息组成与高级特性
6.1JMS消息组成详解
整个JMS消息协议组成结构:
结构 | 描述 |
JMS Provider | 消息中间件/消息服务器 |
JMS Producer | 消息生产者 |
JMS Consumer | 消息消费者 |
JMS Message | 消息(重要) |
JMS Message消息由三部分组成:
(1)消息头
(2)消息体
(3)消息属性
1.消息头
JMS消息头定义了若干字段,用于客户端与JMS提供者之间识别和发送消息。
2.消息体
在消息体中,JMS API定义了五种类型的消息格式,让我们可以以不同的形式发送和接收消息,并提供了对已有消息格式的兼容。
类型 | 描述 |
TextMessage | 字符串类型 |
MapMessage | 键值对类型 |
ObjectMessage | java对象类型 |
BytesMessage | 字节类型 |
StreamMessage | 原始数据流类型 |
文本消息
@Autowired
private JmsTemplate jmsTemplate;
/**
* 文本消息
*/
@RequestMapping("/testText.do")
public void testMessage() {
jmsTemplate.send(this.queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage("文本消息");
return textMessage;
}
});
}
/**
* 点对点的消息接受者
*/
@Component
public class QueueConsumerListener {
//queue模式的消费者
@JmsListener(destination = "${spring.activemq.queue-name}")
public void readActiveMessage(Message message){
if (message instanceof TextMessage){
TextMessage textMessage=(TextMessage)message;
try {
System.out.println("接收消息:"+textMessage.getText());
}catch (Exception e){
e.printStackTrace();
}
}
}
}
map消息
/**
* 发送MapMseeage消息
*/
@RequestMapping("/testMap.do")
public void testMapMessage(){
jmsTemplate.send(this.queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
MapMessage mapMessage = session.createMapMessage();
mapMessage.setString("name","张三");
mapMessage.setInt("age",20);
return mapMessage;
}
});
}
/**
* 接收map消息
*/
@JmsListener(destination = "${spring.activemq.queue-name}")
public void readActiveMessage(Message message){
if (message instanceof MapMessage){
MapMessage mapMessage = (MapMessage) message;
try {
System.out.println("名称:"+mapMessage.getString("name"));
System.out.println("年龄:"+mapMessage.getString("age"));
}catch (Exception e){
e.printStackTrace();
}
}
}
ObjectMessage消息
/**
* 发送ObjectMseeage消息
*/
@RequestMapping("/testObject.do")
public void testObjectMessage(){
jmsTemplate.send(this.queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
UserBean userBean = new UserBean();
userBean.setName("韩小信");
userBean.setAge(33);
// createObjectMessage(java.io.Serializable serializable )
//该对象必须实现序列化,UserBean类实现序列化接口
ObjectMessage objectMessage = session.createObjectMessage((Serializable) userBean);
return objectMessage;
}
});
}
/**
* 接收Object消息
*/
@JmsListener(destination = "${spring.activemq.queue-name}")
public void readActiveMessage(Message message){
if (message instanceof ObjectMessage){
ObjectMessage objectMessage = (ObjectMessage) message;
try {
UserBean userBean = (UserBean) objectMessage.getObject();
System.out.println(userBean.getName());
System.out.println(userBean.getAge());
}catch (Exception e){
e.printStackTrace();
}
}
}
原因:ActiveMQ5.12后,为了安全考虑,ActiveMQ默认不接受自定义的序列化对象,需要将自定义的加入到受信任列表。
解决方案:
#让ActiveMQ信任全部自定义对象,实现对象的序列化或反序列化
spring.activemq.packages.trust-all=true
测试来一下,不生效还是一样报错
换一个方法:在创建连接工厂的时候设置这个属性
//创建链接工厂
@Bean
public ConnectionFactory connectionFactory(){
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(username, password, brokerUrl);
factory.setTrustAllPackages(true);
return factory;
}
测试成功
输出:
韩小信
33
BytesMessage消息
/**
* 发送bytesMseeage消息
*/
@RequestMapping("/testBytes.do")
public void testBytesMessage(){
jmsTemplate.send(this.queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
BytesMessage bytesMessage = session.createBytesMessage();
//1.读取文件
File file = new File("G:/8ec23612b5d317e05c4f819b3191aec.jpg");
//2.构建文件输入流
try {
FileInputStream inputStream = new FileInputStream(file);
//3.把文件写入到缓存数组中
byte[] bytes = new byte[(int) file.length()];
inputStream.read(bytes);
//4.把缓存数组写入到BytesMessage中
bytesMessage.writeBytes(bytes);
} catch (Exception e) {
e.printStackTrace();
}
return bytesMessage;
}
});
}
/**
* 接收bytes消息
*/
@JmsListener(destination = "${spring.activemq.queue-name}")
public void readActiveMessage(Message message){
if (message instanceof BytesMessage){
BytesMessage bytesMessage = (BytesMessage) message;
try {
System.out.println("接收消息内容:"+bytesMessage.getBodyLength());
//1.创建缓存数组
byte[] bytes = new byte[(int) bytesMessage.getBodyLength()];
//2.把字节消息内容读入到缓存数组
bytesMessage.readBytes(bytes);
//3.构建文件输出流
FileOutputStream outputStream = new FileOutputStream("G:/test1.jpg");
//4.把数据写出到本地硬盘
outputStream.write(bytes);
outputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
StreamMessage消息
/**
* 发送streamMseeage消息
*/
@RequestMapping("/testStream.do")
public void testStreamMessage(){
jmsTemplate.send(this.queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
StreamMessage streamMessage = session.createStreamMessage();
streamMessage.writeString("你好,ActiveMQ");
streamMessage.writeInt(27);
return streamMessage;
}
});
}
/**
* 接收Stream消息
*/
@JmsListener(destination = "${spring.activemq.queue-name}")
public void readActiveMessage(Message message) {
if (message instanceof StreamMessage) {
StreamMessage streamMessage = (StreamMessage) message;
try {
System.out.println(streamMessage.readString());
System.out.println(streamMessage.readInt());
} catch (Exception e) {
e.printStackTrace();
}
}
}