java运行时从jar包中动态加载类

109 阅读1分钟

数据治理过程中,需要java后端连接不同数据源去执行不同sql,这就涉及到根据jdbc去从jar文件里面去加载数据库的驱动(把所有驱动都加在依赖里面似乎不太现实,每新增一种数据库还需要更改代码)。

// 从jar文件中获取驱动类

public Driver getDriverFromJar(String className, List<String> localPathList) {
    log.info("threadId:{}", Thread.currentThread().getId());
    try {
        List<URL> urlList = localPathList.stream().map(this::getUrls).collect(toList());
        URLClassLoader classLoader = new URLClassLoader(urlList.toArray(new URL[urlList.size()]), Thread.currentThread().getContextClassLoader());
        Class<?> jdbcClass = classLoader.loadClass(className);
        Object object = jdbcClass.getDeclaredConstructor().newInstance();
        if (object instanceof Driver) {
            return (Driver) object;
        }
    } catch (Exception e) {
        log.error("driver类实例化出错", e);
    }
    return null;
}

// 从数据源创建jdbcTemplate对象

private List buildJdbcTemplate(Long tableId) {

        Map<String, String> stringStringMap = mdMetaObjMapper.queryDefInfo(tableId);
        String data_source_id = stringStringMap.getOrDefault("data_source_id", "0");
        String db_instance_en_name = stringStringMap.getOrDefault("db_instance_en_name", "");
        String db_schema_en_name = stringStringMap.getOrDefault("db_schema_en_name", "");
        ArDataSource arDataSource = arDataSourceMapper.getOne(Long.valueOf(data_source_id));
        if (arDataSource == null) {
            log.error(tableId + ",的数据源无法找到!");
            return null;
        }
        String ipAddr = arDataSource.getIpAddr();
        String port = arDataSource.getPort();
        String para = arDataSource.getPara();

        ArDbEngine arDbEngine = arDbEngineMapper.getOne(arDataSource.getDbEngineId());
        String cnName = "";
        if (StringUtils.hasText(arDbEngine.getCnName())) {
            cnName = arDbEngine.getCnName();
        }
        String driverClass = null;
        if (Objects.nonNull(arDbEngine) && StringUtils.hasText(arDbEngine.getDriverClass())) {
            driverClass = arDbEngine.getDriverClass();
        }
        String urlFormat = arDbEngine.getUrlFormat();
        Map<String, Object> param = new HashMap<String, Object>() {{
            put("host", ipAddr);
            put("port", port);
            put("dbName", db_instance_en_name);
            put("schemaName", db_schema_en_name);

        }};

        String connectStr = FreemarkerUtil.render(urlFormat, param);
        if (StringUtils.hasText(para)) {
            connectStr += para;
        }
        log.warn("urlFormat:{},connectStr:{}", urlFormat, connectStr);
        List list = new ArrayList();
        JdbcTemplate jdbcTemplate = null;
        try {
            List<String> ambryIdList = Lists.newArrayList(org.apache.commons.lang3.StringUtils.split(arDbEngine.getJarPath(), ","));
            Map<String, String> localPathMap = scraperLocalPathService.prepareLocalPath(data_source_id, ambryIdList, true);

            SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
            dataSource.setDriver(getDriverFromJar(driverClass, Lists.newArrayList(localPathMap.values())));

            dataSource.setUrl(connectStr);
            dataSource.setUsername(arDataSource.getUserName());
            dataSource.setPassword(arDataSource.getPwd());

            jdbcTemplate = new JdbcTemplate(dataSource);
            list.add(0, cnName);
            list.add(1, jdbcTemplate);
            return list;
        } catch (Throwable e) {
        
            log.error("构建JdbcTemplate异常,arDataSource:{},arDbEngine:{},err:{}", arDataSource.toString(), arDbEngine.toString(), e.getMessage(), e);
            return null;
        }
    }