All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.eova.common.jdbc.DruidDataSource Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2023 EOVA.CN. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.eova.common.jdbc;

import java.sql.SQLException;
import java.util.HashMap;

import cn.eova.tools.string.AESUtil;
import cn.eova.tools.x;
import com.alibaba.druid.filter.logging.Log4jFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Plugins;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.IDataSourceProvider;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.druid.DruidPlugin;

/**
 * Druid 数据源
 * @author Jieven
 */
public class DruidDataSource {

    /**
     * 注册数据源(支持多数据源)
     *
     * @author Jieven
     */
    public static HashMap create(Plugins plugins) {

        HashMap dps = create();

        HashMap arps = new HashMap<>();
        dps.forEach((dp, arp) -> {
            plugins.add(dp).add(arp);
            arps.put(arp.getConfig().getName(), arp);
        });

        return arps;
    }

    /**
     * 创建数据源(支持多数据源)
     *
     * @author Jieven
     */
    public static HashMap create() {

        HashMap arps = new HashMap<>();

        // 多数据源支持
        String datasource = x.conf.get("db.datasource");
        if (x.isEmpty(datasource)) {
            throw new RuntimeException("数据源配置项不存在,请检查配置jdbc.config 配置项[db.datasource]");
        }
        for (String ds : datasource.split(",")) {
            ds = ds.trim();

            String url = x.conf.get(ds + ".url");
            String user = x.conf.get(ds + ".user");
            String pwd = x.conf.get(ds + ".pwd");
            if (x.isEmpty(url)) {
                throw new RuntimeException(String.format("数据源[%s]配置异常,请检查请检查配置jdbc.config", ds));
            }

            // JDBC密码加密
            if (x.conf.getBool("db.pwd.encrypt", false)) {
                pwd = AESUtil.decrypt(pwd);
            }

            DruidPlugin dp = DruidDataSource.initDruidPlugin(url, user, pwd);
            ActiveRecordPlugin arp = DruidDataSource.initActiveRecordPlugin(url, ds, dp);
            x.log.info("create ds[{}] {} > {}", ds, user, url);

            arps.put(dp, arp);

        }

        return arps;
    }

    /**
     * init Druid
     *
     * @param url      JDBC
     * @param username 数据库用户
     * @param password 数据库密码
     * @return
     */
    public static DruidPlugin initDruidPlugin(String url, String username, String password) {
        // 设置方言
        WallFilter wall = new WallFilter();
        String dbType = null;
        try {
            dbType = JdbcUtils.getDbType(url, JdbcUtils.getDriverClassName(url));
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        wall.setDbType(dbType);

        DruidPlugin dp = new DruidPlugin(url, username, password);
        dp.addFilter(new StatFilter());

        dp.setInitialSize(x.conf.getInt("db.conn.init", 1));// 初始化1个
        dp.setMinIdle(x.conf.getInt("db.conn.min", 2));// 最少空闲2个
        dp.setMaxActive(x.conf.getInt("db.conn.max", 64));// 连接上限
        dp.setMaxWait(x.conf.getInt("db.conn.timeout", 60000));// 配置获取连接等待超时的时间 60s(时间太短会导致高并发连接耗尽异常)

        // 开发者模式 降低SQL安全策略, 保证应用商店安装卸载需要开发者模式.
        boolean devMode = x.conf.getBool("devMode", false);
        if (devMode) {
            // https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter
            WallConfig config = new WallConfig();
            config.setMultiStatementAllow(true);// 一次执行多条语句
            config.setNoneBaseStatementAllow(false);// 非基本DDL语句
            wall.setConfig(config);
            wall.setThrowException(false);// SQL注入抛出SQLException
            wall.setLogViolation(true);/// SQL注入输出日志

            // 配置log插件
            Log4jFilter logFilter = new Log4jFilter();
            logFilter.setStatementLogEnabled(false);
            logFilter.setStatementLogErrorEnabled(true);
            logFilter.setStatementExecutableSqlLogEnable(true);
            dp.addFilter(logFilter);
        }
        dp.addFilter(wall);

        return dp;
    }

    /**
     * init ActiveRecord
     *
     * @param url JDBC
     * @param ds  DataSource
     * @param dp  Druid
     * @return
     */
    public static ActiveRecordPlugin initActiveRecordPlugin(String url, String ds, IDataSourceProvider dp) {
        // 提升事务级别保证事务回滚 MYSQL TRANSACTION_REPEATABLE_READ=4
        int lv = x.conf.getInt("db.transaction_level", 4);
        // DB默认命名规则
        boolean isLowerCase = x.conf.getBool("db.islowercase", true);
        // 是否输出SQL日志
        boolean isShowSql = x.conf.getBool("db.showsql", true);

        ActiveRecordPlugin arp = new ActiveRecordPlugin(ds, dp);

        // 构建方言
        arp.setDialect(new MysqlDialect());
        arp.setShowSql(isShowSql);
        arp.setTransactionLevel(lv);
        // 忽略大小写敏感字段无序
        arp.setContainerFactory(new CaseInsensitiveContainerFactory(isLowerCase));
        // 大小写敏感 保持字段顺序()
        // arp.setContainerFactory(new EovaContainerFactory(isLowerCase));

        return arp;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy