Maven 使用 Maven 调试技巧 mvn dependency:tree
,打印依赖树mvn clean -X
,使用 -X
参数输出详细的日志信息mvn -X
,查看当前生效的是哪个 settings.xml
配置文件mvn help:effective-settings
,查看正在起作用的是那个 settings.xml
的文件内容安装跳过测试用例 使用命令 mvn install -DskipTests
,不执行测试用例,但会编译测试用例类的代码 使用命令 mvn install -Dmaven.test.skip=true
,不但跳过单元测试的运行,也跳过单元测试代码的编译 添加阿里云镜像仓库 添加阿里云的镜像到 Maven 的 setting.xml
配置文件中,这样就不需要每次在项目的 pom.xml
中添加镜像仓库的配置内容,在 <mirrors>
节点里添加对应的子节点即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <mirrors > <mirror > <id > alimaven</id > <name > aliyun maven</name > <url > https://maven.aliyun.com/repository/public/</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > repo2</id > <mirrorOf > central</mirrorOf > <name > Human Readable Name for this Mirror.</name > <url > http://repo2.maven.org/maven2/</url > </mirror > </mirrors >
Maven 项目配置 打包源码 有时候开发一个公共 Jar 包给别人引用,当别人打开包中的类的时候,默认情况下打开的是 IDE 工具反编译出来的 .class
文件,类中的注释什么的都看不到,此时 IDE 工具会提示可以 Download Sources
,但是如果打包的时候没有同时打一个以 -sources.jar
结尾的源码 Jar 包,那么调用方下载源码包的时候就会失败。maven-source
插件就是用来打包源码的,可以部署到私有仓库上的,对于需要查看源码、注释和调试代码,有很大的帮助。
1 2 3 4 5 6 7 8 9 10 11 12 <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-source-plugin</artifactId > <executions > <execution > <id > attach-sources</id > <goals > <goal > jar</goal > </goals > </execution > </executions > </plugin >
打包跳过测试用例 1 2 3 4 5 6 7 8 <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-surefire-plugin</artifactId > <version > 2.5</version > <configuration > <skipTests > true</skipTests > </configuration > </plugin >
使用阿里云镜像仓库 编辑项目的 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 <repositories > <repository > <id > public</id > <name > aliyun nexus</name > <url > http://maven.aliyun.com/nexus/content/groups/public/</url > <releases > <enabled > true</enabled > </releases > <snapshots > <enabled > false</enabled > </snapshots > </repository > </repositories > <pluginRepositories > <pluginRepository > <id > public</id > <name > aliyun nexus</name > <url > http://maven.aliyun.com/nexus/content/groups/public/</url > <releases > <enabled > true</enabled > </releases > <snapshots > <enabled > false</enabled > </snapshots > </pluginRepository > </pluginRepositories >
值得一提的是,Maven 默认中央仓库的 id
为 central
。其中 id
是唯一的,因此使用 <id>central</id>
就可以覆盖默认的中央仓库。
指定编译的 JDK 版本 方式一
1 2 3 4 <properties > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > </properties >
方法二
1 2 3 4 5 6 7 8 9 <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > 3.8.1</version > <configuration > <source > 1.8</source > <target > 1.8</target > </configuration > </plugin >
方法三
该方式并非 Maven 官方配置,要使该方式能够生效首先必须满足以下两个条件:
项目为一个 SpringBoot 工程 项目的 POM 继承了 spring-boot-starter-parent 1 2 3 4 5 6 7 8 9 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.1.3.RELEASE</version > </parent > <properties > <java.version > 1.8</java.version > </properties >
引入本地的 Jar 包 方法一(推荐)
通过 mvn install
命令手动将 Jar 包安装到 Maven 本地仓库(如下),相关资料可参考这里
1 $ mvn install:install-file -Dfile =taobao-sdk-java-auto.jar -DgroupId =com.dingtalk -DartifactId =dingtalk-api-sdk -Dversion =1.0.0-SNAPSHOT -Dpackaging =jar
最后在 pom.xml
里正常引入对应的依赖即可:
1 2 3 4 5 <dependency > <groupId > com.dingtalk</groupId > <artifactId > dingtalk-api-sdk</artifactId > <version > 1.0.0-SNAPSHOT</version > </dependency >
若需要从本地仓库卸载特定的本地 Jar 包,可以在 pom.xml
所在目录下执行以下命令,其中 -DmanualInclude
的参数格式为 groupId:artifactId
1 2 3 4 5 $ mvn dependency:purge-local -repository -DmanualInclude ="com.dingtalk:dingtalk-api-sdk" $ mvn dependency:purge-local -repository -DreResolve =false
方法二(推荐)
通过 Maven 插件将本地 Jar 包安装到 Maven 本地仓库(如下),值得一提的是,需要手动执行 mvn clean && mvn install
命令将本地 Jar 包安装到 Maven 本地仓库,相关资料可参考这里
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 <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-install-plugin</artifactId > <version > 2.5.2</version > <executions > <execution > <id > install-external</id > <phase > clean</phase > <configuration > <file > ${project.basedir}/lib/taobao-sdk-java-auto.jar</file > <repositoryLayout > default</repositoryLayout > <groupId > com.dingtalk</groupId > <artifactId > dingtalk-api-sdk</artifactId > <version > 1.0.0-SNAPSHOT</version > <packaging > jar</packaging > <generatePom > true</generatePom > </configuration > <goals > <goal > install-file</goal > </goals > </execution > </executions > </plugin > </plugins > </build >
最后在 pom.xml
里正常引入对应的依赖即可:
1 2 3 4 5 <dependency > <groupId > com.dingtalk</groupId > <artifactId > dingtalk-api-sdk</artifactId > <version > 1.0.0-SNAPSHOT</version > </dependency >
方法三(不推荐)
假设项目的目录结构如下:
1 2 3 4 5 market ├── common-api │ └── lib │ └── taobao-sdk-java-auto.jar └── common-cache
在 common-api
模块下的 pom.xml
添加以下依赖来引入本地 Jar 包:
groupId
:自定义artifactId
:自定义version
:自定义scope
:必须是 system
systemPath
:Jar 包的路径,${project.basedir}
是指当前 pom.xml
所在的目录1 2 3 4 5 6 7 <dependency > <groupId > com.dingtalk</groupId > <artifactId > dingtalk-api-sdk</artifactId > <version > 1.0.0-SNAPSHOT</version > <scope > system</scope > <systemPath > ${project.basedir}/lib/taobao-sdk-java-auto.jar</systemPath > </dependency >
若 common-api
模块是普通 Maven 项目,那么打包时需要添加以下配置,目的是将本地 Jar 包同时打包在一起:
directory
:指定 lib
文件夹的位置,一般直接写上 ${project.basedir}/lib
即可targetPath
:打包到的文件夹位置,写上 BOOT-INF/lib
即可,或者是 WEB-INF/lib
includes
:一般都是以 .jar
结尾,直接写 **/*.jar
即可1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <build > <resources > <resource > <directory > ${project.basedir}/lib</directory > <targetPath > /BOOT-INF/lib/</targetPath > <includes > <include > **/*.jar</include > </includes > </resource > <resource > <directory > src/main/resources</directory > <filtering > true</filtering > <includes > <include > **/*.*</include > </includes > </resource > </resources > </build >
若 common-api
模块是 SpringBoot 项目,那么打包时需要添加以下配置,目的是将本地 Jar 包同时打包在一起:
1 2 3 4 5 6 7 8 9 10 11 <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <includeSystemScope > true</includeSystemScope > </configuration > </plugin > </plugins > </build >
单元测试拷贝资源文件 @SpringBootTest
注解,只会加载 src/test
路径下的资源文件(如 XML 配置),并不会加载 src/main
路径下的资源文件。若需要在执行单元测试时,加载 src/main
路径下的资源文件,需要让 Maven 拷贝对应的资源文件到 src/test
路径下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <build > <resources > <resource > <directory > src/main/resources</directory > <filtering > true</filtering > <includes > <include > **/*.*</include > </includes > </resource > </resources > <testResources > <testResource > <directory > src/main/resources</directory > </testResource > <testResource > <directory > src/test/resources</directory > </testResource > </testResources > </build >
编译时过滤字体图标文件 如果 Maven 编译项目时,出现下述的错误信息。这一般是 Maven 的 filter
解析字体图标文件时,破坏了文件的二进制文件格式导致的。
1 filtering /xxxx/target/classes/static/fonts/webfont.ttf failed with MalformedInputException: Input length = 1 -> [Help 1]
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 <build > <resources > <resource > <directory > src/main/resources</directory > <filtering > true</filtering > </resource > </resources > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-resources-plugin</artifactId > <version > 3.3.0</version > <configuration > <nonFilteredFileExtensions > <nonFilteredFileExtension > woff</nonFilteredFileExtension > <nonFilteredFileExtension > woff2</nonFilteredFileExtension > <nonFilteredFileExtension > eot</nonFilteredFileExtension > <nonFilteredFileExtension > ttf</nonFilteredFileExtension > <nonFilteredFileExtension > otf</nonFilteredFileExtension > <nonFilteredFileExtension > svg</nonFilteredFileExtension > </nonFilteredFileExtensions > </configuration > </plugin > </plugins > </build >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <build > <resources > <resource > <directory > src/main/resources</directory > <filtering > false</filtering > <includes > <include > **/*.woff</include > <include > **/*.ttf</include > <include > **/*.woff2</include > <include > **/*.otf</include > <include > **/*.eot</include > <include > **/*.svg</include > </includes > </resource > </resources > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-resources-plugin</artifactId > <version > 3.3.0</version > </plugin > </plugins > </build >
将所有依赖包打包进单个 Jar 包 若 Maven 打包时,需要将项目源码与所有依赖包一起打包在单个 Jar 文件中,可以参考以下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-assembly-plugin</artifactId > <version > 3.0.0</version > <executions > <execution > <phase > package</phase > <goals > <goal > single</goal > </goals > </execution > </executions > <configuration > <descriptorRefs > <descriptorRef > jar-with-dependencies</descriptorRef > </descriptorRefs > </configuration > </plugin > </plugins > </build >
将项目的测试代码打包进 Jar 包 Maven 支持打包的插件列表如下:
plugin function maven-jar-plugin maven 默认打包插件,用来创建 project jar maven-shade-plugin 用来打可执行包,executable (fat) jar maven-assembly-plugin 支持定制化打包方式,例如 apache 项目的打包方式
添加 maven-assembly-plugin 插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-assembly-plugin</artifactId > <version > 3.0.0</version > <executions > <execution > <id > assembly</id > <phase > package</phase > <goals > <goal > single</goal > </goals > <configuration > <descriptors > src/main/resources/assembly.xml</descriptors > </configuration > </execution > </executions > </plugin >
还可以在上面的 configuration
节点中指定执行 Jar 包时的 Test 主类:
1 2 3 4 5 6 7 8 <configuration > <descriptors > src/main/resources/assembly.xml</descriptors > <archive > <manifest > <mainClass > com.sample.TestMain</mainClass > </manifest > </archive > </configuration >
创建 assembly.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 <assembly xmlns ="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd" > <id > assembly</id > <formats > <format > jar</format > </formats > <includeBaseDirectory > false</includeBaseDirectory > <dependencySets > <dependencySet > <outputDirectory > /</outputDirectory > <useProjectArtifact > true</useProjectArtifact > <unpack > true</unpack > <scope > test</scope > </dependencySet > </dependencySets > <fileSets > <fileSet > <directory > ${project.build.directory}/test-classes</directory > <outputDirectory > /</outputDirectory > <includes > <include > **/*.class</include > </includes > <useDefaultExcludes > true</useDefaultExcludes > </fileSet > </fileSets > </assembly >
特别注意: 上面 assembly.xml
里的配置,默认会将所有 Jar 包的源码一起打包(包括依赖的第三方 Jar 包),如果只希望打包项目自身的源码,那么则需要添加 exclude
节点来排除依赖:
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 <assembly xmlns ="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd" > <id > assembly</id > <formats > <format > jar</format > </formats > <includeBaseDirectory > false</includeBaseDirectory > <dependencySets > <dependencySet > <outputDirectory > /</outputDirectory > <useProjectArtifact > true</useProjectArtifact > <unpack > true</unpack > <scope > test</scope > <excludes > <exclude > org.slf4j:slf4j-api</exclude > <exclude > com.fasterxml.jackson.core:*</exclude > <exclude > org.apache.httpcomponents:*</exclude > <exclude > com.google.guava:guava</exclude > </excludes > </dependencySet > </dependencySets > <fileSets > <fileSet > <directory > ${project.build.directory}/test-classes</directory > <outputDirectory > /</outputDirectory > <includes > <include > **/*.class</include > </includes > <useDefaultExcludes > true</useDefaultExcludes > </fileSet > </fileSets > </assembly >
运行以下打包命令,会生成 xxxx-1.0.0-SNAPSHOT-assembly.jar
文件,其中文件名里的 assembly
是由 assembly.xml
配置文件里的 id
节点指定:
Maven 私有仓库配置 通过插件上传 Jar 包到私有仓库 编辑 Maven 的 settings.xml
配置文件,通过添加 server
节点来配置私有仓库的账号和密码,这里的 id
可以随便取名字,但必须与下面配置的 id
一致:
1 2 3 4 5 6 7 8 9 10 11 <server > <id > nexus-releases</id > <username > admin</username > <password > admin123</password > </server > <server > <id > nexus-snapshots</id > <username > admin</username > <password > admin123</password > </server >
编辑 Maven 的 settings.xml
配置文件,通过添加 mirror
节点来配置私有仓库的地址,这里的 id
必须和上面 server
节点的 id
一致:
1 2 3 4 5 6 7 8 9 10 11 12 13 <mirror > <id > nexus-releases</id > <mirrorOf > *</mirrorOf > <name > nexus maven releases repo</name > <url > http://127.0.0.1:8081/nexus/content/repositories/releases/</url > </mirror > <mirror > <id > nexus-snapshots</id > <mirrorOf > *</mirrorOf > <name > nexus maven snapshots repo</name > <url > http://127.0.0.1:8081/nexus/content/repositories/snapshots/</url > </mirror >
编辑项目的 pom.xml
文件,添加以下内容,这里的 id
必须与 上面 mirror
节点里的 id
一致:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <distributionManagement > <repository > <id > nexus-snapshots</id > <name > Nexus Snapshots Repository</name > <url > http://127.0.0.1:8081/nexus/content/repositories/snapshots/</url > </repository > </distributionManagement >
执行发布命令:
Maven 常见问题解决 上传 Jar 包到私有仓库出现 400 错误码 一般有 3 个导致出现上面问题的原因:
一、pom.xml 中仓库 id 配置不对,检查 pom.xml 中配置的 distributionManagement 中的仓库 id、url 和私服 Nexus 中的是否相同 1 2 3 4 5 6 7 <distributionManagement > <repository > <id > nexus-snapshots</id > <name > Nexus Snapshots Repository</name > <url > http://127.0.0.1:8081/nexus/content/repositories/snapshots/</url > </repository > </distributionManagement >
二、私服 Nexus 已经存在相同版本且代码完全一样的 Jar 包,同时部署策略为不允许覆盖;此时只需要将仓库对应的 Deployment Policy
设置为 Allow Redeploy
即可
三、如果 Repository Policy
为 Release,则部署 Jar 包的版本号中不允许出现 snapshot 关键字;特别注意,Repository Policy
有两个选项,一个发布版本,一个是快照版本,要和部署 Jar 包的版本号完全对应
上传 Jar 包到私有仓库出现 401 错误码 一般报 401 这个错误码,是因为没有发布权限,而没发布权限的原因,大部分都是因为密码错了导致,或者账号本身就没有发布 Jar 包的权限。如果是密码错误,则可以编辑 Maven 的 settings.xml
配置文件,通过添加 server
节点来配置私有仓库的账号和密码:
1 2 3 4 5 6 7 8 9 10 11 <server > <id > nexus-releases</id > <username > admin</username > <password > admin123</password > </server > <server > <id > nexus-snapshots</id > <username > admin</username > <password > admin123</password > </server >
如果密码正确,账号本身也具有发布 Jar 包的权限,但依然提示 401 错误,那么此时应该检查当前生效的 settings.xml
配置文件是哪个,查询命令如下:
1 2 3 4 5 $ mvn -X [DEBUG] Reading global settings from /usr/develop/maven-3.6.0/conf/settings.xml [DEBUG] Reading user settings from /root/.m2/settings.xml [DEBUG] Reading global toolchains from /usr/develop/maven-3.6.0/conf/toolchains.xml [DEBUG] Reading user toolchains from /root/.m2/toolchains.xml
如果上面输出的 global settings
指向的配置文件不是所期望的,此时就应该注意了,可以使用以下命令进一步查看正在起作用的那个 settings.xml
的内容:
1 $ mvn help :effective-settings
Nexus 常见问题解决 指定 Nexus 使用的 JDK 版本 Nexus Version Supported Sun/Oracle JRE version 1.9 and earlier 5 or 6 2.0-2.5 6 or 7 2.6.x 7u45+, only 8+ will not work 2.7.x-2.9.x 7u45+, 8+ may work but is not thoroughly tested 2.10.x-2.11.1 7u45+, 8u25+ 2.11.2+ 8u31+ strongly recommended, 7u79+ no further public updates as of April 2015 2.12.0-01 8u31+ strongly recommended, 11.0.9 not work
由于以前安装的 Nexus 版本为 2.12.0-01,JDK 版本为 8,后来 JDK 升级为 11 后,Nexus 无法启动,因此只能指定 Nexus 默认使用 JDK 8,方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ cd nexus/nexus-2.12.0-01/bin/jsw/conf$ cp wrapper.conf wrapper.conf.default$ vim wrapper.confwrapper.java.command =/usr/java/jdk1.8.0_102/bin/java $ service nexus restart$ service nexus status
Maven 实用插件介绍 项目打包与 Git Commit 信息关联插件 Maven 打包发布版本可能会遇到自己的提交不起作用的情况,排查比较困难,可能需要拉下服务器上的 Jar 包,然后反编译查看是否包含自己的提交记录。如果使用的是 Git 作为 SCM,可以使用 git-commit-id-plugin 插件,该插件可以很方便地在项目打包时,将 Git Commit 信息写入 git.properties
文件并存放在 Jar 包中,这样就可以很方便的查看 Jar 包对应的提交记录。
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 <build > <plugins > <plugin > <groupId > io.github.git-commit-id</groupId > <artifactId > git-commit-id-maven-plugin</artifactId > <version > 4.9.9</version > <executions > <execution > <id > get-the-git-infos</id > <goals > <goal > revision</goal > </goals > <phase > initialize</phase > </execution > </executions > <configuration > <failOnNoGitDirectory > false</failOnNoGitDirectory > <generateGitPropertiesFile > true</generateGitPropertiesFile > <dateFormat > yyyy-MM-dd HH:mm:ss</dateFormat > <includeOnlyProperties > <includeOnlyProperty > ^git.build.(time|version)$</includeOnlyProperty > <includeOnlyProperty > ^git.commit.(id|message|time).*$</includeOnlyProperty > </includeOnlyProperties > </configuration > </plugin > </plugins > </build >
Maven 标签使用介绍 两种 Dependency 标签的区别 Maven 提供了 <dependencyManagement>
与 <dependency>
这两种依赖管理标签,其中 <dependencyManagement>
标签用于管理依赖的版本号,通常会在一个组织或者项目的最顶层的父 POM 中看到 <dependencyManagement>
标签。在 pom.xml
中使用 <dependencyManagement>
标签,能够让所有子项目引用一个依赖而不需要显式地声明版本号。Maven 会沿着父子层次向上走,直到找到一个拥有 <dependencyManagement>
标签的项目,然后它就会使用这个 <dependencyManagement>
标签中声明的版本号。
这样做的好处就是:如果有多个子项目都引用了一样的依赖,就可以避免在每个子项目里都声明一个版本号,其优势是:
<dependencyManagement>
只是负责声明依赖,并不是真正的引入,因此子项目仍然需要显式地声明需要使用的依赖。如果不在子项目中声明依赖,那么就不会从父项目中继承下来的,只有在子项目中写了该依赖项并且没有指定具体版本号时,才会从父项目中继承该项依赖,且版本号都读取自父 POM。 如果子项目中指定了依赖的版本号,那么就会使用子项目中指定的 Jar 版本号。