我需要测试与数据库的JDBC连接.执行此操作的Java代码应该如下所示:
DriverManager.getConnection("jdbc connection URL", "username", "password");
驱动程序管理器将查找给定连接URL的相应驱动程序.但是我需要能够在运行时加载JDBC驱动程序(jar).即我在运行上述代码片段的java应用程序的类路径上没有JDBC驱动程序.
所以我可以使用这段代码加载驱动程序,例如:
URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader()); Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance();
但是后来驱动程序管理器仍然不会接收它,因为我无法告诉它使用哪个类加载器.我尝试设置当前线程的上下文类加载器,它仍然无法正常工作.
任何人都有最好的方法来实现这一目标吗?
从文章中选择运行时的JDBC驱动程序 ; 我将在这里发布代码以供参考.
这个想法是欺骗驱动程序管理器认为驱动程序是从系统类加载器加载的.为此,我们使用此类:
public class DelegatingDriver implements Driver { private final Driver driver; public DelegatingDriver(Driver driver) { if (driver == null) { throw new IllegalArgumentException("Driver must not be null."); } this.driver = driver; } public Connection connect(String url, Properties info) throws SQLException { return driver.connect(url, info); } public boolean acceptsURL(String url) throws SQLException { return driver.acceptsURL(url); } public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { return driver.getPropertyInfo(url, info); } public int getMajorVersion() { return driver.getMajorVersion(); } public int getMinorVersion() { return driver.getMinorVersion(); } public boolean jdbcCompliant() { return driver.jdbcCompliant(); } }
这样,您注册的驱动程序DelegatingDriver
是加载系统类加载器的类型.您现在只需要使用您想要的任何类加载器加载您真正想要使用的驱动程序.例如:
URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader()); Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance(); DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found
问题是DriverManager
执行"使用直接调用者的类加载器实例的任务".请参阅Java编程语言安全编码指南的指南6-3 ,版本2.0.在这种情况下,系统类加载器绝不是特殊的.
仅仅为了踢,我不久前写了一篇关于这个主题的博客文章.我的解决方案虽然比Nick Sayer的解决方案更复杂,但更完整,甚至可以使用不受信任的代码.另请注意URLClassLoader.newInstance
优先new URLClassLoader
.