(1)首先一般在项目中的使用无非不就是把消息发送到ActiveMQ中的消息队列中去,先要考虑是使用点对点的模式,还是使用topic发布订阅的模式来进行发送的。然后就是结合自己的业务,看你放到ActiveMQ中的是什么类型的数据,然后采用不同的Message类型
- TextMessage
- MapMessage
- BytesMessage(我这里项目中采用的是字节数组类型的)
- StreamMessage
- ObjectMessage
(2)然后其实就是封装send方法,当然你可以用Jmstemeplate这个模板类型来进行使用原生的API,但是我这里是自己封装的sendMessage()方法,封装到ActiveMQService类中,用的时候直接注入ActiveMQService这个类就行了
/**
* @FileName: ActiveMqService.java
* @Description: ActiveMqService.java类说明
* @Author: admin
* @Date: 2019/5/31 11:56
*/
@Slf4j
@Service
public class ActiveMqServiceImpl implements ActiveMqService{
@Value("${spring.activemq.broker-url}")
private String mBrokerURL;
@Value("${spring.activemq.user}")
private String user;
@Value("${spring.activemq.password}")
private String password;
@Override
public Boolean sendMessage(String destinationName, ActiveMqTask activeMqTaskData) {
MessageProducer producer = null;
Session session = null;
try {
session = getSession();
Destination destination = session.createQueue(destinationName);
log.info("发送到MQ的目的队列为:{}",destinationName);
producer = session.createProducer(destination);
BytesMessage message = session.createBytesMessage();
byte[] data = objectToBytes(activeMqTaskData);
message.writeBytes(data);
producer.send(message);
log.info("发送到:{}消息队列中成功!",destinationName);
}catch (Exception e){
log.info("发送到:{}消息队列异常失败!",destinationName);
return false;
}finally {
if(producer != null){
try {
producer.close();
log.info("关闭生产者");
} catch (JMSException e) {
e.printStackTrace();
}
}
if(session != null){
try {
session.close();
log.info("关闭session连接");
} catch (JMSException e) {
e.printStackTrace();
}
}
}
return true;
}
/**
* @Author: wangwei
* @Description: 这个是用来封装获取session的方法
* @Param: * @Param: null
* @Date: 2019-06-04
*/
public Session getSession(){
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user,password,mBrokerURL);
Connection connection = null;
Session session = null;
try {
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
} catch (JMSException e) {
log.info("没有成功连接到ActiveMQ的服务器");
e.printStackTrace();
}
log.info("从connection获取session成功!");
return session;
}
/**
* @Author: wangwei
* @Description: 把消息对象转为byte数组进行传输
* @Param: * @Param: null
* @Date: 2019-06-04
*/
public byte[] objectToBytes(ActiveMqTask activeMqTask) throws Exception {
log.info("把任务名为:{}的对象转换为byte数组",activeMqTask.getName());
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream sOut = new ObjectOutputStream(out);
sOut.writeObject(activeMqTask);
sOut.flush();
byte[] bytes = out.toByteArray();
return bytes;
}
}
(3)封装好sendMessage方法之后,就是在项目中具体怎么去监听一个ActiveMQ中的Queue或者Topic主题的事件了,这个就是监听的时候使用到的方法
/**
* @Author: wangwei
* @Description: 监听任务进度更新的消息队列
* @Param: * @Param: null
* @Date: 2019-06-04
*/
@JmsListener(destination = "DX_MOBSEC_task_progress_queue")
public void listerProgressQueueMessage(BytesMessage bytesMessage) {
TaskProgressBO taskProgressBO = null;
log.info("*****************************开始监听DX_MOBSEC_task_progress_queue队列中的任务*******************************");
if (bytesMessage != null) {
try {
taskProgressBO = ActiveMqUtils.fromMessageToTaskProgress(bytesMessage);
if (taskProgressBO != null) {
int effectResult = fastenProtectExtendMapper.updTaskProgressById(taskProgressBO);
if (effectResult > 0) {
log.info("更新任务:{}进度信息成功!", taskProgressBO.getId());
} else {
log.info("更新任务:{}进度信息失败!", taskProgressBO.getId());
}
}
} catch (Exception e) {
log.info("把BytesMessage转为实体的过程中失败!");
}
} else {
log.info("监听到[DX_MOBSEC_task_progress_queue]的BytesMessage类型的信息为NULL");
}
}
这个是需要把上面监听到主题的数据内容给转换成你想要的实体对象(因为一般和业务结合的话,这个数据都是放在对象实体中的,因为发送消息的时候使用到的Message类型是BytesMessage类型,所以这里也需要把接收的Message对象转为实体)
- 这里有几个坑需要注意一下:首先你得知道BytesMessage和TextMessage等等,他们都是继承自Message对象,所以这里的message其实就是指我们接受到的BytesMessage类型
- 第一个坑就是发送数据使用到的XXXXMessage类型和接收到的Message类型必须要保持一致,不然是接收不到数据的,还会报错
- 第二个坑就是你的ActiveMQ的brokerUrl的地址是 tcp://10.0.0.203:61616这种的,而不是8161的这种端口,不然会报错 javax.jms.JMSException: Unknown data type: 47
/**
* @Author: wangwei
* @Description: 把消费到的Message信息通过byte[]字节数组过渡到TaskProgressBO对象
* @Param: * @Param: null
* @Date: 2019-06-04
*/
public static TaskProgressBO fromMessageToTaskProgress(Message message){
try(ByteArrayOutputStream bos = new ByteArrayOutputStream()){
byte buff[] = new byte[256];
int length;
while((length = ((BytesMessage)message).readBytes(buff)) > 0){
bos.write(buff, 0, length);
}
return ActiveMqUtils.fromBytesToTaskProgress(bos.toByteArray());
}catch (IOException e){
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
return null;
}
把传输过来的字节数组转为TaskProgressBO对象
/**
* @Author: wangwei
* @Description: 把传输过来的字节数组转为TaskProgressBO对象
* @Param: * @Param: null
* @Date: 2019-06-04
*/
public static TaskProgressBO fromBytesToTaskProgress(byte[] bytes){
try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))){
return (TaskProgressBO)ois.readObject();
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}
return null;
}