掘金 后端 ( ) • 2021-12-06 11:12

1 引言

mybatis generator 是一个命令行运行工具,可以生成 mybatis 代码。但它需要依赖数据库驱动 jar,否则会抛出 ClassNotFoundException 异常。

Exception in thread "main" java.lang.RuntimeException: Exception getting JDBC Driver
        at org.mybatis.generator.internal.JDBCConnectionFactory.getDriver(JDBCConnectionFactory.java:100)
        at org.mybatis.generator.internal.JDBCConnectionFactory.getConnection(JDBCConnectionFactory.java:83)
        at org.mybatis.generator.config.Context.getConnection(Context.java:542)
        at org.mybatis.generator.config.Context.introspectTables(Context.java:446)
        at org.mybatis.generator.api.MyBatisGenerator.generate(MyBatisGenerator.java:257)
        at org.mybatis.generator.api.MyBatisGenerator.generate(MyBatisGenerator.java:189)
        at org.mybatis.generator.api.ShellRunner.main(ShellRunner.java:117)
Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at org.mybatis.generator.internal.ObjectFactory.internalClassForName(ObjectFactory.java:148)
        at org.mybatis.generator.internal.ObjectFactory.externalClassForName(ObjectFactory.java:119)
        at org.mybatis.generator.internal.JDBCConnectionFactory.getDriver(JDBCConnectionFactory.java:97)
        ... 6 more
'-overwrite' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

这也就引出了本文的问题:利用 Java jar 命令行运行程序如何引用第三方依赖包?

2 Java 类加载器

JDK9 之前把类加载器分为三类,它们分别是启动类加载器、扩展类加载器和应用程序类加载器。

(1)启动类加载器 ( Bootstrap Class Loader )

启动类加载器负责加载存放在 \lib 目录,或者被 -Xbootclasspath 参数所指定的路径中存放的、且是 Java 虚拟机能够识别的类库加载到虚拟机的内存中。

(2)扩展类加载器 (Extension Class Loader)

扩展类加载器是在类 sun.misc.Launchers&ExtClassLoader 中以 Java 代码的形式实现的。它负责加载 \lib\ext 目录中,或者被 java. ext .dirs 系统变量所指定的路径中所有的类库。

(3)应用程序类加载器 (Application Class Loader )

应用程序类加载器由 sun.misc.Launcher&AppClassLoader 实现。它负责加载用户类路径 (Classpath) 上所有的类库。

3 双亲委派模型

在这里插入图片描述

类加载器之间的层次关系被称为类加载器的 “ 双亲委派模型 (Parents Delegation Model)”。 双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求 ( 它的搜索范围中没有找到所需的类 ) 时,子加载器才会尝试自己去完成加载。

4 引用第三方依赖包

(1)使用启动类加载器

-Xbootclasspath/a:xxx.jar

示例:

java -Xbootclasspath/a:postgresql-42.2.18.jar; -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml -overwrite

(2) 使用扩展类加载器

-Djava.ext.dirs=扩展类所在路径

示例:

cd C:\workspace\ideaProjects\deniro-app\deniro-fly\generator\
java -Djava.ext.dirs=C:\programs\jdk1.8.0_181\jre\lib\ext -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml
-overwrite

通过扩展类加载器来指定第三方依赖包的所在路径,可以实现多个命令行程序复用这些第三方依赖包,因此建议采用。

参考资料

周志明. 深入理解Java虚拟机[M]. 机械工业出版社, 2019.

https://www.cnblogs.com/wqbin/p/11122709.html

https://blog.csdn.net/cyony/article/details/74375251/