IDEA+MAVEN:踩坑指南
个人感觉很多网上的Maven教程都容易忽略一些基础操作,所以也准备把网上一些容易一笔带过的地方详细写一写。
0. 为什么要用 Maven ?
这个问题绝大多数教材和教程都会写,但是恐怕对于大多数初学者来说 Maven 带来的麻烦还要多于便利。尤其是写算法题的经验让大家都习惯了直接 import 完事的良好体验,就算要用第三方的包从 IDEA 里点两下鼠标就解决了,额外去写一个 pom,还要考虑各种名称、版本号实属多此一举。
真正让我意识到 Maven 便利性的是一次处理 json 文件的经历。因为要将一堆字符串导出为一个 json 文档,所以当时用了 json-lib 这个包。下载下来 import 进去结果用不了,编译不通过,马上意识到是依赖包的问题,结果查了一下发现…有 6 个依赖包!但是头铁的我还是不用 Maven,决定自己下载这 6 个包,结果下载下来还是不行,气急败坏。最后发现是版本问题,json-lib 依赖包的版本不是最新版本,需要把这 6 个包都找到对应版本才可以。到此,再头铁也得承认 Maven 对于这种情况有着莫大的帮助,毕竟只需要简单添加一个依赖(甚至都不需要手动下载),就可以解决上面所有的问题。
更重要的是,学习 Java 框架基本上都依赖于 Maven,不管是 SSM 还是简单的 Junit,没有 Maven 的话都会很繁琐,所以不论从哪个方面来讲 Maven 都是必经之路。
1. Maven 安装
首先,IDEA是内置有Maven的,一般来讲可以直接使用,如果要额外安装的话也没有问题,从官方网站( https://maven.apache.org/ )下载即可。具体安装方式和环境变量配置可以直接搜索“Maven 安装”,一般都会有详细的教程。
如果额外安装了 Maven,那么在 IDEA 创建 Maven 项目时可以选择任意一个进行创建:
这里额外说一下版本的问题。我在使用过程中碰到的一个问题是 Maven 报错无法导入:
首先介绍一下 IDEA 怎么打开 log。点击菜单栏“Help”—“Show Log in Explorer”会打开一个“log”文件夹,再打开“idea.log”文件即可:
之后可以在 log 文档中看到具体的错误信息。
在这个问题中我们可以在 log 中找到下列信息:
1.No implementation for org.apache.maven.model.path.PathTranslator was bound.
whilelocatingorg.apache.maven.model.path.PathTranslatorforfieldatorg.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator.pathTranslator(UnknownSource)atorg.codehaus.plexus.DefaultPlexusContainer$1.configure(DefaultPlexusContainer.java:350)
2.No implementation for org.apache.maven.model.path.UrlNormalizer was bound.
while locating org.apache.maven.model.path.UrlNormalizer
forfieldatorg.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator.urlNormalizer(UnknownSource)atorg.codehaus.plexus.DefaultPlexusContainer$1.configure(DefaultPlexusContainer.java:350)
2 errors
java.lang.RuntimeException: com.google.inject.CreationException: Unable to create injector, see the following errors:
- No implementation for org.apache.maven.model.path.PathTranslator was bound.while locating org.apache.maven.model.path.PathTranslatorfor field at org.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator.pathTranslator(UnknownSource)atorg.codehaus.plexus.DefaultPlexusContainer$1.configure(DefaultPlexusContainer.java:350)
2.No implementation for org.apache.maven.model.path.UrlNormalizer was bound.
whilelocatingorg.apache.maven.model.path.UrlNormalizerforfieldatorg.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator.urlNormalizer(UnknownSource)atorg.codehaus.plexus.DefaultPlexusContainer$1.configure(DefaultPlexusContainer.java:350)
这个问题主要是 IDEA 和 Maven 版本冲突带来的。Maven 从 3.6.2 版本开始不再使用 Plexus 而是使用 JSP 330 注释,而 IDEA 与之出现了兼容性问题。主要有两个解决方式:
使用早期的 Maven。3.6.1 及以前的版本均可。
升级到最新的 IDEA。从 IDEA 2019.2.3 版本开始这一问题得到了修复,可以正常使用。
2. Maven 创建项目
直接从 IDEA 当中创建 Maven 项目相当的方便,在新建项目页面中选择 Maven 即可,同时,勾选“Create from archetype”即可自动使用模板:
之后的步骤十分简单,需要注意的是,创建过程中常会出现下面这个问题,即出现“Generating project in Batch mode”信息然后一直没有反应:
这个问题一般是因为创建项目时需要从网络上下载一个 archetype-catalog.xml 文件,如果网络情况不理想很容易卡在这一步。这一问题可以通过调整 archetypeCatalog 参数来解决。这一参数可以为 internal,local,remote:
internal:读取maven-archetype-plugin内置的 archetype-catalog.xml 文件;
local:读取本地文件,位置为~/.m2/archetype-catalog.xml;
remote:默认,指向Maven中央仓库的Catalog。
因此,一个简单的方法就是在创建过程中点击“Properties”最右侧的加号,加入 archetypeCatalog=internal 这一项:
这样一般创建过程就不会有问题了。
3. Maven 使用
在我刚刚开始学习 Maven 的时候,其实对它的功能是很懵懂的。当时我的第一反应是,既然 Maven 是进行包管理的,那是不是不用写 import 了?答案当然是否定的,该写还是得写,但这并不妨碍 Maven 主要用于包管理这个事实。Maven 最主要的功能在于自动化地解决依赖问题,也就是说只要你写清楚你需要什么包,那么 Maven 可以自动把这个包准备好,同时也会把所有的依赖包准备好,而不需要自己手动下载再一个一个添加。
但遇到的下一个问题就是在 pom 文件中添加了依赖,可是并没有什么反应,IDEA 反而会把它标红。这是因为对应的包在本地仓内找不到,而为了充分发挥 Maven 自动化的优势,避免手动下载,我们需要调整 IDEA 的设置,依次点击“File”—“Settings”,之后在 Maven 选项卡中找到“Importing”一项,勾选“Import Maven projects automatically”即可:
这样,使用过程就变得异常简单,找到需要的包的相关信息(建议直接从 Maven 仓库中复制),把依赖项添加进 pom,之后稍等片刻就会发现字体颜色自动变成了正常,而查看本地仓就会发现相应的包已经被下载了下来,也可以直接在项目中使用了。
那么这里顺便展开一下 Maven 本地仓库的路径问题。一般来讲,本地仓库的地址默认为${user.home}/.m2/repository,这个 user.home 在 Windows 下一般就是 C 盘 Users 文件夹中以自己登录的那个用户名命名的文件夹。那么在这个文件夹下 jar 包是怎么存储的呢?下面是一个例子:
// pom 文件中的dependency
org.junit.jupiter
junit-jupiter-api
5.6.0
test
// 实际地址
c:\Users\MyName.m2\repository\org\junit\jupiter\junit-jupiter-api\5.6.0\junit-jupiter-api-5.6.0.jar
可以看到,从 Maven 的 dependency 标签内容到实际地址主要依据下列转化步骤:
处理 groupId,每一个 . 转化为一级文件夹。比如‘org.junit.jupiter’,就是首先在repository 文件夹下创建一个 org 文件夹(已有的话不用创建),然后在 org 文件夹下创建 junit 文件夹,在 junit 文件夹下创建 jupiter 文件夹;
再下一级创建以 artifactId 命名的文件夹,即在 jupiter 文件夹下创建 junit-jupiter-api 文件夹;
创建版本号文件夹;
把 artifactId 和 version 用连字符连接(如果有 classifier 也要连接),然后加上扩展名,就是实际文件的地址。
显然,整个过程相当繁琐,而且但凡一步出错那么 Maven 就无法读取这个依赖。所以,尽管可以通过手工方式将依赖下载到本地仓库再添加到 pom 文件中,但除非情况特殊,否则非常非常非常不推荐这种做法,还是推荐使用 IDEA 自动导入依赖。