ActiveMQ自定义messageid

本文详细介绍了如何在ActiveMQ中自定义消息的Timestamp和MessageID,包括设置方法、源码解析及实现过程,以及遇到的问题和解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

修改Timestamp

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

修改MessageID

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

// transform to our own message format here
ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);
 
// Set the message id.
if (msg == message) {
    msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
} else {
    msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
    message.setJMSMessageID(msg.getMessageId().toString());
}

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

ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);

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

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

根据发送源码知道

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

Transport transport = super.createTransport();
connection = new CustomActiveMQConnection(transport,super.getClientIdGenerator(),factoryStats,messageid);
connection.setUserName(userName);
connection.setPassword(password);
super.configureConnection(connection);
transport.start();
if (clientID != null) {
    connection.setDefaultClientID(clientID);
}
return connection;

CustomActiveMQConnection.java

	public CustomActiveMQConnection(final Transport transport,
			IdGenerator clientIdGenerator, JMSStatsImpl factoryStats,String messageid)
			throws Exception {
		super(transport, clientIdGenerator, factoryStats);
		//取得生动生成的connectionid
		String uniqueId = super.getConnectionInfo().getConnectionId().getValue();
        if(messageid!=null){//替换机器名
        	Matcher matcher = pattern.matcher(uniqueId);
    		if(matcher.find()){
    			String localName = matcher.group(1);
    			uniqueId = uniqueId.replace(localName, messageid);
    		}
        }
        //构造自己的connectionInfo
		this.info = new ConnectionInfo(new ConnectionId(uniqueId));
        this.info.setManageable(true);
        this.info.setFaultTolerant(transport.isFaultTolerant());
	}


代码下载


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值