ActiveMQ学习:连接池的简单实现和模板模式的应用

一、安装activemq

下载地址:https://archive.apache.org/dist/activemq/5.13.0/apache-activemq-5.13.0-bin.zip

下载完后如果是64位操作系统打开~\apache-activemq-5.13.0\bin\win64目录下的activemq.bat即可,如果是32位的打开~\apache-activemq-5.13.0\bin\win32目录下的activemq.bat就可以了。

打开activemq的管理地址http://localhost:8161/admin/,用户名和密码都是admin,出现以下界面说明activemq已经正常运行。

二、创建maven项目,pom.xml中添加activemq的jar包依赖:

    <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.13.0</version>
        </dependency>

三、activemq连接池的实现

  1、创建连接池接口ConnectionPool

package com.guods.mymq.activemq;

import javax.jms.Connection;
import javax.jms.JMSException;

/**
 * jms连接池接口
 * @author guods
 *
 */
public interface ConnectionPool {

    Connection getConnection() throws JMSException;
    void releaseConnection(Connection connection);
}

  2、连接池实现ConnectionPoolImpl

    创建初始连接,并把连接存到链表,使用的时候从链表中获取连接。

package com.guods.mymq.activemq;

import java.util.LinkedList;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * jms连接池实现
 * @author guods
 *
 */
public class ConnectionPoolImpl implements ConnectionPool {

    //连接用户名
    private static final String USERNAME = "admin";
    //连接密码
    private static final String PASSWORD = "admin";
    //连接地址
    private static final String BROKEURL = "tcp://localhost:61616";
    //初始连接数
    private static final int INIT_SIZE = 2;
    //最大连接数
    private static final int MAX_SIZE = 5;
    //当前存在的连接总数,包括:正在使用的连接 + connections列表中的连接
    private int poolSize = 0;
    
    //创建连接工厂
    private ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
    //存放空闲connection的链表
    private LinkedList<Connection> connections = new LinkedList<Connection>();

