同一个项目如果引入多个版本数据库,ClassLoad加载驱动时会报版本冲突,所以不能以Maven包的形式映入到项目中,只能在需要获取数据库连接时通过读取jar文件的形式来加载驱动。实际开发中我们项目是要打成jar包的形式的所以需要判断下项目的运行方式,springboot的可执行jar通过copy目录BOOT-INF/driverlib/下的对应jar包生成新的文件再加载。
/**
* 从lib包中读取驱动,创建数据库连接
*
* @param driverInfoPO 驱动信息
* @param connectionInfoPO 连接信息
* @return 数据库连接
* @throws Exception 获取DB连接失败
*/
public static Connection create(DriverInfoBO driverInfoPO, ConnectionInfoBO connectionInfoPO) throws Exception {
File file = new File(userDir + "/tmp/" + driverInfoPO.getJarFileName());
MyClassLoader loader = null;
synchronized (LOCK) {
loader = urlClassLoaderMap.get(driverInfoPO.getJarFileName());
if (loader == null) {
String jarFilePath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
//打成jar包运行
if(jarFilePath.contains("!/BOOT-INF/")){
jarFilePath = jarFilePath.replace("!/BOOT-INF/classes!/", "");
if (jarFilePath.startsWith("file")) {
jarFilePath = jarFilePath.substring(5);
}
JarFile jarFile = new JarFile(jarFilePath);
File dir = new File(userDir + "/tmp");
if(!dir.exists()){
dir.mkdirs();
}
if(!file.exists()){
dir.createNewFile();
}
log.info("驱动包文件位置 BOOT-INF/driverlib/" + driverInfoPO.getJarFileName());
ZipEntry zipEntry = jarFile.getEntry("BOOT-INF/driverlib/" + driverInfoPO.getJarFileName());
FileUtil.copyInputStreamToFile(jarFile.getInputStream(zipEntry), file);
System.out.println(jarFilePath);
loader = new MyClassLoader();
loader.addFile(file);
}else {
//idea
jarFilePath = userDir + "/driverlib" + File.separator
+ driverInfoPO.getJarFileName();
if (loader == null) {
URL url = new URL("jar:file:/" + jarFilePath + "!/");
System.out.println(url.getPath());
loader = new MyClassLoader(new URL[]{url});
}
}
urlClassLoaderMap.put(driverInfoPO.getJarFileName(), loader);
}
}
// 记录原始ClassLoader并设置当前线程的ClassLoader
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(loader);
// 获取数据库连接
Driver driver = (Driver) loader.loadClass(driverInfoPO.getDriverClassName()).newInstance();
Properties connInfo = new Properties();
connInfo.put("user", connectionInfoPO.getUsername());
connInfo.put("password", connectionInfoPO.getPassword());
Connection conn = driver.connect(connectionInfoPO.getUrl(), connInfo);
// 还原原始ClassLoader
Thread.currentThread().setContextClassLoader(oldClassLoader);
return conn;
}