关于Maven找不到依赖或者下载慢的问题总结

概述

Maven和gradle是现在JAVA世界中最普遍的两个依赖管理工具。
即便是使用gradle的人,也难逃maven的折磨。
相信作为一个JAVA开发者,一定会遇到不少Maven相关的错误。
这里总结一下一些maven的使用经验,能解决大部分平时能遇到的棘手问题。

Maven 问题分类

  • HTTPS 协议
  • 网络问题
  • 仓库问题
  • 项目本身的问题
  • IDEA Cannot find symbol xx
  • IDEA Cannot resolve xx 401 Unauthorized
  • 下载慢

访问中央仓库需要用HTTPS协议

2020年01月15日起 Maven中央仓库禁止了HTTP访问,需要修改HTTP为HTTPS才能访问。

Effective January 15, 2020, The Central Repository no longer supports insecure communication over plain HTTP and requires that all requests to the repository are encrypted over HTTPS.

If you're receiving this error, then you need to replace all URL references to Maven Central with their canonical HTTPS counterparts
---出处链接

1.网络问题

找不到jar,无法在某某仓库找到jar,我的思路是这样的。

检查网络问题
以commons-collections为例执行,手动下载

mvn dependency:get -Dartifact=org.apache.commons:commons-collections4:4.4

如果不能下载,则可能是仓库问题, 一般来说 central 的 jar,下载失败,肯定是因为网络问题。

可以检查 settings.xml 中的 proxies 等位置的配置。

2.仓库问题

有些jar不在central

