MySQL池化框架学习接池自定义

引言

最近在学习了通用池化框架commons-pool2实践之后,再HTTP性能测试中进行了实践,结果出乎意料,对于性能提升没啥卵用。经过我自己的本地测试,性能也是足够好的。

后来我仔细想了想,原来是我用错地方了。本来想自己写一个Redis的连接池的没想到,jedis的连接池本身就是commons-pool2开发的,让我有点意外,看来想的是一样的。commons-pool2用来做连接池是非常不错的。

我仔细找了找,发现还缺一个本地的MySQL连接池,而不是springboot那样需要启动一个服务才行。当然应该也是有的,不过我非常想自己写一个然后进行各类测试,所以也没有仔细找。

可池化对象

首先,我们需要一个可池化对象,这里我选用了com.funtester.db.mysql.FunMySql,这是一个我自己写的单链接的MySQL对象。我计划用这个作为基础可池化对象。

package com.funtester.db.mysql;
import com.funtester.base.interfaces.IMySqlBasic;
import com.funtester.config.SqlConstant;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
/**
 * mysql操作的基础类
 * 

用于存储数据,多用于爬虫

 */ public class FunMySql extends SqlBase implements IMySqlBasic {     /**      *  {@link SqlConstant#FUN_SQL_URL}会替换IP到URL      */     String url;     /**      * 库      */     String database;     /**      * 用户      */     String user;     /**      * 密码      */     String password;     Connection connection;     Statement statement;     /**      * 私有构造方法      *      * @param url      连接地址,包括端口      * @param database 库      * @param user     用户名      * @param password 密码      */     public FunMySql(String url, String database, String user, String password) {         this.url = url;         this.database = database;         this.user = user;         this.password = password;         getConnection(database);     }     /**      * 初始化连接      */     @Override     public void getConnection() {         getConnection(EMPTY);     }     /**      * 执行sql语句,非query语句,并不关闭连接      *      * @param sql      */     @Override     public void executeUpdateSql(String sql) {         SqlBase.executeUpdateSql(connection, statement, sql);     }     /**      * 查询功能      *      * @param sql      * @return      */     @Override     public ResultSet executeQuerySql(String sql) {         return SqlBase.executeQuerySql(connection, statement, sql);     }     /**      * 关闭query连接      */     @Override     public void over() {         SqlBase.close(connection, statement);     }     @Override     public void getConnection(String database) {         if (connection == null)             connection = SqlBase.getConnection(SqlConstant.FUN_SQL_URL.replace("ip", url).replace("database", database), user, password);         if (statement == null) statement = SqlBase.getStatement(connection);     } }

池化工厂

相对连接,创建com.funtester.db.mysql.FunMySql的时候,顺便一起初始化MySQL连接。然后再com.funtester.db.mysql.MysqlPool.FunTester#destroyObject的时候进行连接的回收。

    /**
     * 池化工厂类
     */
    private class FunTester extends BasePooledObjectFactory {
        @Override
        FunMySql create() throws Exception {
            return new FunMySql(url, database, user, password)
        }
        @Override
        PooledObject wrap(FunMySql obj) {
            return new DefaultPooledObject(obj)
        }
        @Override
        void destroyObject(PooledObject p) throws Exception {
            p.getObject().over()
            super.destroyObject(p)
        }
    }

对象池

这里显得有些冗余,后面再使用过程中,我会继续优化。通过创建一个com.funtester.db.mysql.MysqlPool对象,获取一个com.funtester.db.mysql.FunMySql对象池。

/**
 * 自定义MySQL连接池对象
 */
class MysqlPool extends PoolConstant {
    private static final Logger logger = LogManager.getLogger(MysqlPool.class);
    /**
     * {@link com.funtester.config.SqlConstant#FUN_SQL_URL}会替换IP到URL*/
    String url;
    /**
     * 库
     **/
    String database;
    /**
     * 用户
     **/
    String user;
    /**
     * 密码
     **/
    String password;
    private GenericObjectPool pool
    MysqlPool(String url, String database, String user, String password) {
        this.url = url
        this.database = database
        this.user = user
        this.password = password
        init()
    }
    /**
     * 初始化连接池
     * @return
     */
    def init() {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(MAX);
        poolConfig.setMinIdle(MIN_IDLE);
        poolConfig.setMaxIdle(MAX_IDLE);
        poolConfig.setMaxWaitMillis(MAX_WAIT_TIME);
        poolConfig.setMinEvictableIdleTimeMillis(MAX_IDLE_TIME);
        pool = new GenericObjectPool(new FunTester(), poolConfig);
    }
}

API封装

自从学习了Go语言的gorm框架和Redis框架,我发现其实不用把池化相关信息不用暴露出来,直接封装原始的API,暴露给用户使用,这样用户就不用关心连接的回收问题了。

    /**
     * 借出对象
     * @return
     */
    def borrow() {
        try {
            return pool.borrowObject()
        } catch (e) {
            logger.warn("获取${JSONObject.class} 失败", e)
        } finally {
            new JSONObject()
        }
    }
    /**
     * 归还对象
     * @param funMySql
     * @return
     */
    def back(FunMySql funMySql) {
        pool.returnObject(funMySql)
    }
    /**
     * 执行update SQL
     * @param sql
     * @return
     */
    def execute(def sql) {
        def driver = borrow()
        try {
            driver.executeUpdateSql(sql)
        } catch (e) {
            logger.warn("执行:{}失败", sql)
        } finally {
            back(driver)
        }
    }
    /**
     * 执行查询SQL
     * @param sql
     * @return
     */
    def query(def sql) {
        def driver = borrow()
        try {
            return driver.executeQuerySql(sql)
        } catch (e) {
            logger.warn("执行:{}失败", sql)
        } finally {
            back(driver)
        }
    }

以上就是MySQL连接池自定义示例详解的详细内容,更多关于MySQL连接池自定义的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(MySQL池化框架学习接池自定义)