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.