    public ConnectionPoolImpl() {
        initConnections();
    }
    /**
     * 初始化连接,生成初始连接数
     */
    private void initConnections() {
        for (int i = 0; i < INIT_SIZE; i++) {
            try {
                connections.add(createConnection());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 添加连接,每增加一个connection,poolSize加1
     * @throws JMSException
     */
    private synchronized Connection createConnection() throws JMSException {
        Connection newConnection = connectionFactory.createConnection();
        newConnection.start();
        poolSize++;
        return newConnection;
    }
    /**
     * 删除连接,每删除一个connection,poolSize减1
     * @param connection
     * @throws JMSException 
     */
    private synchronized void delConnection() throws JMSException {
        Connection connection = connections.removeFirst();
        if (connection != null) {
            connection.close();
            poolSize--;
        }
    }
    /**
     * 从连接池获取connection
     * @throws JMSException 
     */
    public synchronized Connection getConnection() throws JMSException {
        int i = 0;
        while (true) {
            //3次获取连接失败,抛超时异常
            if (i == 3) {
                throw new JMSException("Get connection timeout !");
            }
            //连接池有连接,直接取一个返回
            if (connections.size() > 0) {
                return connections.removeFirst();
            }
            //连接池空,如果连接数没到最大,创建一个连接返回
            if (poolSize < MAX_SIZE) {
                try {
                    return createConnection();
                } catch (JMSException e) {
                }
            }
            //连接池空,并且连接达到最大数,等1秒再试尝试获取连接
            try {
                Thread.sleep(1000);
                i++;
            } catch (InterruptedException e) {
            }
        }
    }
    /**
     * 释放连接,连接用完后放回队列
     */
    public synchronized void releaseConnection(Connection connection) {
        connections.add(connection);
    }

}

 四、创建jms模板

  beginSession方法从连接池获取连接,创建session。

  endSession方法提交session,并把连接交还给连接池。

  execute方法整合了beginSession和endSession两个模板方法,中间执行抽象方法action中的内容。

  action在子类中实现业务操作,如创建队列、生产消息、消费消息等。

package com.guods.mymq.activemq;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Session;

/**
 * 模板模式,创建JMS模板
 * @author guods
 *
 */
public abstract class JmsTemplate {

    private ConnectionPool connectionPool;
    private Connection connection;
    private Session session;
    
    public JmsTemplate(ConnectionPool connectionPool) {
        super();
        this.connectionPool = connectionPool;
    }

    public abstract Object action(Session session) throws JMSException;

    public Object execute() throws JMSException{
        //获取连接,开启session
        beginSession();
        //处理事务
        Object object = action(session);
        //关闭session,释放连接
        endSession();
        return object;
    }
    
    /**
     * 从连接池获取connection,创建session
     * @throws JMSException
     */
    private void beginSession() throws JMSException{
        connection = connectionPool.getConnection();
        session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
    }
    
    /**
     * 提交事务,关闭session,释放connection
     * @throws JMSException
     */
    private void endSession() throws JMSException{
        session.commit();
        session.close();
        connectionPool.releaseConnection(connection);
    }
}

五、实现activemq的各种业务操作

package com.guods.mymq.activemq;

import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

/**
 * activemq的各种业务操作
 * @author guods
 *
 */
public class JmsAction {

    private ConnectionPool connectionPool;
    
    public JmsAction(ConnectionPool connectionPool) {
        super();
        this.connectionPool = connectionPool;
    }

    /**
     * 创建消息队列
     * @param queueName
     * @return
     * @throws JMSException
     */
    public Queue createQueue(final String queueName) throws JMSException {
        
        return (Queue) new JmsTemplate(connectionPool) {
            
            @Override
            public Object action(Session session) {
                try {
                    return session.createQueue(queueName);
                } catch (JMSException e) {
                    return null;
                }
            }
        }.execute();
    };

    /**
     * 发送p2p消息
     * @param queue
     * @param message
     * @throws JMSException
     */
    public void produceP2pMessage(final Queue queue, final String message) throws JMSException{
        new JmsTemplate(connectionPool) {
            
            @Override
            public Object action(Session session) throws JMSException {
                MessageProducer messageProducer = session.createProducer(queue);
                TextMessage textMessage = session.createTextMessage(message);
                messageProducer.send(queue, textMessage);
                return null;
            }
        }.execute();
    }
    
    /**
     * 消费一条p2p消息
     * @param queue
     * @return
     * @throws JMSException
     */
    public String consumP2pMessage(final Queue queue) throws JMSException{
        return (String) new JmsTemplate(connectionPool) {
            
            @Override
            public Object action(Session session) throws JMSException {
                MessageConsumer createConsumer = session.createConsumer(queue);
                TextMessage textMessage = (TextMessage) createConsumer.receive(10000);
                if (textMessage == null) {
                    return null;
                }
                return textMessage.getText();
            }
        }.execute();
    }
    
    
}

六、测试

  1、生产者生产消息

package com.guods.mymq.activemq;

import javax.jms.JMSException;
import javax.jms.Queue;

public class JmsProducer {

    private static ConnectionPool connectionPool = new ConnectionPoolImpl();
    private static JmsAction jmsAction = new JmsAction(connectionPool);
    
    public static void main(String[] args) throws JMSException {
        //创建队列
        Queue queue = jmsAction.createQueue("MyQueue");
        //生产消息
        for (int i = 0; i < 5; i++) {
            String message = "第" + i + "条消息!";
            jmsAction.produceP2pMessage(queue, message);
            System.out.println("生产消息:" + message);
        }
    }
}

  2、消费者消费消息

package com.guods.mymq.activemq;

import javax.jms.JMSException;
import javax.jms.Queue;

public class JmsConsumer {

    private static ConnectionPool connectionPool = new ConnectionPoolImpl();
    private static JmsAction jmsAction = new JmsAction(connectionPool);
    
    public static void main(String[] args) throws JMSException {
        //创建队列
        Queue queue = jmsAction.createQueue("MyQueue");
        //消费消息
        while (true) {
            String message = jmsAction.consumP2pMessage(queue);
            if (message != null) {
                System.out.println("消费消息:" + message);
            }
        }
    }
}

 

git源码:https://github.com/dongsheng824/mymq.git

转载于:https://www.cnblogs.com/guods/p/6757480.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值