ActiveMQ自定义messageid

来源:互联网 发布:mac暗黑3无法进入游戏 编辑:程序博客网 时间:2024/05/14 05:01

最近做ActiveMQ相关工作,有需求发送JMS里使用自定义的Timestamp和MessageID.

修改Timestamp

很顺利.Producer对象设置 setDisableMessageTimestame(true) .在发送Message前给Message设置 setJMSTimestamp(当前时间的毫秒数) 再发送,从总线看到的Timestamp就是自定义的时间了

修改MessageID

很坑爹,花了两天时间.本以为同timestamp一样给 Producer 设置 setDisableMesssageID(true) 然后在发送Message前给Message设置 setJMSMessageID(...) 就能得到预期的效果,但结果令我失望.后来以各种方式对ConnectionFactory、Producer、Message进行设置都无效.于是我找了它的源码研究下发现,它的发送代码有这样一个片段

[java] view plain copy
  1. // transform to our own message format here  
  2. ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);  
  3.    
  4. // Set the message id.  
  5. if (msg == message) {  
  6.     msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));  
  7. else {  
  8.     msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));  
  9.     message.setJMSMessageID(msg.getMessageId().toString());  
  10. }  

我不知道这是神马黑科技,为么if else里都给message设置同样的值.且不说这个,我把代码

[java] view plain copy
  1. ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);  

拿出来测试发现msg总和我自己的message相等,哥们费解了.else同学,你是来打酱油的吗

哥们被坑了,time is money frend一天时间就这样没了.算了哥们我自立更生,过程很曲折.

根据发送源码知道

[java] view plain copy
  1. msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));  
messageid是从Producer中获得的.更具体地说是从ProducerId的getConnectionId()中得到的,所以只要把ProcuderId中的 getConnectionId() 改了就行吧,根据我的分析它们的关系如下

ConnectionFactory--生成-->Connection--生成-->Session--生成-->Producer

就是说要得到自己的Producer得从ConnectionFactory做起,经过漫长的继承和重载终于有了自己的ProducerId,当我根据业务返回自定义messageid后发现总线没有收到或者说程序没有成功发送消息.由此知道如果生成和发送时的connectionid不一样就不会发送数据,如果要改就得从connection生成时改.哥们绕远路了,还是个错路.

最终我分析出的逻辑大体是这样:

ConnectionFactory生成Connection

Connection生成Session并传入ConnectionInfo

Session生成Producer并传入ConnectionInfo和SessionInfo.

所以ConnectionInfo是关键,这样只要重写ActiveMQConnectionFactory和ActiveMQConnection两个类就行了.我在重写Factory中加了一个createConnection(String messageid)方法返回自己重写的Connection类,在重写的Connection中声明一个新的ConnectionInfo 属性,并在构造方法中重新构造ConnectionInfo ,再覆盖原来的getConnectionInfo()方法,返回本类中声明的ConnectionInfo对象就搞定了.

代码片段

CustomActiveMQConnectionFactory.Java

[java] view plain copy
  1. Transport transport = super.createTransport();  
  2. connection = new CustomActiveMQConnection(transport,super.getClientIdGenerator(),factoryStats,messageid);  
  3. connection.setUserName(userName);  
  4. connection.setPassword(password);  
  5. super.configureConnection(connection);  
  6. transport.start();  
  7. if (clientID != null) {  
  8.     connection.setDefaultClientID(clientID);  
  9. }  
  10. return connection;  

CustomActiveMQConnection.java

[java] view plain copy
  1. public CustomActiveMQConnection(final Transport transport,  
  2.         IdGenerator clientIdGenerator, JMSStatsImpl factoryStats,String messageid)  
  3.         throws Exception {  
  4.     super(transport, clientIdGenerator, factoryStats);  
  5.     //取得生动生成的connectionid  
  6.     String uniqueId = super.getConnectionInfo().getConnectionId().getValue();  
  7.        if(messageid!=null){//替换机器名  
  8.         Matcher matcher = pattern.matcher(uniqueId);  
  9.         if(matcher.find()){  
  10.             String localName = matcher.group(1);  
  11.             uniqueId = uniqueId.replace(localName, messageid);  
  12.         }  
  13.        }  
  14.        //构造自己的connectionInfo  
  15.     this.info = new ConnectionInfo(new ConnectionId(uniqueId));  
  16.        this.info.setManageable(true);  
  17.        this.info.setFaultTolerant(transport.isFaultTolerant());  
  18. }  


代码下载

原文代码:http://blog.csdn.net/fxz1982/article/details/7480073


0 0
原创粉丝点击