GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

用maven的shade插件打包javaFX项目

用maven的shade插件打包javaFX项目

javaFX是java在2007年首次公布,可用于替代Java Swing、AWT 等图形界面的客户端UI框架。

java项目一般会被打包成一个jar,然后和依赖的jar一起发布,运行时要在classpath里指定出来各个依赖的jar。我们开发项目时一般用很多现成的轮子,依赖的jar很多。

maven的shade插件可以把依赖的jar一起打包到一个大jar中(这个jar体积会比较大),之后仅拷贝并运行一个jar就可以了,为使用提供了很多方便。

使用 shade 插件

在pom.xml中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- 下面这个改成运行jar包时需要执行的java类 -->
<mainClass>cn.devmgr.client.NewMain</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>


createDependencyReducedPom 是用来告诉shade不要生成dependency-reduced-pom.xml文件的,配置成true(默认)每次打包时会自动在pom.xml同级目录生成这个文件,如果配置成true,建议把此文件假如.gitignore。

mainClass用来指定启动类,特别注意这个启动类,不能是javaFX的启动类,要另写一个。

创建一个仅供shade插件用的启动类

不能把javaFX的启动类直接配置给shade插件,否则打包后的文件会运行不起来。出现类似 Error: JavaFX runtime components are missing, and are required to run this application 这样的错误提示。要解决它,需要做一个新的,不使用javaFX的启动类

1
2
3
4
5
6
7
8
9
package cn.devmgr.client;

public class NewMain {

public static void main(String[] args) {
MainApp.main(args); //MainApp是javaFX的启动类,直接调用它即可
}
}

这是由于javaFX启动机制和打包成一个大jar后对分jar运行的改变造成的,详细可参考

  1. https://stackoverflow.com/questions/52653836/maven-shade-javafx-runtime-components-are-missing
  2. https://stackoverflow.com/questions/52569724/javafx-11-create-a-jar-file-with-gradle/52571719#52571719

pom.xml 里的javaFX依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>15.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>15.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>15.0.1</version>
</dependency>

<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>15.0.1</version>
<classifier>mac</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>15.0.1</version>
<classifier>win</classifier>
</dependency>

这里只列出来了我使用到的几个,其他(例如webview)如果项目中使用,需要再增加依赖。
特别注意webview和javafx-graphics一样,分平台不同包的,而且体积很大。

IntelliJ IDEA 里直接运行时遇到的错误

在idea里直接运行javaFX启动类,如果遇到以下错误

1
2
3
4
5
6
7
8
Graphics Device initialization failed for :  es2, sw
Error initializing QuantumRenderer: no suitable pipeline found
java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:244)
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:261)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)

而且命令行运行没问题,这很可能是idea使用了不是自己平台的javafx-graphics包导致的。
例如我在mac idea里,如果maven pom.xml的两个javafx-graphics win在前,mac在后就会出现这个异常,只需要把自己平台的调整到前面,reimport就好。

IntelliJ IDEA 里对module-java.java的错误提示及原因

idea 里会提示module-java.java中有一个错误

Module ‘xxx’ reads package ‘javafx.animation’ from both ‘javafx.graphics’ and ‘javafx.graphics’

这个提示不影响运行,出现这个提示的原因是 javafx.graphics 在依赖中出现了2次。
此处出现两次是因为pom.xml的确写了2个javafx-graphics的依赖(mac和win两个)。如果不需要跨平台,pom里只写一个,也就不会出现这个提示了。

一个完整的 pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.devmgr.client</groupId>
<artifactId>client-tool</artifactId>
<version>1.0-SNAPSHOT</version>


<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<javafx.maven.plugin.version>0.0.6</javafx.maven.plugin.version>
</properties>

<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>15.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>15.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>15.0.1</version>
</dependency>

<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>15.0.1</version>
<classifier>mac</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>15.0.1</version>
<classifier>win</classifier>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.31</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>


<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.36.0.1</version>
</dependency>


</dependencies>


<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</execution>
</executions>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>

<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.maven.plugin.version}</version>
<configuration>
<mainClass>cn.devmgr.client.MainApp</mainClass>
</configuration>
</plugin>


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<!-- <createDependencyReducedPom>false</createDependencyReducedPom>-->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- 下面这个改成运行jar包时需要执行的java类 -->
<mainClass>cn.devmgr.client.NewMain</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>
</build>
</project>

maven 命令行

运行javaFX项目

1
mvn javafx:run

打包(和其他maven项目相同)

和其他maven项目完全相同,只是打包完毕target目录下的jar包很大。 fat jar

1
mvn package