元数据之动态加载不同版本驱动jar包

210 阅读1分钟

元数据之动态加载不同版本驱动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);