让maven生成可运行jar包
平时项目大多用到的是war包,今天实现了一个简单功能,无需部署到web服务器上,只需本地跑java代码即可,因此只要生成一个jar包。那么怎么让maven项目打成一个可以使用java命令跑的jar包呢?这里通过maven插件实现:
首先修改pom.xml文件,这里需要新增build节点,在build里加入plugins节点:
<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>com.wlf.net</groupId> <artifactId>point-circle</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>point-circle</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.12.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>10.2.0.2.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.wlf.net.point.App</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/lib </outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
上面的pom文件里有两个plugin,第一个是在jar包中的META-INF/MANIFEST.MF中指定Main-Class,指定lib库的jar包依赖classpath;第二个是把依赖到的lib库jar包都复制到配置的classpathPrefix目录下,这一步不做的话运行打出来的jar包会报错,因为相关依赖的jar包虽然配置了classpath但其实该classpath下并没有真实的jar包存在。addClasspath为true说明需要在MANIFEST.MF加上classpath并配置依赖包,classpathPrefix指定依赖包所在的目录,mainClass指定MANIFEST.MF中的Main-Class。${project.build.directory}这变量是maven内置的,系统会自动寻找,其实就编译class的目录target,这里配置的${project.build.directory}/lib,在我本机就是E:\workspace\point-circle\target\lib。每次修改完pom配置文件之后,记得在Eclipse右击项目,点击Update Project让修改生效。
执行maven打包命令:
E:\workspace\point-circle>mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building point-circle 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ point-circle ---
[INFO] Deleting E:\workspace\point-circle\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ point-circle ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\workspace\point-circle\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ point-circle ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to E:\workspace\point-circle\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ point-circle ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\workspace\point-circle\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ point-circle ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\workspace\point-circle\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ point-circle ---
[INFO] Surefire report directory: E:\workspace\point-circle\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.wlf.net.point.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.063 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ point-circle ---
[INFO] Building jar: E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (copy) @ point-circle ---
[INFO] Copying commons-dbcp-1.2.2.jar to E:\workspace\point-circle\target\lib\commons-dbcp-1.2.2.jar
[INFO] Copying spring-expression-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-expression-4.3.12.RELEASE.jar
[INFO] Copying jts-1.8.jar to E:\workspace\point-circle\target\lib\jts-1.8.jar
[INFO] Copying commons-pool-1.3.jar to E:\workspace\point-circle\target\lib\commons-pool-1.3.jar
[INFO] Copying hamcrest-core-1.3.jar to E:\workspace\point-circle\target\lib\hamcrest-core-1.3.jar
[INFO] Copying spring-aop-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-aop-4.3.12.RELEASE.jar
[INFO] Copying spring-web-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-web-4.3.12.RELEASE.jar
[INFO] Copying junit-4.12.jar to E:\workspace\point-circle\target\lib\junit-4.12.jar
[INFO] Copying commons-logging-1.2.jar to E:\workspace\point-circle\target\lib\commons-logging-1.2.jar
[INFO] Copying spring-jdbc-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-jdbc-4.3.12.RELEASE.jar
[INFO] Copying spring-webmvc-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-webmvc-4.3.12.RELEASE.jar
[INFO] Copying spring-core-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-core-4.3.12.RELEASE.jar
[INFO] Copying spring-context-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-context-4.3.12.RELEASE.jar
[INFO] Copying ojdbc14-10.2.0.2.0.jar to E:\workspace\point-circle\target\lib\ojdbc14-10.2.0.2.0.jar
[INFO] Copying spring-beans-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-beans-4.3.12.RELEASE.jar
[INFO] Copying spring-context-support-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-context-support-4.3.12.RELEASE.jar
[INFO] Copying spring-tx-4.3.12.RELEASE.jar to E:\workspace\point-circle\target\lib\spring-tx-4.3.12.RELEASE.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ point-circle ---
[INFO] Installing E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.jar
[INFO] Installing E:\workspace\point-circle\pom.xml to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.180 s
[INFO] Finished at: 2018-01-25T21:13:38+08:00
[INFO] Final Memory: 23M/196M
[INFO] ------------------------------------------------------------------------
看下我们打出来的jar包里的MANIFEST.MF目录和内容:point-circle-0.0.1-SNAPSHOT.jar\META-INF\MANIFEST.MF
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Built-By: wulf Class-Path: lib/spring-core-4.3.12.RELEASE.jar lib/commons-logging-1.2 .jar lib/spring-context-support-4.3.12.RELEASE.jar lib/spring-beans-4 .3.12.RELEASE.jar lib/spring-context-4.3.12.RELEASE.jar lib/spring-ao p-4.3.12.RELEASE.jar lib/spring-expression-4.3.12.RELEASE.jar lib/spr ing-web-4.3.12.RELEASE.jar lib/spring-webmvc-4.3.12.RELEASE.jar lib/s pring-jdbc-4.3.12.RELEASE.jar lib/spring-tx-4.3.12.RELEASE.jar lib/jt s-1.8.jar lib/commons-dbcp-1.2.2.jar lib/commons-pool-1.3.jar lib/ojd bc14-10.2.0.2.0.jar Created-By: Apache Maven 3.3.9 Build-Jdk: 1.8.0_102 Main-Class: com.wlf.net.point.App
上面列出了classpath里所依赖到的jar包列表、主class。最后打开命令行界面执行jar包:
E:\>cd E:\workspace\point-circle\target E:\workspace\point-circle\target>java -jar point-circle-0.0.1-SNAPSHOT.jar Exception in thread "main" java.lang.NullPointerException at com.wlf.net.point.App.main(App.java:39)
空指针是spring的注入问题,这里说明可执行jar包出炉了。但如果我把这个新鲜烤出来的jar包复制到另一个地方,比如E盘,再执行就报找不到依赖的jar包了:
E:\>java -jar point-circle-0.0.1-SNAPSHOT.jar Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: com/vividsolutions/jts/io/ParseException at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: com.vividsolutions.jts.io.ParseException at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 7 more
看来这个面包只能在面包店里吃了,我打包带走就吃不了。这是因为classpath已经设定了依赖jar包的位置了,只能到当前目录target的lib目录下找,你拿到其他地方还想跑也可以,那么请你一并把lib目录复制过去吧。难道我吃个面包还得随身带个烤面包机吗?是的,但是我们不用到处复制,把烤面包机放进面包里就可以了。这里我们就要用到另一个maven插件了,它可以把我们所依赖的jar包一并打入我们自己的jar包里。我们干掉之前那两个plugin,换成maven-assembly-plugin这个plugin,改后的pom文件的build节点如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.wlf.net.point.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
再次执行打包命令:
E:\workspace\point-circle>mvn clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building point-circle 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ point-circle --- [INFO] Deleting E:\workspace\point-circle\target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ point-circle --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory E:\workspace\point-circle\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ point-circle --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 3 source files to E:\workspace\point-circle\target\classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ point-circle --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory E:\workspace\point-circle\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ point-circle --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to E:\workspace\point-circle\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ point-circle --- [INFO] Surefire report directory: E:\workspace\point-circle\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.wlf.net.point.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.068 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ point-circle --- [INFO] Building jar: E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- maven-assembly-plugin:2.2-beta-5:single (make-assembly) @ point-circle --- [INFO] [INFO] --- maven-install-plugin:2.4:install (default-install) @ point-circle --- [INFO] Installing E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.jar [INFO] Installing E:\workspace\point-circle\pom.xml to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.pom [INFO] Installing E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT-jar-with-dependencies.jar to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT-jar-with-dependencies.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 24.621 s [INFO] Finished at: 2018-01-26T11:17:05+08:00 [INFO] Final Memory: 29M/230M [INFO] ------------------------------------------------------------------------
这次生成的jar包里多了很多东西,而且名称也变了:point-circle-0.0.1-SNAPSHOT-jar-with-dependencies.jar。我们把它复制到E盘执行,这次没问题了:
C:\Users\wulf>e: E:\>java -jar point-circle-0.0.1-SNAPSHOT-jar-with-dependencies.jar Exception in thread "main" java.lang.NullPointerException at com.wlf.net.point.App.main(App.java:39)
还可以用另外一个插件maven-shade-plugin来代替maven-assembly-plugin,修改后的pom文件如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.wlf.net.point.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行maven打包:
:\workspace\point-circle>mvn clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building point-circle 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ point-circle --- [INFO] Deleting E:\workspace\point-circle\target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ point-circle --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 2 resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ point-circle --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 3 source files to E:\workspace\point-circle\target\classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ point-circle --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory E:\workspace\point-circle\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ point-circle --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to E:\workspace\point-circle\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ point-circle --- [INFO] Surefire report directory: E:\workspace\point-circle\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.wlf.net.point.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.036 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ point-circle --- [INFO] Building jar: E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- maven-shade-plugin:2.4.1:shade (default) @ point-circle --- [INFO] Including org.springframework:spring-core:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including commons-logging:commons-logging:jar:1.2 in the shaded jar. [INFO] Including org.springframework:spring-context-support:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-beans:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-context:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-aop:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-expression:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-web:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-webmvc:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-jdbc:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including org.springframework:spring-tx:jar:4.3.12.RELEASE in the shaded jar. [INFO] Including com.vividsolutions:jts:jar:1.8 in the shaded jar. [INFO] Including commons-dbcp:commons-dbcp:jar:1.2.2 in the shaded jar. [INFO] Including commons-pool:commons-pool:jar:1.3 in the shaded jar. [INFO] Including com.oracle:ojdbc14:jar:10.2.0.2.0 in the shaded jar. [INFO] Replacing original artifact with shaded artifact. [INFO] Replacing E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar with E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT-shaded.jar [INFO] Dependency-reduced POM written at: E:\workspace\point-circle\dependency-reduced-pom.xml [INFO] Dependency-reduced POM written at: E:\workspace\point-circle\dependency-reduced-pom.xml [INFO] [INFO] --- maven-install-plugin:2.4:install (default-install) @ point-circle --- [INFO] Installing E:\workspace\point-circle\target\point-circle-0.0.1-SNAPSHOT.jar to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.jar [INFO] Installing E:\workspace\point-circle\dependency-reduced-pom.xml to E:\Users\wulf\.m2\repository\com\wlf\net\point-circle\0.0.1-SNAPSHOT\point-circle-0.0.1-SNAPSHOT.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.557 s [INFO] Finished at: 2018-01-26T16:33:45+08:00 [INFO] Final Memory: 28M/195M [INFO] ------------------------------------------------------------------------
注意这里会生成两个jar,一个带original前缀表示原始jar包,一个没带该前缀,我们要用的是没带的。