消息类型
JMS消息由以下三部分组成的:
消息头
每个消息头字段都有相应的getter和setter方法。
消息属性
如果需要除消息头字段以外的值,那么可以使用消息属性。
消息体
JMS定义的消息类型有TextMessage、MapMessage、BytesMessage、StreamMessage和
ObjectMessage。
TextMessage
文本消息
MapMessage
k/v
BytesMessage
字节流
StreamMessage
java原始的数据流
ObjectMessage
序列化的java对象
我们就以ObjectMessage和BytesMessage为例写个小案例
首先创建一个实现序列化的实体类,因为通过ActiveMQ传输对象时是通过序列化传输,反序列化接收的,所以实体类一定要实现序列化
public class Girl implements Serializable {
String name;//姓名
int age;//年龄
double price;//彩礼价格
public Girl(String name, int age, double price) {
this.name = name;
this.age = age;
this.price = price;
}
@Override
public String toString() {
return "Girl{" +
"name='" + name + '\'' +
", age=" + age +
", price=" + price +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
消息发送者Sender.java
/**
* 消息发送者
*/
public class Sender {
public static void main(String[] args) throws JMSException {
//创建连接
ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(
"admin",
"123",
"tcp://localhost:61616");
Connection connection = mqConnectionFactory.createConnection();
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("queue");
MessageProducer producer = session.createProducer(queue);
Girl girl = new Girl("小丽",25,200.00);
ObjectMessage objectMessage = session.createObjectMessage(girl);
//发送字节流,图片,文件等相对来说比较小的
BytesMessage bytesMessage = session.createBytesMessage();
bytesMessage.writeUTF("发送字节流");
producer.send(objectMessage);
producer.send(bytesMessage);
session.close();
System.out.println("关闭连接");
}
}
消息接收者Receiver.java,在接收者里面定义了一个监听器来处理消息
public class Receiver {
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(
"admin",
"123",
"tcp://localhost:61616"
);
//设置信任持久化类型
ArrayList<String> list = new ArrayList<String>();
list.add(Girl.class.getPackage().getName());
mqConnectionFactory.setTrustedPackages(list);
Connection connection = mqConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("queue");
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(new MyListener());
}
}
监听器MyListener.java
public class MyListener implements MessageListener {
public void onMessage(Message message) {
if(message instanceof ObjectMessage){
ObjectMessage objectMessage = (ObjectMessage) message;
try {
Girl girl = (Girl) objectMessage.getObject();
System.out.println(girl.toString());
} catch (JMSException e) {
e.printStackTrace();
}
}else if(message instanceof BytesMessage){
BytesMessage bytesMessage = (BytesMessage) message;
try {
System.out.println(bytesMessage.readUTF());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
运行发送者,接收者就可以看到接收者已经接收到了girl对象和字节流
死信队列
死信队列是用来保存处理失败或者过期的消息的队列,默认的死信队列是ActiveMQ.DLQ,如果没有特别指定,死信都会被发送到这个队列。默认的持久化消息过去,会被送到DLQ,非持久消息不会送到DLQ,我们可以通过配置文件(activemq.xml)来修改死信队列的配置
1、不使用默认的死信队列
<broker...>
<destinationPolicy>
<policyMap>
<policyEntries>
<!— 设置所有队列,使用 '>' ,否则用队列名称 -->
<policyEntry queue=">">
<deadLetterStrategy>
<!--
queuePrefix:设置死信队列前缀
useQueueForQueueMessages: 设置使用队列保存死信,还可以设置useQueueForTopicMessages,使用Topic来保存死信
-->
<individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true" />
</deadLetterStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
...
</broker>
2、非持久化消息保存到死信队列
<policyEntry queue=">">
<deadLetterStrategy>
<sharedDeadLetterStrategy processNonPersistent="true" />
</deadLetterStrategy>
</policyEntry>
3、过期消息不保存到死信队列
<policyEntry queue=">">
<deadLetterStrategy>
<sharedDeadLetterStrategy processExpired="false" />
</deadLetterStrategy>
</policyEntry>
4、持久消息不保存到死信队列
丢弃所有死信
<beans>
<broker ...>
<plugins>
<discardingDLQBrokerPlugin dropAll="true" dropTemporaryTopics="true" dropTemporaryQueues="true" />
</plugins>
</broker>
</beans>
丢弃指定目的死信
<beans>
<broker ...>
<plugins>
<discardingDLQBrokerPlugin dropOnly="MY.EXAMPLE.TOPIC.[0-9]{3} MY.EXAMPLE.QUEUE.[0-9]{3}" reportInterval="3000" />
</plugins>
</broker>
</beans>