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 )
启动类加载器负责加载存放在 <JAVA_HOME>\lib
目录,或者被 -Xbootclasspath 参数所指定的路径中存放的、且是 Java 虚拟机能够识别的类库加载到虚拟机的内存中。
(2)扩展类加载器 (Extension Class Loader)
扩展类加载器是在类 sun.misc.Launchers&ExtClassLoader
中以 Java 代码的形式实现的。它负责加载 <JAVA_HOME>\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.