例如:org.apache.hadoop:hadoop-common:2.6.0-cdh5.13.2
mvnrepository 网站会提示:Note: this artifact it located at Cloudera Rel repository (https://repository.cloudera.com/content/repositories/releases/)

仓库地址问题

注:mvnrepository网站关联的 Cloudera Rel仓库地址已经过时

以下位置都可以配置 repository,其中 settings.xml 当中的 profile 可以配置 repository。

  • 项目自己的pom.xml
  • MAVEN_HOME/conf/settings.xml
  • USER_PROFILE/.m2/settings.xml

Cloudera Rel的仓库地址
Cloudera Rel

3.项目本身的问题

能下载jar但是无法下载源码

有一些 jar 开源软件发布的时候,忘记推送 sources。
可以亲临中央仓库去查看,有些jar的某些版本目录内没有源码的压缩包,只有其他的。

尤其是公司自己的项目,经常发布 jar到私服的时候故意或者不小心忘记了源码 jar

例如,项目 hadoop-hdfs:2.9.0 版本就没有 source 包。

点击查看 hadoop-hdfs 的 GAV
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>2.9.0</version>
</dependency>

仓库地址

注:打包源码的 maven 插件是 maven-source-plugin,源码的 classifier=sources

4.IDEA Cannot resolve symbol

IDEA中,某一个依赖的import报红,或者某一个方法报 cannot resolve symbol之类的。

其实是可以用mvn package打包的,就是不能识别。

解决方案:(推荐办法)

点击 Repair IDEA,一步一步点击,跟着IDEA的引导,直到 Everything Works。

解决方案:(传统办法)

  1. 可能的原因有,本地仓库的jar在网络传输中损坏,删除掉重新下载。
  2. 重新下载的方式有 点击右侧刷新reimport,以及手动下载,执行mvn dependency:get -Dartifact=$groupId:$artifactId:$version
  3. 最后一个终极解决办法,无需重新安装IDEA,无需invalid Cache And Restart,直接退出IDEA,删除%USERPROFILE%\.IdeaIC2019.3\system\Maven,重新打开IDEA,IDEA会update maven indices。
  4. 对于IDEA 2020.1.x的版本,位置变成了%APPDATA%\Local\JetBrains\IdeaIC2020.1\Maven
  5. 如果你曾经手动删除过local Repository的某一个文件夹,这个缓存就对不上了,特别容易出现这个问题。

5.IDEA 不能下载 cannot resolve

有一个私服的jar,如果IDEA点击刷新reimport报错:cannot resolve $groupId:$artifactId:$version

解决方案:

  1. 可手动下载mvn dependency:get -Dartifact=$groupId:$artifactId:$version
  2. 如果1不行,则参考上述删除缓存的方案。

401 unauthorzied
要留意IDEA 下载失败的错误提示,如果是401,则检查settings.xml语法是否正常,Server的账户密码是否正确。

6.下载慢

使用镜像服务器

maven镜像服务器,有华为云,腾讯云,阿里云镜像服务器,又快又稳。注意,每个人所在的公司的网络环境可能有所不同,访问阿里云不一定是最快的,或者访问腾讯云不是最快的,甚至很慢。

可以在构建项目的时候多做测试。

下面给出最快的Maven三个镜像服务器

 <!-- 阿里云仓库 -->
    <mirror>
      <id>alimaven</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun-maven</name>
      <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
    </mirror>

    <!-- 中央仓库1 -->
    <mirror>
      <id>repo1</id>
      <mirrorOf>central</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>https://repo1.maven.org/maven2/</url>
    </mirror>

    <!-- 中央仓库2 -->
    <mirror>
      <id>repo2</id>
      <mirrorOf>central</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>https://repo2.maven.org/maven2/</url>
    </mirror>

    <!-- 腾讯云 -->
    <mirror>
      <id>nexus-tencentyun</id>
      <name>Nexus tencentyun</name>
      <url>http://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
    </mirror>

    <!--华为云 -->
    <mirror>
      <id>huaweicloud</id>
      <url>https://mirrors.huaweicloud.com/repository/maven/</url>
    </mirror>

常见的误区

注意,99%的JAR都是在中央仓库的,还有一些在公司的私服,也就是nexus repository,还有一些在第三方开源仓库,例如SpringPlugins:

<dependency>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>jetty</artifactId>
    <version>6.1.26.cloudera.4</version>
</dependency>

Note: this artifact it located at Spring Plugins repository (https://repo.spring.io/plugins-release/)
因此镜像服务器不要上来就配mirrorOf *, 这个表示所有的jar都从这里下载,这肯定是不行的。

<mirror>
   <id>alimaven</id>
   <mirrorOf>*</mirrorOf>
   <name>aliyun-maven</name>
   <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>

正确做法是

<mirrorOf>external:*</mirrorOf>

或者是

<mirrorOf>central</mirrorOf>

external表示URL是127.0.0.1或者localhost以外的
参见 maven-3.3.9 external的源码

另外,对于公司自己的私服,最好在 mirrorOf里面排除的,假设私服的 id 是 snaps,推荐在mirror中的写法:

 <mirrorOf>external:*,!snaps</mirrorOf>

总结

对于某一个找不到jar的依赖,应该养成习惯。

  • 第一时间检查这个artifact是不是在maven中央仓库,是不是在某一个第三方仓库。如果在某一个第三方仓库,则把它加入到自己的pom.xml中,或者上述其他位置的settings.xml。除此以外,还可以将这个仓库加入自己私服的PROXY代理中。
  • 如果在第三方仓库,仍需检查网络是否连通。

2023年补充

随着时间的推移,公司被收购,企业被关停,网站无法访问,某些库的jar 原始仓库已经不存在了
举例说明:ehcache,它来源于 terracotta,而他的仓库估计早就关停了。

maven会扫描所有jar里面的pom,还会扫描里面的仓库,某些仓库可能还在配置文件里,Maven会花时间去连接。

查看ehcache-2.10.6.pom 可以看到:

 <repositories>
    <repository>
      <id>terracotta-snapshots</id>
      <url>http://www.terracotta.org/download/reflector/snapshots</url>
    </repository>
    <repository>
      <id>terracotta-releases</id>
      <url>http://www.terracotta.org/download/reflector/releases</url>
    </repository>
  </repositories>

如果访问可能会出现

<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>maven2</Key>
<RequestId>92K9HAKHCB9XSBMP</RequestId>
<HostId>lZnkzKKy9r4vY5yt/y+zK5auzIG46OMdINEVOuyD5x4Hw7xkfgBWUKbO01m8+N87Z4O234OwKEI=</HostId>
</Error>

因此,如果做到极致,可以这样:

    <mirror>
      <id>maven-repo-blocker</id>
      <mirrorOf>terracotta-snapshots,terracotta-releases</mirrorOf>
      <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
      <url>http://0.0.0.0/</url>
      <blocked>true</blocked>
    </mirror>
posted @ 2020-01-16 18:14  一杯半盏  阅读(6992)  评论(0编辑  收藏  举报