Maven 使用要点
记录一些使用过程遇到的问题。
Maven 依赖配置
<?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>com.envview.hgy.tool</groupId>
<artifactId>DBRemover</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
</dependencies>
</project>
Maven 打包
如果没有配置Maven构建参数,虽然在IDEA上能调试和运行项目,但执行mvn 的 clean package 命令打出来的 jar 包,放在服务器上运行(java -jar App.jar),并不能正常运行,因为有两个问题:
- 没有指定入口函数,将提示:Could not find or load main class App.jar
- 依赖的jar包没有一起打包进入App.jar,将提示找不到jar包中的类,如:ClassNotFoundException: com.mysql.jdbc.Driver
所以,还应该配置 Maven 构建 (build)所需要的一些插件,指定主函数,并在打包时,配置依赖项。
注意:本文打包用的是java8,如果出现问题,那么可能是mvn命令依赖的jdk版本问题。
打成一个完整的可执行 jar 包
使用maven-shade-plugin插件可以把所依赖的 jar 包一起打包成一个独立的可执行的 jar 包,并指定主函数。下面配置能解决上一节遇到的两个问题,配置如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
//主程序入口类,可以按住control,单机定位到该类
<mainClass>com.envview.hgy.tool.DBRemover</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意 <build> 配置应该放在<project>下面,与 <dependencies> 同级。
打成主 jar 包和外置依赖 jar 包
使用 maven-jar-plugin 和 maven-dependency-plugin 可打包成一个纯应用的主 jar 包(指定主函数)和外置依赖 jar 包。
maven-jar-plugin 插件可以配置 mainClass,maven-dependency-plugin 插件可以把依赖的 jar包拷贝到 target 目录下,把target下 App.jar 和依赖的 jar 包拷贝到应用环境,可以直接运行。
<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}
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix></classpathPrefix>
//主程序入口类,可以按住control,单机定位到该类
<mainClass>com.envview.hgy.tool.DBRemover</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
将依赖的jar包和配置文件外置的打包方式
将项目依赖的jar包外置到主jar包所在目录的lib目录,resources文件外置到主jar包所在目录的配置:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<!-- 配置打包后jar包内的元数据,比如classpath是什么【从哪里找依赖】 -->
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>me.silentdoer.demomybladetest.Entrance</mainClass> <useUniqueVersions>false</useUniqueVersions>
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>
<!-- 排除文件的写法 -->
<exclude>**/*.xml</exclude>
<!-- 排除resources内的某个目录打包到项目jar包内 -->
<exclude>/config/**</exclude>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
<executions>
<execution>
<!-- 如果不行这个换成copy-config试试 -->
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- 将resources的内容复制到target目录里 -->
<outputDirectory>${project.build.directory}/</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<encoding>UTF-8</encoding>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<!-- 这里是否可以增加多个execution和通过include等来实现将部分依赖直接压缩到主jar包内? -->
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 将依赖复制到target目录下的lib目录里 -->
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<!-- 要包含间接依赖 -->
<excludeTransitive>false</excludeTransitive>
<!-- 不忽略版本 -->
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
<!-- 这个是可以生成一个zip包或war包,而且它是后于jar包生成,所以可以引用target的文件 -->
<!-- 如果不需要生成zip包或war包等,只需要jar包则上面的配置就够了,这个可以注释掉 -->
<!-- 注意,这里依赖了一个package.xml文件,这个文件一般放在项目/module根目录里 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<!-- 如果是true则压缩包名字最后面会加package.xml里的id值 -->
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
这个是module项目根目录下的package.xml文件的配置,里面的内容可以根据自己实际情况修改:
<assembly>
<id>distribution</id>
<formats>
<!-- 这里填zip,war。。等等包类型,war包会自动在压缩文件根目录添加以META-INF目录 -->
<format>zip</format>
</formats>
<!-- true表示压缩包内部会用一个和压缩包前缀名一样的目录包裹需要压缩的文件,目录等,false则
打开压缩包就能直接看到outputDirectory配置的目录、文件-->
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<!-- 将directory里的文件压缩到压缩包文件里的outputDirectory目录里-->
<directory>src/main/resources</directory>
<outputDirectory>/sk</outputDirectory>
<includes>
<!-- 注意这里必须手动指定需要directory里的哪些文件压缩到压缩包的outputDirectory里
如果是全部文件则**/*来配置 -->
<include>**/system*</include>
</includes>
</fileSet>
<!-- 还可以包含target目录里的文件,因为assembly这个maven插件是要比jar插件更晚执行
,此时target及内部文件已经生成 -->
<fileSet>
<directory>target</directory>
<!-- 表示直接将include添加的文件或目录输出到压缩包的相对根路径里 -->
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
参考:
https://www.cnblogs.com/silentdoer/p/12612254.html