元数据之动态加载不同版本驱动jar包
1. 核心代码
public void driverTest() throws Exception {
String userName = "username";
String password = "password";
String url = "jdbc:mysql://localhost:3306/schema";
String className = "com.mysql.jdbc.Driver";
String jarFilePath = "file:/home/xxx/libs/mysql-connector-java-8.0.29.jar";
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
Driver driver = (Driver) Class.forName(className, true, loader).newInstance();
Connection connection = null;
Properties info = new Properties();
info.put("user", userName);
info.put("password", password);
connection = driver.connect(url, info);
System.out.println(connection.getMetaData().getDatabaseProductVersion());
System.out.println(connection.getMetaData().getDriverVersion());
}
2.类加载器
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
jarFilePath指向类所在的jar包,指定类加载器装载驱动类的路径。 注意类加载器的parent需要设为null,否则它会将加载类通过双亲委派机制委派给AppClassLoader,如果AppClassLoader中已经存在同限定名的类(比如pom文件依赖),这里UrlClassLoader中加载的类会被忽略。
3.获取驱动与连接
Class.forName用于加载指定限定名的类,参数中需要指定类加载器loader。jdbc的驱动类被加载时,会被驱动管理器DriverManager管理,但是通过DriverManager.getConnection()方法获取连接时,无法指定类加载器/驱动对象,这里需要使用driver.connect()。
4.可能会出现的异常
NoClassDefFoundErro
occurs error when execute method ,message org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: com/clickhouse/client/logging/LoggerFactory
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
-
解决方案
方案一:
重写jdbc代码,将完整依赖代码写入一个jar包
方案二:
加载完整依赖包,修改此行代码
// URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file:a.jar"),new URL("file:b.jar") }, null);