package com.producer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;
public class ActiveProducer implements ExceptionListener {
//设置连接的最大连接数
public final static int DEFAULT_MAX_CONNECTIONS = 10;
private int maxConnections = DEFAULT_MAX_CONNECTIONS;
//设置每个连接中使用的最大活动会话数
private int maximumActiveSessionPerConnection = DEFAULT_MAXIMUM_ACTIVE_SESSION_PER_CONNECTION;
public final static int DEFAULT_MAXIMUM_ACTIVE_SESSION_PER_CONNECTION = 500;
//线程池数量
private int threadPoolSize = DEFAULT_THREAD_POOL_SIZE;
public final static int DEFAULT_THREAD_POOL_SIZE = 50;
//强制使用同步返回数据的格式
private boolean useAsyncSendForJMS = DEFAULT_USE_ASYNC_SEND_FOR_JMS;
public final static boolean DEFAULT_USE_ASYNC_SEND_FOR_JMS = true;
//是否持久化消息
private boolean isPersistent = DEFAULT_IS_PERSISTENT;
public final static boolean DEFAULT_IS_PERSISTENT = true;
//连接地址
private String ip;
private String port;
private ExecutorService threadPool;
private PooledConnectionFactory connectionFactory;
// 已发送数据的缓存,用于去重
private final SendUniqueCache cache;
public ActiveProducer(String ip, String port) {
this(ip, port, DEFAULT_MAX_CONNECTIONS, DEFAULT_MAXIMUM_ACTIVE_SESSION_PER_CONNECTION, DEFAULT_THREAD_POOL_SIZE, DEFAULT_USE_ASYNC_SEND_FOR_JMS, DEFAULT_IS_PERSISTENT);
}
public ActiveProducer(String ip, String port, int maximumActiveSessionPerConnection) {
this(ip, port, DEFAULT_MAX_CONNECTIONS, maximumActiveSessionPerConnection, DEFAULT_THREAD_POOL_SIZE, DEFAULT_USE_ASYNC_SEND_FOR_JMS, DEFAULT_IS_PERSISTENT);
}
public ActiveProducer(String ip, String port, int maxConnections, int maximumActiveSessionPerConnection, int threadPoolSize, boolean useAsyncSendForJMS, boolean isPersistent) {
this.ip = ip;
this.port = port;
this.isPersistent = isPersistent;
this.cache = new SendUniqueCache();
this.maxConnections = maxConnections;
this.threadPoolSize = threadPoolSize;
this.useAsyncSendForJMS = useAsyncSendForJMS;
this.maximumActiveSessionPerConnection = maximumActiveSessionPerConnection;
init();
}
private void init() {
String url = this.buildMQUrl();
//设置JAVA线程池
this.threadPool = Executors.newFixedThreadPool(this.threadPoolSize);
//ActiveMQ的连接工厂
ActiveMQConnectionFactory actualConnectionFactory = new ActiveMQConnectionFactory(url);
actualConnectionFactory.setUseAsyncSend(this.useAsyncSendForJMS);
//Active中的连接池工厂
this.connectionFactory = new PooledConnectionFactory(actualConnectionFactory);
this.connectionFactory.setCreateConnectionOnStartup(true);
this.connectionFactory.setMaxConnections(this.maxConnections);
this.connectionFactory.setMaximumActiveSessionPerConnection(this.maximumActiveSessionPerConnection);
}
private String buildMQUrl() {
String[] ips = this.ip.split(",");
String[] ports = this.port.split(",");
StringBuilder tcpLink = new StringBuilder();
for (int i = 0; i < ips.length; i++) {
tcpLink.append("tcp://").append(ips[i]).append(":").append(ports[i]).append(",");
}
String mqLink = tcpLink.toString();
if (tcpLink.length() > 0) {
if (',' == tcpLink.charAt(tcpLink.length() - 1)) {
mqLink = tcpLink.substring(0, tcpLink.length() - 1);
}
}
return String.format("failover:(%s)?initialReconnectDelay=100&timeout=5000&startupMaxReconnectAttempts=3", mqLink);
}
/**
* 执行发送消息的具体方法
*
* @param queueName
* @param message
*/
public void send(final String queueName, final String message) {
//直接使用线程池来执行具体的调用
this.threadPool.execute(new Runnable() {
@Override
public void run() {
try {
if (!cache.check(message)) {
boolean result = sendMsgToMQ(queueName, message);
LogUtil.mustMark(LogUtil.TAG.TAG_MQ, this.getClass(), "send", "Send message to MQ ->", " MessageQueue:[", queueName, "] SendResult:[", result, "] MessageData:[", message, "]");
if (!result) {
MailQueueCache.instance().put("ActiveMQSend ", CstCode.BR_STR, "[Queue:", queueName, "]message send fail! ", CstCode.BR_STR, message);
}
} else {
LogUtil.mustMark(LogUtil.TAG.TAG_MQ, this.getClass(), "send", "Send message to MQ ->", " MessageQueue:[", queueName, "] SendResult:[The data has been sent] MessageData:[", message, "]");
}
} catch (Exception e) {
LogUtil.errorMark(LogUtil.TAG.TAG_MQ, "ActiveMQ send Error:", e.getMessage());
}
}
});
}
/**
* 真正的执行消息发送
*
* @param queue
* @param map
* @throws Exception
*/
private boolean sendMsgToMQ(String queue, String message) throws Exception {
boolean result = false;
Connection connection = null;
Session session = null;
try {
//从连接池工厂中获取一个连接
connection = this.connectionFactory.createConnection();
/*createSession(boolean transacted,int acknowledgeMode)
transacted - indicates whether the session is transacted acknowledgeMode - indicates whether the consumer or the client
will acknowledge any messages it receives; ignored if the session is transacted.
Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.
*/
//false 参数表示 为非事务型消息,后面的参数表示消息的确认类型
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//Destination is superinterface of Queue
//PTP消息方式
Destination destination = session.createQueue(queue);
//Creates a MessageProducer to send messages to the specified destination
MessageProducer producer = session.createProducer(destination);
//set delevery mode
producer.setDeliveryMode(this.isPersistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
//map convert to javax message
TextMessage textMessage = session.createTextMessage(message);
producer.send(textMessage);
result = true;
} finally {
closeSession(session);
closeConnection(connection);
}
return result;
}
private void closeSession(Session session) {
try {
if (session != null) {
session.close();
}
} catch (Exception e) {
LogUtil.errorMark(LogUtil.TAG.TAG_MQ, "ActiveMQ closeSession Error:", e.getMessage());
}
}
private void closeConnection(Connection connection) {
try {
if (connection != null) {
connection.close();
}
} catch (Exception e) {
LogUtil.errorMark(LogUtil.TAG.TAG_MQ, "ActiveMQ closeConnection Error:", e.getMessage());
}
}
@Override
public void onException(JMSException exception) {
LogUtil.errorMark(LogUtil.TAG.TAG_MQ, "ActiveMQ Error:", exception.getMessage());
}
}
大概需要引入的POM内容:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>2.12.1</version>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aop</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-expression</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-jms</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-tx</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>poi</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>