参考地址:https://blog.csdn.net/qq447995687/article/details/80233621
利用commons-pool2自定义对象池
commons-pool2是Apache下一个开源的公共资源池。我们可以根据它来快速的建立一个自己的对象池。
commons-pool2包下载地址:https://pan.baidu.com/s/1lVUX_FZAbKjW87jTGJ_Rmw
密码:a8d0
1.创建连接池工厂,实现PooledObjectFactory接口
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.tds.smgw.util.Environment;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
1. 自定义连接池工厂
**/
public class RabbitMqChannelPoolFactory implements PooledObjectFactory<Channel> {
private Connection connection;
public RabbitMqChannelPoolFactory(){
try {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置host
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("test");
factory.setPassword("test");
factory.setVirtualHost("/");
factory.setConnectionTimeout(15000);
connection = factory.newConnection();
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
}
@Override
public PooledObject<Channel> makeObject() throws Exception {
// 池对象创建实例化资源
return new DefaultPooledObject<>(connection.createChannel());
}
@Override
public void destroyObject(PooledObject<Channel> p) throws Exception {
// 池对象销毁资源
if (p != null && p.getObject() != null && p.getObject().isOpen()) {
p.getObject().close();
}
}
@Override
public boolean validateObject(PooledObject<Channel> p) {
// 验证资源是否可用
return p.getObject() != null && p.getObject().isOpen();
}
@Override
public void activateObject(PooledObject<Channel> p) {
}
@Override
public void passivateObject(PooledObject<Channel> p) {
}
}
2.创建连接池,实现GenericObjectPool接口
import com.rabbitmq.client.Channel;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.AbandonedConfig;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
/**
1. 自定义连接池
**/
public class RabbitMqChannelPool extends GenericObjectPool<Channel> {
public RabbitMqChannelPool(PooledObjectFactory<Channel> factory) {
super(factory);
}
public RabbitMqChannelPool(PooledObjectFactory<Channel> factory, GenericObjectPoolConfig config) {
super(factory, config);
}
public RabbitMqChannelPool(PooledObjectFactory<Channel> factory, GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) {
super(factory, config, abandonedConfig);
}
}
3.获取和关闭channel连接
import com.rabbitmq.client.Channel;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
/**
* channel管理
**/
public class RabbitMqChannelService {
private RabbitMqChannelPool pool;
public static RabbitMqChannelService getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 获取channel对象
* pool.borrowObject()是线程安全的
*
* @return 结果
* @throws Exception 异常
*/
public Channel getChannel() throws Exception {
return pool.borrowObject();
}
/**
* 归还channel对象
*
* @param channel 结果
*/
public void returnChannel(Channel channel) {
pool.returnObject(channel);
}
private static class SingletonHolder {
private final static RabbitMqChannelService INSTANCE = new RabbitMqChannelService();
}
private RabbitMqChannelService() {
initPool();
}
/**
* 初始化pool
*/
private void initPool() {
RabbitMqChannelPoolFactory factory = new RabbitMqChannelPoolFactory();
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
// 设置最大连接数
config.setMaxTotal(300);
// 最大空闲连接数
config.setMaxIdle(20);
// 最小空闲连接数
config.setMinIdle(10);
// 空闲连接检测周期
config.setTimeBetweenEvictionRunsMillis(6000);
// 达到此空闲时间后,连接将被移除
config.setSoftMinEvictableIdleTimeMillis(20000);
// 连接资源耗尽后最大等待时间
config.setMaxWaitMillis(10000);
pool = new RabbitMqChannelPool(factory, config);
}
}
4.生产者
import com.rabbitmq.client.Channel;
import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
/**
* rabbit消息发送
*/
public class RabbitMqProducer {
private Logger logger = LoggerFactory.getLogger(RabbitMqProducer.class);
private String queueName;
public RabbitMqProducer(String queueName) {
this.queueName = queueName;
}
/**
* 发送信息
*
* @param obj 发送的内容
*/
public void sendMessage(Serializable obj) {
RabbitMqChannelService rabbitMqChannelService = RabbitMqChannelService.getInstance();
Channel channel = null;
try {
channel = rabbitMqChannelService.getChannel();
// 为这个通道申明一个队列,如果这个队列不存在,他将在服务器上创建
channel.queueDeclare(queueName, true, false, false, null);
channel.basicPublish("", queueName, null, SerializationUtils.serialize(obj));
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (null != channel) {
rabbitMqChannelService.returnChannel(channel);
}
}
}
}
5.消费者,实现Consumer接口
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.ShutdownSignalException;
import com.tds.smgw.service.impl.RabitMqService;
import com.tds.smgw.util.Environment;
import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* 消费者
* 这里channel和Consumer是一对一
* 使用消息自动确认机制
*/
public class RabbitMqConsumer implements Consumer {
private static Logger logger = LoggerFactory.getLogger(RabbitMqConsumer.class);
private static String queueName;
private static RabitMqService rabitMqService;
private Channel channel;
private RabbitMqConsumer() {
init();
}
private static class SingletonHolder {
private static final RabbitMqConsumer INSTANCE = new RabbitMqConsumer();
}
public static RabbitMqConsumer getInstance(String queueName) {
if (null == RabbitMqConsumer.queueName) {
RabbitMqConsumer.queueName = queueName;
}
return SingletonHolder.INSTANCE;
}
/**
* 设置接收消息queue
*/
private void init() {
try {
channel = RabbitMqChannelService.getInstance().getChannel();
logger.info("启动RabbitMq监听器:" + channel + "监听QUEUE【" + queueName + "】");
// 为这个通道申明一个队列,如果这个队列不存在,他将在服务器上创建,防止不存在时报错
channel.queueDeclare(queueName, true, false, false, null);
// 开启接收信息,自动确认
channel.basicConsume(queueName, true, this);
// 开启接收信息,手动确认
// channel.basicConsume(queueName, false, this);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (null != channel) {
logger.info("channel ---》" + channel);
// 不能归还,归还后有可能被关闭导致消费者阻塞
// rabbitMqChannelService.returnChannel(channel);
}
}
}
/**
* 当用户注册时调用
*/
@Override
public void handleCancelOk(String consumerTag) {
System.out.println("Consumer " + consumerTag + " registered");
}
/**
* 当有可用新消息时调用
*/
@Override
@SuppressWarnings("unchecked")
public void handleDelivery(String consumerTag, Envelope env, BasicProperties props, byte[] body) {
logger.info("------------------------------[{}]MQ监听器执行开始[{}]---------------------------"
, env.getRoutingKey(), System.currentTimeMillis());
Map<String, String> map = (HashMap<String, String>) SerializationUtils.deserialize(body);
logger.info("接收消息:" + SerializationUtils.deserialize(body));
// channel.basicAck(env.getDeliveryTag(), false);
logger.info("------------------------------[{}]MQ监听器执行结束[{}]---------------------------"
, env.getRoutingKey(), System.currentTimeMillis());
}
@Override
public void handleCancel(String consumerTag) {
}
@Override
public void handleConsumeOk(String consumerTag) {
}
@Override
public void handleRecoverOk(String consumerTag) {
}
@Override
public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {
}
}
6.测试
public static void main(String[] args) {
String queueName = "testQueue";
// 需要提前启动消费者监听queue,否则监听不到生产者生产的消息
RabbitMqConsumer.getInstance(queueName);
// 启动rabbitMq生产者
RabbitMqProducer producer = new RabbitMqProducer(queueName);
Map<String, String> map = new HashMap<>(16);
map.put("date", "date");
map.put("time", "time");
map.put("userId", "userId");
producer.sendMessage((Serializable) map);
}