[http://blog.csdn.net/supersue/archive/2007/11/24/1901203.aspx]
這種實現的原理是利用Jms Connection的ExceptionListen機制,只在發生錯誤的時候纔去Check和重連,系統開銷會小一些。
以下是代碼
DCJmsMessageListenerContainer.java
import javax.jms.Connection;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import org.springframework.jms.JmsException;
import org.springframework.jms.listener.serversession.ServerSessionMessageListenerContainer;
public class DCJmsMessageListenerContainer extends ServerSessionMessageListenerContainer
implements ExceptionListener {
/** interval */
private long interval = 300000;
private CheckConnectionThread checker;
/** ClassLoader */
private ClassLoader classLoader;
/** ExceptionListener */
private ExceptionListener exListener;
public void setInterval(long interval) {
this.interval = 60000 * interval;
}
public void setExListener(ExceptionListener exListener) {
this.exListener = exListener;
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
this.classLoader = Thread.currentThread().getContextClassLoader();
}
@Override
protected Connection createConnection() throws JMSException {
Connection conn = super.createConnection();
if (this.exListener == null) {
conn.setExceptionListener(this);
} else {
conn.setExceptionListener(this.exListener);
}
return conn;
}
@Override
public void destroy() {
if (this.checker != null) {
this.checker.shutdown();
this.checker = null;
}
super.destroy();
}
public void refreshConnection() {
try {
this.logger.info(this.getBeanName() + " RefreshConnection Begin.");
if (this.checker == null || !this.checker.isCheckRun()) {
super.refreshSharedConnection();
super.initialize();
}
this.logger.info(this.getBeanName() + " RefreshConnection Succeed.");
} catch (JMSException e) {
this.logger.error(this.getBeanName() + " [Digitalcinema JMS Failover]", e);
}
}
public void onException(JMSException e) {
this.logger.error(this.getBeanName() + " Connection Error: " + e.getMessage());
if (this.checker != null) {
this.checker.shutdown();
this.checker = null;
}
this.checker = new CheckConnectionThread();
this.checker.setDaemon(true);
this.checker.setContextClassLoader(this.classLoader);
this.checker.start();
}
public void handleException(JMSException e) {
this.logger.error(this.getBeanName() + " Connection Error: " + e.getMessage());
if (this.checker == null || !this.checker.isCheckRun()) {
this.checker = new CheckConnectionThread();
this.checker.setDaemon(true);
this.checker.setContextClassLoader(this.classLoader);
this.checker.start();
}
}
private class CheckConnectionThread extends Thread {
/** checkRunFlg */
private volatile boolean checkRunFlg = true;
public void shutdown() {
this.checkRunFlg = false;
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " CheckConnectionThread Stoped!");
this.interrupt();
}
public boolean isCheckRun() {
return this.checkRunFlg;
}
@Override
public void run() {
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " CheckConnectionThread Started!");
this.checkRunFlg = true;
while (this.checkRunFlg) {
try {
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover] Refresh Shared Connection");
DCJmsMessageListenerContainer.this.refreshSharedConnection();
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover] Container Initialize");
DCJmsMessageListenerContainer.this.initialize();
this.checkRunFlg = false;
break;
} catch (JmsException e) {
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover]", e);
try {
Thread.sleep(interval);
} catch (InterruptedException ie) {
logger.error(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover]", ie);
}
} catch (JMSException e) {
logger.info(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover]", e);
try {
Thread.sleep(interval);
} catch (InterruptedException ie) {
logger.error(DCJmsMessageListenerContainer.this.getBeanName()
+ " [Digitalcinema JMS Failover]", ie);
}
}
}
}
}
}
在Spring的配置文件中可以這樣配置
class="jms.receiver.DCJmsMessageListenerContainer">
<property name="connectionFactory" ref="myConnectionFactory" />
<property name="destinationName" value="B" />
<property name="messageListener" ref="messageListener" />
<property name="sessionTransacted" value="true" />
</bean>