- 浏览: 996742 次
-
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
JMS(ActiveMQ) PTP和PUB/SUB模式实例:http://donald-draper.iteye.com/blog/2347445
ActiveMQ连接工厂、连接详解:http://donald-draper.iteye.com/blog/2348070
ActiveMQ会话初始化:http://donald-draper.iteye.com/blog/2348341
ActiveMQ生产者:http://donald-draper.iteye.com/blog/2348381
ActiveMQ消费者:http://donald-draper.iteye.com/blog/2348389
ActiveMQ启动过程详解:http://donald-draper.iteye.com/blog/2348399
ActiveMQ Broker发送消息给消费者过程详解:http://donald-draper.iteye.com/blog/2348440
Spring与ActiveMQ的集成:http://donald-draper.iteye.com/blog/2347638
Spring与ActiveMQ的集成详解一:http://donald-draper.iteye.com/blog/2348449
Spring与ActiveMQ的集成详解二:http://donald-draper.iteye.com/blog/2348461
在Spring与ActiveMQ继承这篇文章中,消息的生产和手动消费都是依赖于JmsTemplate,今天我们就来看一
JmsTemplate,
贴上JmsTemplate配置,以便理解
再来看JmsTemplate的构造
JmsTemplateResourceFactory为JmsTemplate的内部类
从JmsTemplate的构造可以看出,主要是初始化事务资源工厂,消息转换器,传输延时,优先级,消息生存时间
再来看发送消息
再来看执行回调接口
先看当会话为null时的情况:
创建连接
//JmsAccessor
创建会话
当会话不为空的情况:
//ConnectionFactoryUtils
来看从事务同步管理器获取JmsResourceHolder
//事务同步器注册到事务同步管理器
//JmsResourceSynchronization
//ResourceHolderSynchronization
绑定连接工厂与资源holder的关系
我们先理一下,TransactionSynchronizationManager,JmsResourceHolder,JmsResourceSynchronization的关系;JmsResourceHolder管理连接,会话,连接工厂,及连接与会话的映射关系,JmsResourceSynchronization为连接工厂和JmsResourceHolder及事务的包装;TransactionSynchronizationManager管理线程的事务JmsResourceSynchronization,
连接工厂和JmsResourceHolder的映射管理。
再来理一下上面这一段说了什么,JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder
获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话
回到执行会话回调接口
来看执行会话回调接口doInJms方法
生产者发送消息
再来看发送转换消息
小节一下:
JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话,然后由会话创建生产者,有生产者发送消息;对于有消息转换的,则将消息转化器包装到MessageCreator,发送时由MessageCreator,调用消息转换器的消息转化方法,
转换消息,发送消息。
再来看一JmsTemplate的消费消息
这段发送送消息相似,直接忽略掉,直接看接受消息
消费者手动消费消息分方式同样是包装成会话回调接口,会话获取与生产者发送消息的会话阶段一样,然后从会话创建消费者,消费消息,而转化消息模式,只是将消费者获取的消息通过消息转化器转换一下;
总结:
JmsTemplate的构造,主要是初始化事务资源工厂,消息转换器,传输延时,优先级,消息生存时间再来看发送消息。JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder
获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话,然后由会话创建生产者,有生产者发送消息;对于有消息转换的,则将消息转化器包装到MessageCreator,发送时由MessageCreator,调用消息转换器的消息转化方法,转换消息,发送消息。消费者手动消费消息分方式同样是包装成会话回调接口,会话获取与生产者发送消息的会话阶段一样,然后从会话创建消费者,消费消息,而转化消息模式,只是将消费者获取的消息通过消息转化器转换一下;
ActiveMQ连接工厂、连接详解:http://donald-draper.iteye.com/blog/2348070
ActiveMQ会话初始化:http://donald-draper.iteye.com/blog/2348341
ActiveMQ生产者:http://donald-draper.iteye.com/blog/2348381
ActiveMQ消费者:http://donald-draper.iteye.com/blog/2348389
ActiveMQ启动过程详解:http://donald-draper.iteye.com/blog/2348399
ActiveMQ Broker发送消息给消费者过程详解:http://donald-draper.iteye.com/blog/2348440
Spring与ActiveMQ的集成:http://donald-draper.iteye.com/blog/2347638
Spring与ActiveMQ的集成详解一:http://donald-draper.iteye.com/blog/2348449
Spring与ActiveMQ的集成详解二:http://donald-draper.iteye.com/blog/2348461
在Spring与ActiveMQ继承这篇文章中,消息的生产和手动消费都是依赖于JmsTemplate,今天我们就来看一
JmsTemplate,
贴上JmsTemplate配置,以便理解
<!-- 配置Jms模板 --> <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactoryMQ" /> <property name="defaultDestination" ref="testQueue" /> <!-- 接收消息时的超时时间 --> <!--<property name="receiveTimeout" value="10000" /> --> <!-- 消息类型转换 --> <property name="messageConverter" ref="msgConverter"></property> </bean>
public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations { public static final long RECEIVE_TIMEOUT_NO_WAIT = -1L; public static final long RECEIVE_TIMEOUT_INDEFINITE_WAIT = 0L; private static final Method setDeliveryDelayMethod; private final JmsTemplateResourceFactory transactionalResourceFactory; private Object defaultDestination;//消息目的地 private MessageConverter messageConverter;//消息转换器 private boolean messageIdEnabled; private boolean messageTimestampEnabled; private boolean pubSubNoLocal; private long receiveTimeout; private long deliveryDelay;//传输延时 private boolean explicitQosEnabled; private int deliveryMode;//消息持久化模式 private int priority;//优先级 private long timeToLive;//消息生存时间 static { //获取MessageProducer的设置传输延时方法 setDeliveryDelayMethod = ClassUtils.getMethodIfAvailable(javax/jms/MessageProducer, "setDeliveryDelay", new Class[] { Long.TYPE }); } }
public abstract class JmsDestinationAccessor extends JmsAccessor { private DestinationResolver destinationResolver;//消息目的地解决器 private boolean pubSubDomain;//是否为订阅主题模式 }
public abstract class JmsAccessor implements InitializingBean { private static final Constants sessionConstants = new Constants(javax/jms/Session); private ConnectionFactory connectionFactory;//连接工厂 private boolean sessionTransacted;//是不是事务会话 private int sessionAcknowledgeMode;//会话确认模式 }
再来看JmsTemplate的构造
public JmsTemplate() { transactionalResourceFactory = new JmsTemplateResourceFactory(); messageIdEnabled = true; messageTimestampEnabled = true; pubSubNoLocal = false; receiveTimeout = 0L; deliveryDelay = 0L; explicitQosEnabled = false; deliveryMode = 2; priority = 4; timeToLive = 0L; //初始化消息转换器 initDefaultStrategies(); } protected void initDefaultStrategies() { //初始化消息转换器 setMessageConverter(new SimpleMessageConverter()); }
JmsTemplateResourceFactory为JmsTemplate的内部类
public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations { private class JmsTemplateResourceFactory implements org.springframework.jms.connection.ConnectionFactoryUtils.ResourceFactory { public Connection getConnection(JmsResourceHolder holder) { return JmsTemplate.this.getConnection(holder); } public Session getSession(JmsResourceHolder holder) { return JmsTemplate.this.getSession(holder); } public Connection createConnection() throws JMSException { return JmsTemplate.this.createConnection(); } public Session createSession(Connection con) throws JMSException { return JmsTemplate.this.createSession(con); } public boolean isSynchedLocalTransactionAllowed() { return isSessionTransacted(); } final JmsTemplate this$0; private JmsTemplateResourceFactory() { this$0 = JmsTemplate.this; super(); } } }
从JmsTemplate的构造可以看出,主要是初始化事务资源工厂,消息转换器,传输延时,优先级,消息生存时间
再来看发送消息
public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException { //创建会话回调接口,发送消息 execute(new SessionCallback() { public Object doInJms(Session session) throws JMSException { //会话发送消息 doSend(session, destination, messageCreator); return null; } final Destination val$destination; final MessageCreator val$messageCreator; final JmsTemplate this$0; { this.this$0 = JmsTemplate.this; destination = destination1; messageCreator = messagecreator; super(); } }, false); }
再来看执行回调接口
public Object execute(SessionCallback action, boolean startConnection) throws JmsException { Connection conToClose; Session sessionToClose; Assert.notNull(action, "Callback object must not be null"); conToClose = null; sessionToClose = null; Object obj; try { //从ConnectionFactoryUtils获取事务会话 Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(getConnectionFactory(), transactionalResourceFactory, startConnection); if(sessionToUse == null) { //创建连接 conToClose = createConnection(); //创建会话 sessionToClose = createSession(conToClose); if(startConnection) conToClose.start(); sessionToUse = sessionToClose; } if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("Executing callback on JMS Session: ").append(sessionToUse).toString()); //执行会话回调接口doInJms方法 obj = action.doInJms(sessionToUse); } //关闭会话 JmsUtils.closeSession(sessionToClose); //释放连接 ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection); return obj; }
先看当会话为null时的情况:
创建连接
conToClose = createConnection();
//JmsAccessor
protected Connection createConnection() throws JMSException { //从ActiveMQConnectionFactory获取连接ActiveMQConnection return getConnectionFactory().createConnection(); }
创建会话
sessionToClose = createSession(conToClose);
protected Session createSession(Connection con) throws JMSException { //从ActiveMQConnection获取连接会话ActiveMQSession return con.createSession(isSessionTransacted(), getSessionAcknowledgeMode()); }
当会话不为空的情况:
//ConnectionFactoryUtils
public static Session doGetTransactionalSession(ConnectionFactory connectionFactory, ResourceFactory resourceFactory, boolean startConnection) throws JMSException { Assert.notNull(connectionFactory, "ConnectionFactory must not be null"); Assert.notNull(resourceFactory, "ResourceFactory must not be null"); //事务同步管理器获取JmsResourceHolder JmsResourceHolder resourceHolder = (JmsResourceHolder)TransactionSynchronizationManager.getResource(connectionFactory); Connection con; if(resourceHolder != null) { //如果JmsResourceHolder存在,则从resourceFactory获取会话 Session session = resourceFactory.getSession(resourceHolder); if(session != null) { if(startConnection) { //获取启动,则从resourceFactory获取resourceHolder对应的连接 con = resourceFactory.getConnection(resourceHolder); if(con != null) //启动连接 con.start(); } return session; } if(resourceHolder.isFrozen()) return null; } if(!TransactionSynchronizationManager.isSynchronizationActive()) return null; JmsResourceHolder resourceHolderToUse = resourceHolder; if(resourceHolderToUse == null) resourceHolderToUse = new JmsResourceHolder(connectionFactory); //从resourceFactory获取resourceHolder对应的连接 con = resourceFactory.getConnection(resourceHolderToUse); Session session = null; try { boolean isExistingCon = con != null; if(!isExistingCon) { con = resourceFactory.createConnection(); resourceHolderToUse.addConnection(con); } //resourceFactory根据连接创建会话 session = resourceFactory.createSession(con); //将连接与会话关系添加到resourceHolderToUse resourceHolderToUse.addSession(session, con); if(startConnection) con.start(); } if(resourceHolderToUse != resourceHolder) { //注册同步器 TransactionSynchronizationManager.registerSynchronization(new JmsResourceSynchronization(resourceHolderToUse, connectionFactory, resourceFactory.isSynchedLocalTransactionAllowed())); //设置事务 resourceHolderToUse.setSynchronizedWithTransaction(true); //绑定连接工厂与资源holder的关系 TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse); } return session; }
来看从事务同步管理器获取JmsResourceHolder
JmsResourceHolder resourceHolder = (JmsResourceHolder)TransactionSynchronizationManager.getResource(connectionFactory); ublic abstract class TransactionSynchronizationManager { private static final ThreadLocal resources = new ThreadLocal();//资源 private static final ThreadLocal synchronizations = new ThreadLocal();//同步器 private static final Comparator synchronizationComparator = new OrderComparator(); private static final ThreadLocal currentTransactionName = new ThreadLocal();//当前事务名 private static final ThreadLocal currentTransactionReadOnly = new ThreadLocal();//事务读写 private static final ThreadLocal currentTransactionIsolationLevel = new ThreadLocal();事务级别 private static final ThreadLocal actualTransactionActive = new ThreadLocal(); public static Object getResource(Object key) { Assert.notNull(key, "Key must not be null"); Map map = (Map)resources.get(); if(map == null) return null; Object value = map.get(key); if(value != null && logger.isDebugEnabled()) logger.debug("Retrieved value [" + value + "] for key [" + key + "] bound to thread [" + Thread.currentThread().getName() + "]"); return value; } }
//事务同步器注册到事务同步管理器
public static void registerSynchronization(TransactionSynchronization synchronization) throws IllegalStateException { Assert.notNull(synchronization, "TransactionSynchronization must not be null"); if(!isSynchronizationActive()) { throw new IllegalStateException("Transaction synchronization is not active"); } else { //添加到事务同步管理,同步集 List synchs = (List)synchronizations.get(); synchs.add(synchronization); return; } }
//JmsResourceSynchronization
public abstract class ConnectionFactoryUtils { private static class JmsResourceSynchronization extends ResourceHolderSynchronization { private final boolean transacted; public JmsResourceSynchronization(JmsResourceHolder resourceHolder, Object resourceKey, boolean transacted) { super(resourceHolder, resourceKey); this.transacted = transacted; } } }
//ResourceHolderSynchronization
public abstract class ResourceHolderSynchronization implements TransactionSynchronization { private final ResourceHolder resourceHolder; private final Object resourceKey; private volatile boolean holderActive; }
绑定连接工厂与资源holder的关系
TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse); //TransactionSynchronizationManager public static void bindResource(Object key, Object value) throws IllegalStateException { //从当前线程事务同步化管理获取工厂与资源holder的映射,并将映射关系添加到映射Map中 Map map = (Map)resources.get(); if(map == null) { map = new HashMap(); resources.set(map); } if(map.containsKey(key)) throw new IllegalStateException("Already value [" + map.get(key) + "] for key [" + key + "] bound to thread [" + Thread.currentThread().getName() + "]"); map.put(key, value); }
public class JmsResourceHolder extends ResourceHolderSupport { private ConnectionFactory connectionFactory;//连接工厂 private boolean frozen; private final List connections;//连接 private final List sessions;//会话 private final Map sessionsPerConnection;//连接会话映射关系 public final void addSession(Session session, Connection connection) { if(!this.sessions.contains(session)) { //添加会话 this.sessions.add(session); if(connection != null) { List sessions = (List)sessionsPerConnection.get(connection); if(sessions == null) { sessions = new LinkedList(); //添加连接会话映射关系 sessionsPerConnection.put(connection, sessions); } sessions.add(session); } } } }
我们先理一下,TransactionSynchronizationManager,JmsResourceHolder,JmsResourceSynchronization的关系;JmsResourceHolder管理连接,会话,连接工厂,及连接与会话的映射关系,JmsResourceSynchronization为连接工厂和JmsResourceHolder及事务的包装;TransactionSynchronizationManager管理线程的事务JmsResourceSynchronization,
连接工厂和JmsResourceHolder的映射管理。
再来理一下上面这一段说了什么,JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder
获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话
回到执行会话回调接口
来看执行会话回调接口doInJms方法
obj = action.doInJms(sessionToUse); public Object doInJms(Session session) throws JMSException { //会话发送消息 doSend(session, destination, messageCreator); return null; } protected void doSend(Session session, Destination destination, MessageCreator messageCreator) throws JMSException { MessageProducer producer; //创建生产者 producer = createProducer(session, destination); Message message = messageCreator.createMessage(session); //生产者发送消息 doSend(producer, message); }
生产者发送消息
doSend(producer, message); protected void doSend(MessageProducer producer, Message message) throws JMSException { if(deliveryDelay > 0L) { if(setDeliveryDelayMethod == null) throw new IllegalStateException("setDeliveryDelay requires JMS 2.0"); //如果有延时,则延时发送 ReflectionUtils.invokeMethod(setDeliveryDelayMethod, producer, new Object[] { Long.valueOf(deliveryDelay) }); } if(isExplicitQosEnabled()) producer.send(message, getDeliveryMode(), getPriority(), getTimeToLive()); else //无延时直接发送 producer.send(message); }
再来看发送转换消息
public void convertAndSend(Object message) throws JmsException { //获取默认目的地,即我们配置的JmsTemplate的defaultDestination Destination defaultDestination = getDefaultDestination(); if(defaultDestination != null) convertAndSend(defaultDestination, message); else convertAndSend(getRequiredDefaultDestinationName(), message); } public void convertAndSend(Destination destination, final Object message) throws JmsException { send(destination, new MessageCreator() { public Message createMessage(Session session) throws JMSException { //调用配置JmsTemplate的messageConverter的toMessage方法 return getRequiredMessageConverter().toMessage(message, session); } final Object val$message; final JmsTemplate this$0; { this.this$0 = JmsTemplate.this; message = obj; super(); } }); } public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException { execute(new SessionCallback() { public Object doInJms(Session session) throws JMSException { //委托给doSend(Session session, Destination destination, MessageCreator messageCreator) doSend(session, destination, messageCreator); return null; } final Destination val$destination; final MessageCreator val$messageCreator; final JmsTemplate this$0; { this.this$0 = JmsTemplate.this; destination = destination1; messageCreator = messagecreator; super(); } }, false); } protected void doSend(Session session, Destination destination, MessageCreator messageCreator) throws JMSException { MessageProducer producer; producer = createProducer(session, destination); //调用配置JmsTemplate的messageConverter的toMessage方法 Message message = messageCreator.createMessage(session); if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("Sending created message: ").append(message).toString()); doSend(producer, message); }
小节一下:
JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话,然后由会话创建生产者,有生产者发送消息;对于有消息转换的,则将消息转化器包装到MessageCreator,发送时由MessageCreator,调用消息转换器的消息转化方法,
转换消息,发送消息。
再来看一JmsTemplate的消费消息
public Message receive() throws JmsException { Destination defaultDestination = getDefaultDestination(); if(defaultDestination != null) return receive(defaultDestination); } public Message receive(Destination destination) throws JmsException { return receiveSelected(destination, null); } public Message receiveSelected(final Destination destination, final String messageSelector) throws JmsException { return (Message)execute(new SessionCallback() { public Message doInJms(Session session) throws JMSException { return doReceive(session, destination, messageSelector); } public volatile Object doInJms(Session session) throws JMSException { return doInJms(session); } final Destination val$destination; final String val$messageSelector; final JmsTemplate this$0; { this.this$0 = JmsTemplate.this; destination = destination1; messageSelector = s; super(); } }, true); }
这段发送送消息相似,直接忽略掉,直接看接受消息
doReceive(session, destination, messageSelector); protected Message doReceive(Session session, Destination destination, String messageSelector) throws JMSException { return doReceive(session, createConsumer(session, destination, messageSelector)); } protected Message doReceive(Session session, MessageConsumer consumer) throws JMSException { Message message1; long timeout = getReceiveTimeout(); JmsResourceHolder resourceHolder = (JmsResourceHolder)TransactionSynchronizationManager.getResource(getConnectionFactory()); if(resourceHolder != null && resourceHolder.hasTimeout()) timeout = Math.min(timeout, resourceHolder.getTimeToLiveInMillis()); //消费消息 Message message = doReceive(consumer, timeout); if(session.getTransacted()) { if(isSessionLocallyTransacted(session)) JmsUtils.commitIfNecessary(session); } else //如果需要客户端确认,则调用acknowledge if(isClientAcknowledge(session) && message != null) message.acknowledge(); message1 = message; JmsUtils.closeMessageConsumer(consumer); return message1; } private Message doReceive(MessageConsumer consumer, long timeout) throws JMSException { if(timeout == -1L) return consumer.receiveNoWait(); if(timeout > 0L) return consumer.receive(timeout); else //消费者消费消息 return consumer.receive(); } public Object receiveAndConvert() throws JmsException { return doConvertFromMessage(receive()); } protected Object doConvertFromMessage(Message message) { if(message == null) break MISSING_BLOCK_LABEL_22; //直接有消息转发器,转换消息 return getRequiredMessageConverter().fromMessage(message); JMSException ex; ex; throw convertJmsAccessException(ex); return null; }
消费者手动消费消息分方式同样是包装成会话回调接口,会话获取与生产者发送消息的会话阶段一样,然后从会话创建消费者,消费消息,而转化消息模式,只是将消费者获取的消息通过消息转化器转换一下;
总结:
JmsTemplate的构造,主要是初始化事务资源工厂,消息转换器,传输延时,优先级,消息生存时间再来看发送消息。JmsTemplate发送消息的时候,是将这一过程包装成会话回调接口,然后执行会话回调接口,会话回调结构中有个一参数就是Session,这个Session的获取就是我们上面在讲的,首先从事务同步管理器获取连接工厂对应的JmsResourceHolder,如果JmsResourceHolder存在,则从JmsResourceHolder
获取会话,如果没有则直接从ActiveMQConnectionFactory获取连接及会话,然后由会话创建生产者,有生产者发送消息;对于有消息转换的,则将消息转化器包装到MessageCreator,发送时由MessageCreator,调用消息转换器的消息转化方法,转换消息,发送消息。消费者手动消费消息分方式同样是包装成会话回调接口,会话获取与生产者发送消息的会话阶段一样,然后从会话创建消费者,消费消息,而转化消息模式,只是将消费者获取的消息通过消息转化器转换一下;
发表评论
-
Spring与ActiveMQ的集成详解二
2017-01-03 10:07 2110JMS(ActiveMQ) PTP和PUB/SUB模 ... -
ActiveMQ Broker发送消息给消费者过程详解
2017-01-02 15:30 6325JMS(ActiveMQ) PTP和PUB/SUB模 ... -
ActiveMQ Server启动过程详解
2017-01-02 12:43 6540JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ消费者详解
2017-01-01 14:38 8698JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ生产者详解
2017-01-01 12:29 6886JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ会话初始化详解
2016-12-31 20:26 4815JMS(ActiveMQ) PTP和PUB/SUB模 ... -
ActiveMQ连接工厂、连接详解
2016-12-29 16:09 12094JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
基于LevelDB的高可用ActiveMQ集群
2016-12-28 18:34 4316ActiveMQ实现负载均衡+高可用部署方案:http://w ... -
ActiveMQ 目录配置文件
2016-12-28 12:47 7823下载apache-activemq-5.12.1.tar.gz ... -
Spring与ActiveMQ的集成
2016-12-27 18:09 1752JMS与MQ详解:http://www.fx114.net/q ... -
ActiveMQ PTP模式实例二
2016-12-27 14:45 718这篇主要是测试PTP模式下的回复消息,具体测试代码如下: 队列 ... -
JMS(ActiveMQ) PTP和PUB/SUB模式实例
2016-12-27 09:02 3154深入浅出JMS(一)——JMS简介 :http://blog. ...
相关推荐
内容概要:本文详细探讨了利用NSGA2算法进行电力系统中储能系统的选址和定容优化,并结合熵权TOPSIS方法选择最优解。首先介绍了使用Matpower工具包进行潮流计算的基础步骤,随后深入讨论了储能系统引入后的复杂性和优化目标设定。文中展示了如何构建目标函数,包括储能的投资成本和系统电压偏差,并详细解释了NSGA2算法的具体实现,如种群初始化、交叉变异操作以及约束条件处理。最后,通过熵权法确定权重并应用TOPSIS方法对多个优化结果进行评估,选出综合性能最佳的储能配置方案。 适合人群:从事电力系统规划、优化算法研究的专业人士,尤其是对储能系统优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于需要解决电力系统中储能系统选址和定容问题的实际工程项目。主要目标是在满足系统稳定性要求的前提下,最小化储能系统的投资成本,提高系统的经济性和可靠性。 其他说明:文章提供了详细的代码片段和理论推导,帮助读者更好地理解和实施所提出的优化方法。此外,还提到了一些实际应用中的注意事项,如SOC约束处理、参数选择等,为后续的研究和应用提供了宝贵的实践经验。
基于python+pyqt5实现视频自动化下载、剪辑和上传系统源码+项目说明.zip 该项目是用脚本实现部分视频网站视频内容的自动化下载、剪辑以及上传,其中界面是用PyQT做的。 使用的浏览器驱动是undetected_chromedriver,可以跳过tiktok的机器人检查 使用的浏览器是91,版本:Google_Chrome_(64bit)_v91.0.4472.77 【功能】 自动从各种视频网站下载视频 支持视频剪辑和合集制作 支持自动上传视频到视频网站 技术栈 Python PyQT undetected_chromedriver
内容概要:本文详细介绍了西门子S7-1200双套三坐标6轴联动控制系统的开发与调试经验。主要内容涵盖双PLC通信机制、轴控制逻辑、安全联锁设计以及触摸屏程序绑定等方面。文中通过具体代码示例展示了如何利用SCL语言实现高效稳定的多轴联动控制,并分享了实际项目中的最佳实践和技术难点解决方案。此外,还讨论了程序结构优化、报警代码设计、数据块管理等关键环节,强调了模块化设计思想的应用及其带来的效率提升。 适合人群:从事工业自动化领域的工程师,尤其是熟悉西门子PLC编程的专业人士。 使用场景及目标:适用于需要进行复杂运动控制的自动化生产线,如汽车制造、电子装配等行业。主要目标是提高生产效率,确保设备运行的安全性和稳定性。 其他说明:文中提到的许多技术和方法不仅限于特定型号的PLC,对于其他品牌的控制器也有一定的借鉴意义。同时,提供的代码片段可以直接应用于类似项目中,帮助开发者快速搭建可靠的控制系统。
NFC Tools是一个应用程序,允许你在你的 NFC 标签和其他 RFID 兼容芯片上读取或写入或编程代码任务。NFC Tools PRO版本包括很多其他的附加功能,比如配置文件管理等。保存你的NFC标签或任务的配置文件,以便你以后重新使用它们。导出和导入很容易。NFC Tools PRO官方版允许你直接从现有的 NFC 标签导入你的记录或任务。 你可以很快编辑你的标签。此外还可以直接运行你的任务配置文件,不需要NFC 标签。
该资源为protobuf-6.30.1-py3-none-any.whl,欢迎下载使用哦!
内容概要:本文详细介绍了如何在FLAC3D中提取壳单元和衬砌单元的关键内力数据,如弯矩、轴力和剪力。针对壳单元,文中提供了具体的FISH命令和函数,展示了如何利用gp.extra属性提取弯矩,并强调了局部坐标系方向的重要性。对于衬砌单元,则介绍了专门的命令和注意事项,如使用liner组件提取轴力和剪力,以及如何处理弯矩数据。此外,还分享了一些实用的经验和技巧,如批量数据处理、单位换算、内力符号规则等。最后,提到了使用Python进行后处理的方法,将提取的数据转化为更直观的形式,便于进一步分析。 适合人群:从事岩土工程、隧道工程及相关领域的工程师和技术人员,尤其是对FLAC3D有一定基础的用户。 使用场景及目标:帮助用户掌握FLAC3D中壳单元和衬砌单元内力提取的具体方法,提高工作效率,确保数据分析的准确性。适用于需要进行结构内力分析、支护设计优化等项目的工程师。 其他说明:文章不仅提供了详细的命令和函数示例,还分享了许多实战经验和常见错误的规避方法,有助于初学者少走弯路。同时,强调了内力符号规则和单位换算的重要性,避免因疏忽导致的重大失误。
内容概要:本文详细介绍了ST公司发布的HL07:ST PMSM FOC电机控制资料包2.0的内容及其应用。资料包涵盖了ST芯片电机控制的全源代码、详细文档、多个工程源码、stm32库培训资料及例程源码。文中通过具体的代码示例,如GPIO初始化、PWM配置、ADC采样、Clarke变换、PID调节器、SVPWM生成等,深入剖析了电机控制的关键技术和优化技巧。此外,还揭示了一些隐藏的技术细节和调试技巧,如硬件同步、动态调整PID参数、电机参数自识别等。 适合人群:电机控制工程师、嵌入式开发人员、尤其是对STM32和FOC算法感兴趣的开发者。 使用场景及目标:帮助读者深入了解ST芯片电机控制的具体实现,掌握从硬件配置到算法优化的全过程,提高实际项目的开发效率和质量。适用于需要进行电机控制系统设计、调试和优化的工程项目。 其他说明:资料包中的代码和文档非常实用,提供了丰富的实战经验和优化建议,尤其适合初学者和有一定基础的研发人员。同时,文中提到的一些特殊技巧和注意事项有助于避免常见的开发陷阱,提升系统的稳定性和性能。
内容概要:文章探讨了2025年AI技术发展趋势及潜在的GPT级技术突破。首先回顾了GPT系列模型的发展历程及其对自然语言处理领域的深远影响。接着,通过介绍Geoffrey Hinton、李飞飞和张晨等AI领袖的观点,阐述了AI技术在实际应用场景中的挑战与机遇。文中详细描述了AI大模型的演进,包括多模态技术的发展、轻量化趋势以及可控性和可解释性的提升。此外,还介绍了AI计算力的革命性升级,如量子计算、云计算+AI和边缘AI的发展。最后,文章分析了AI在医疗、金融、教育、自动驾驶等行业的落地应用,并指出了面临的挑战与机遇,展望了未来的技术和社会影响。 适合人群:对AI技术感兴趣的从业者、研究人员、企业家及政策制定者。 使用场景及目标:①了解AI技术的最新进展和未来趋势;②探索AI技术在各行业的应用前景;③评估AI技术带来的挑战与机遇,为相关决策提供参考。 阅读建议:本文内容涵盖广泛,既有技术细节又有宏观展望,建议读者结合自身背景选择感兴趣的部分深入阅读,重点关注与自身行业或研究方向相关的章节。
内容概要:本文详细探讨了基于樽海鞘算法(SSA)优化的极限学习机(ELM)在回归预测任务中的应用,并与传统的BP神经网络、广义回归神经网络(GRNN)以及未优化的ELM进行了性能对比。首先介绍了ELM的基本原理,即通过随机生成输入层与隐藏层之间的连接权重及阈值,仅需计算输出权重即可快速完成训练。接着阐述了SSA的工作机制,利用樽海鞘群体觅食行为优化ELM的输入权重和隐藏层阈值,从而提高模型性能。随后分别给出了BP、GRNN、ELM和SSA-ELM的具体实现代码,并通过波士顿房价数据集和其他工业数据集验证了各模型的表现。结果显示,SSA-ELM在预测精度方面显著优于其他三种方法,尽管其训练时间较长,但在实际应用中仍具有明显优势。 适合人群:对机器学习尤其是回归预测感兴趣的科研人员和技术开发者,特别是那些希望深入了解ELM及其优化方法的人。 使用场景及目标:适用于需要高效、高精度回归预测的应用场景,如金融建模、工业数据分析等。主要目标是提供一种更为有效的回归预测解决方案,尤其是在处理大规模数据集时能够保持较高的预测精度。 其他说明:文中提供了详细的代码示例和性能对比图表,帮助读者更好地理解和复现实验结果。同时提醒使用者注意SSA参数的选择对模型性能的影响,建议进行参数敏感性分析以获得最佳效果。
内容概要:本文详细介绍了汇川PLC与基恩士PLC通过Ethernet/IP (EIP) 协议实现联机的方法及其应用场景。首先,文章解释了硬件配置,包括基恩士KV-7300 CPU搭配KV-EP21v以太网通信模块以及汇川AM-400系列PLC的网口连接。接下来,分别阐述了基恩士和汇川PLC的程序框架,涵盖初始化EIP通讯模块、设置IP地址、建立连接、数据映射及心跳检测机制等关键技术点。此外,文中提供了具体的代码示例和调试建议,如使用Wireshark抓包工具排查问题,并强调了数据同步、字节序转换、超时处理等方面需要注意的地方。最后,分享了一些实践经验,例如确保正确的IP地址分配、合理的缓冲区大小规划、良好的接地措施等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程有一定基础并希望深入了解不同品牌PLC间通讯机制的专业人士。 使用场景及目标:适用于需要将不同品牌PLC集成到同一个控制系统中的工业项目,旨在提高系统的灵活性和互操作性。通过掌握本文介绍的技术要点,可以有效减少因PLC品牌差异带来的兼容性和稳定性问题。 其他说明:文中不仅提供了理论指导,还结合实际案例进行了深入浅出的讲解,帮助读者更好地理解和应用相关技术。同时,针对可能出现的问题给出了预防和解决方案,使读者能够在实践中少走弯路。
内容概要:本文详细记录了作者将VESC项目的非线性磁链观测器移植到STM32F4开发板的过程。首先介绍了FOC技术和VESC源码的重要性和特点,然后重点阐述了非线性磁链观测器的实现方法及其核心代码。接着讨论了移植过程中遇到的技术难题,如实时性、稳定性、中断处理、电流采样等问题,并分享了解决这些问题的具体措施。最后展示了测试结果,证明了移植的成功以及观测器的良好性能。 适合人群:具有一定嵌入式开发经验的研发人员,特别是从事电机控制领域的工程师和技术爱好者。 使用场景及目标:适用于希望深入理解VESC源码和非线性磁链观测器的工作机制,掌握STM32F4平台上FOC算法实现的人群。目标是在实际项目中应用这些技术,提高电机控制系统的性能。 其他说明:文中提供了大量实用的代码片段和调试技巧,帮助读者更好地理解和解决问题。此外,作者还分享了一些个人经验和心得,增加了文章的趣味性和实用性。
移远EC20 Windows驱动 操作系统 - 桌面系统 - 移远EC20 Windows驱动
检证资料jianzhen.ppt
内容概要:本文档《ATK-DLRK3568嵌入式Qt开发实战V1.2》是正点原子出品的一份面向初学者的嵌入式Qt开发指南,主要内容涵盖嵌入式Linux环境下Qt的安装配置、C++基础、Qt基础、多线程编程、网络编程、多媒体开发、数据库操作以及项目实战案例。文档从最简单的“Hello World”程序开始,逐步引导读者熟悉Qt开发环境的搭建、常用控件的使用、信号与槽机制、UI设计、数据处理等关键技术点。此外,文档还提供了详细的项目实战案例,如车牌识别系统的开发,帮助读者将理论知识应用于实际项目中。 适合人群:具备一定Linux和C++基础,希望快速入门嵌入式Qt开发的初学者或有一定开发经验的研发人员。 使用场景及目标: 1. **环境搭建**:学习如何在Ubuntu环境下搭建Qt开发环境,包括安装必要的工具和库。 2. **基础知识**:掌握C++面向对象编程、Qt基础控件的使用、信号与槽机制等核心概念。 3. **高级功能**:理解多线程编程、网络通信、多媒体处理、数据库操作等高级功能的实现方法。 4. **项目实战**:通过具体的项目案例(如车牌识别系统),巩固
1、文件说明: Centos8操作系统tcl-tclxml-devel-3.2-26.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf tcl-tclxml-devel-3.2-26.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
C盘清理bat脚本自动清理C盘垃圾文件
桶排
内容概要:本文详细介绍了利用混沌系统进行图像加密的方法,重点探讨了Logistic映射生成混沌序列用于图像加密的具体实现。首先,通过生成混沌序列并对其进行预热处理,确保序列的随机性和稳定性。然后,采用循环移位扰乱方法对图像像素进行重新排列,使图像像素位置发生改变。接着,通过水平和垂直扩散步骤进一步打乱像素之间的关联性,增强了加密效果。文中还展示了如何通过直方图、信息熵和相关系数等指标评估加密效果,验证了该方法的有效性。 适合人群:对图像加密技术和混沌系统感兴趣的科研人员、信息安全领域的开发者和技术爱好者。 使用场景及目标:适用于研究和开发高效的图像加密算法,特别是在需要高安全性的应用场景中,如军事通信、隐私保护等领域。目标是提供一种基于混沌系统的高效、安全的图像加密解决方案。 其他说明:文中提供了详细的Python代码实现,帮助读者更好地理解和实践该加密方法。同时,强调了在实际应用中需要注意的一些关键点,如参数选择和优化,以确保最佳的加密效果。
基于EEMD奇异值熵的滚动轴承故障诊断方法研究
内容概要:本文档介绍了分块查找的基本思想及其具体实现方法。分块查找的核心在于将一个数据集划分为若干个块,块内部元素可以无序排列,但块间元素必须保持有序(对于非递减序列,后一块的所有元素均大于前一块)。文档通过C#语言实现了分块查找算法,定义了IndexBlock结构体用于存储每个块的最大值、起始位置和结束位置,并展示了如何初始化分块以及执行具体的查找操作。最后通过一个简单的例子演示了分块查找的应用,当查找成功时返回元素在数组中的索引,否则返回-1表示查找失败。; 适合人群:计算机科学专业学生或有一定编程基础的技术人员。; 使用场景及目标:①理解分块查找算法的工作原理;②掌握利用C#实现分块查找的具体步骤;③学习如何根据实际需求选择合适的查找算法以提高效率。; 其他说明:此文档不仅提供了理论性的概念解释,还结合了实际代码示例帮助读者更好地理解分块查找算法,建议读者在阅读过程中尝试运行代码并理解每一部分的功能。