我想分享我通过代理使用 maven 的经验。
您很可能会遇到异常和消息,例如:
repository metadata for: 'org.apache.maven.plugins' could not be retrieved from repository: central due to an error: Error transferring file: Connection refused: connect
或者
[WARNING] Failed to retrieve plugin descriptor for org.apache.maven.plugins:maven-clean- plugin:2.5: Plugin org.apache.maven.plugins:maven-clean-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-clean-plugin:jar:2.5
如何配置 Maven 以使用代理服务器?
有关为 Maven 设置代理的详细信息,请参阅mini guide。
本质上,您需要确保正确配置全局设置 ([maven install]/conf/settings.xml
) 或用户设置 (${user.home}/.m2/settings.xml
) 中的代理部分。最好在您的用户设置中执行此操作,以避免将密码以纯文本形式存储在公共位置。
Maven 2.1 引入了 password encryption,但我还没有检查加密是否适用于代理设置以及存储库密码(但不明白为什么不适用)。
有关信息,您的 settings.xml 中有一个已注释掉的代理配置以及有关如何修改它的说明。
在迷你指南中,您的设置应如下所示:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
[...]
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>proxy.somewhere.com</host>
<port>8080</port>
<username>proxyuser</username>
<password>somepassword</password>
<nonProxyHosts>www.google.com|*.somewhere.com</nonProxyHosts>
</proxy>
</proxies>
[...]
</settings>
在某处设置到服务器的 SSH 隧道:
ssh -D $PORT $USER@$SERVER
Linux(bash):
export MAVEN_OPTS="-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=$PORT"
视窗:
set MAVEN_OPTS="-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=$PORT"
MAVEN_OPTS
使用 socks 代理是让 Maven 通过 HTTPS 下载的唯一方法。通过 MAVEN_OPTS
或 settings.xml
使用 HTTP 或 HTTPS 代理会导致 org.apache.maven.wagon.providers.http.httpclient.impl.execchain.RetryExec execute INFO: I/O exception (java.net.SocketException) caught when processing request to {tls}->http://proxy.mycompany.com:911->https://repo.maven.apache.org:443: SOCKS: TTL expired
http
代理:export MAVEN_OPTS="-DproxyHost=127.0.0.1 -DproxyPort=$PORT"
MAVEN_OPTS="-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080" mvn clean install
同一会话中的下一个 mvn
命令将没有任何代理。
另请注意,某些插件(想到远程资源)使用了一个非常旧的库,该库仅通过 MAVEN_OPTS 接受代理配置;
-Dhttp.proxyHost=<host> -Dhttp.proxyPort=<port> -Dhttps.proxyHost=<host> -Dhttps.proxyPort=<port>
你可能会被困在这个身份验证上。
我也遇到了这个问题,我通过编辑 .m2
文件夹中的 settings.xml
文件解决了这个问题。我的 settings.xml
现在是这样的:
<settings>
<proxies>
<proxy>
<id>genproxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxyHost</host>
<port>3128</port>
<username>username</username>
<password>password</password>
</proxy>
</proxies>
</settings>
设置 Maven 代理:
在 ~/.m2/settings.xml 文件中编辑代理会话。如果找不到文件,请创建一个。
<settings>
<proxies>
<proxy>
<id>httpproxy</id>
<active>true</active>
<protocol>http</protocol>
<host>your-proxy-host</host>
<port>your-proxy-port</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
<proxy>
<id>httpsproxy</id>
<active>true</active>
<protocol>https</protocol>
<host>your-proxy-host</host>
<port>your-proxy-port</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
</proxies>
</settings>
或者
在您的 {M2_HOME}/conf/settings.xml 中编辑代理会话
这些很可能是由两个问题引起的:
您需要将代理配置添加到您的 settings.xml。这是您的用户名字段中的一个技巧。确保它看起来像域\用户名。在那里设置域并放置这个精确的斜线很重要'\'。如果您的密码包含非 xml 友好字符,您可能需要使用 标记。我注意到 maven 2.2.0 有时根本无法通过代理工作,而 2.2.1 工作得非常好。
如果其中一些被省略 - maven 可能会因随机错误消息而失败。
只是希望我能像我一样避免有人在这个问题上搜索 6 个小时。
只是添加我自己的经验:我公司的代理是 http://webproxy.intra.companyname.com:3128
。为了让 maven 通过这个代理工作,设置必须像这样完全
<settings>
<proxies>
<proxy>
<id>default</id>
<active>true</active>
<protocol>http</protocol>
<host>webproxy.intra.companyname.com</host>
<port>3128</port>
</proxy>
</proxies>
</settings>
与其他一些代理配置文件不同,这里的 protocol
描述了如何连接到代理服务器,而不是应该代理哪种协议。目标的 http
部分必须从主机名中分离出来,否则它将不起作用。
谢谢@krosenvold。
如果设置文件更改不起作用,请在具有 POM 文件的命令提示符下尝试此操作。
mvn install -Dhttp.proxyHost=abcproxy -Dhttp.proxyPort=8080 -Dhttps.proxyHost=abcproxy -Dhttps.proxyPort=8080
这在更改密码后立即帮助了我。
我在本地运行 cntlm
,配置了 NTLMv2
密码哈希以通过公司代理进行身份验证,并使用
export MAVEN_OPTS="-DproxyHost=127.0.0.1 -DproxyPort=3128"
使用来自 maven
的代理。当然,您使用的代理应该支持 cntlm
/NTLMv2
。
[Environment]::SetEnvironmentVariable("MAVEN_OPTS", "-DproxyHost=127.0.0.1 -DproxyPort=3128", "Machine")
为了补充这个话题,下面是我的经验......真的很奇怪而且很耗时,所以我认为值得添加。
我在尝试在 Windows 上构建 portlet-bridge 时遇到了类似的问题,出现以下错误:
Downloading: http://repo1.maven.org/maven2/org/apache/portals/bridges-pom/1.0/bridges-pom-1.0.pom [DEBUG] Reading resolution tracking file C:\Documents and Settings\myuser\.m2\repository\org\apache\portals\bridges-pom\1.0\bridges-pom-1.0.pom.lastUpdated [DEBUG] Writing resolution tracking file C:\Documents and Settings\myuser\.m2\repository\org\apache\portals\bridges-pom\1.0\bridges-pom-1.0.pom.lastUpdated [ERROR] The build could not read 1 project -> [Help 1] org.apache.maven.project.ProjectBuildingException: Some problems were encountered while processing the POMs: [FATAL] Non-resolvable parent POM: Could not transfer artifact org.apache.portals:bridges-pom:pom:1.0 from/to central (http://repo1.maven.org/maven2): Error transferring file: repo1.maven.org and 'parent.relativePath' points at wrong local POM @ line 23, column 11 ... [ERROR] The project org.apache.portals.bridges:portals-bridges-common:2.0 (H:\path_to_project\portals-bridges-common-2.0\pom.xml) has 1 error [ERROR] Non-resolvable parent POM: Could not transfer artifact org.apache.portals:bridges-pom:pom:1.0 from/to central (http://repo1.maven.org/maven2): Error transferring file: repo1.maven.org and 'parent.relativePath' points at wrong local POM @ line 23, column 11: Unknown host repo1.maven.org -> [Help 2] ... [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException [ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
在网上冲浪之后,我尝试了几件事:
试图将 parent.relativePath 设置为空,以便 maven 认为父级不是本地的。这是根据 Hudson build fail: Non-resolvable parent POM 和这个 nabble 论坛中关于 SO 的建议。这没有效果。
我还尝试确保在我的 settings.xml 中明确列出了存储库,但这也没有效果。
然后我确保 mvn 被迫查找存储库,而不是依赖它自己的历史记录,正如 Sarthon 在这篇博客中所讨论的那样。不幸的是,这也不是问题。
在绝望中,我重新访问了我的 MAVEN_OPTS 以确保我没有违反我的代理设置。这些都是正确的,尽管值未引用: set MAVEN_OPTS= -Dhttp.proxyHost=myproxy.mycompany.com -Dhttp.proxyPort=8080 -Xmx256m
所以,最后,我将代理配置移动到我的 settings.xml 中,这很有效:
<proxies>
<proxy>
<id>genproxy</id>
<active>true</active>
<protocol>http</protocol>
<!--username>proxyuser</username-->
<!--password>proxypass</password-->
<host>myproxy.mycompany.com</host>
<port>8080</port>
<nonProxyHosts>*.mycompany.com|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>
真的不知道为什么我原来的 MAVEN_OPTS 不工作(引号?)而 settings.xml 配置确实有效。我想撤消修复并再次检查每个步骤,但浪费了太多时间。将在何时报告。
我知道这并不是问题的真正答案,但对于搜索这篇文章的人来说可能值得知道。也可以安装像 nexus 这样的 Maven 存储库代理。
您的 Maven 将被配置为联系本地 Nexus 代理,然后 Nexus 将检索(并缓存)工件。它可以通过 Web 界面进行配置,并支持(http)代理)。
这可能是一个优势,尤其是在公司环境中,因为人工制品在本地可用并且可以快速下载,并且您不再依赖外部 Maven 存储库的可用性。
链接回问题; Nexus 有一个很好的代理配置 GUI,它只需要在一个地方完成,而不是为每个开发人员。
如果您是 Maven 代理设置的新手在我的情况下,首先去检查您的主文件夹天气有 .m2
文件夹,如果没有创建它,其中应该有一个名为 settings.xml
的文件,然后粘贴并更改 {3 } 和 port
,然后根据需要更改 nonProxyHosts
主文件夹 - C:\Users\ {用户名}
<settings>
<proxies>
<proxy>
<id>httpproxy</id>
<active>true</active>
<protocol>http</protocol>
<host>your-proxy-host</host>
<port>your-proxy-port</port>
<nonProxyHosts>localhost</nonProxyHosts>
</proxy>
<proxy>
<id>httpsproxy</id>
<active>true</active>
<protocol>https</protocol>
<host>your-proxy-host</host>
<port>your-proxy-port</port>
<nonProxyHosts>localhost</nonProxyHosts>
</proxy>
</proxies>
</settings>
如果任何情况下这不成功,请在主文件夹的这个位置进行更改
/conf/settings.xml
我正在使用 Eclipse 作为我的 IDE 希望这会有所帮助!
注意:要删除代理,只需将 settings.xml
移动到其他位置
如果 maven 通过代理而不是它正在调用的某些插件工作,请尝试设置 JAVA_TOOL_OPTIONS
以及 -Dhttp*.proxy*
设置。
如果您已经有 JAVA_OPTS
,请执行
export JAVA_TOOL_OPTIONS=$JAVA_OPTS
Maven 通过一个名为 settings.xml 的文件提供了一种内置方法来执行此操作,其他答案中已对此进行了介绍。但是,习惯上,尤其是在 Linux 中,命令行工具会自动使用环境变量 https_proxy
指定的代理。
要遵循 Don't repeat yourself principle(旨在帮助您避免错误),如果 mvn
也能自动使用它会很好。
这是一个进行必要转换的 shell 脚本:
#! /usr/bin/env bash
function javaproxy {
## using "Shell Parameter Expansion"
request_scheme=$1 ; proxy=$2
notscheme=$(echo ${proxy#*://}) ## parse
scheme=$(echo ${proxy%${notscheme}}) ## remove
scheme=$(echo ${scheme%://}) ## strip
hostport=$(echo ${proxy#*//*}) ## parse
host=$(echo ${hostport%:*}) ## parse
port=$(echo ${hostport#${host}}) ## remove
port=$(echo ${port#:}) ## strip
scheme=$(echo ${scheme:-http}) ## default
host=$(echo ${host:-localhost}) ## default
port=$(echo ${port:-8080}) ## default
echo -n " -D${request_scheme}.proxyHost=${host}"
echo -n " -D${request_scheme}.proxyPort=${port}"
}
JTO=""
if [ $http_proxy ] ; then
JTO="${JTO}$(javaproxy http ${http_proxy})"
fi
if [ $https_proxy ] ; then
JTO="${JTO}$(javaproxy https ${https_proxy})"
fi
if [ $no_proxy ] ; then
JTO="${JTO} -Dhttp.nonProxyHosts=$(echo \"${no_proxy}\"|tr ',' '|')"
fi
export JAVA_TOOL_OPTIONS=${JTO}
echo "JAVA_TOOL_OPTIONS=${JAVA_TOOL_OPTIONS}"
mvn_friendliness_options+=--update-snapshots
mvn ${mvn_friendliness_options} $@
您可以将其命名为 proxied_mvn
并将其运行为:
$ https_proxy=http://localhost:58080 ./proxied_mvn clean package
或者,您可以将环境设置移动到您的启动脚本中。
陷阱
尝试将 Maven 配置为通过代理访问 Nexus 时,可能会出现许多问题。希望这个脚本能帮助解决一些最挑剔的问题,但其他问题仍然存在:
Nexus 凭据可用且正确(仅在需要时)检查 mvn help:effective-settings
Maven 缓存:“不会重新尝试解析” mvn clean package --update-snapshots
Maven 文本墙输出——您必须仔细查看输出以确保错误消息在运行之间没有细微差别
旧版本的 Java 可能需要 _JAVA_OPTIONS 而不是 JAVA_TOOL_OPTIONS。
结语
Proxy 不止一种。相应地,这个问题的解释方式不止一种——导致这里出现大量不同的答案。
我已经明确解决了(转发 HTTP/HTTPS)web proxy server 的情况,它用于从公司网络(对于某些公司)访问互联网。这可能与 SOCKS proxy 明显不同,这也已在此处的一些答案中得到解决。
哦对了,因为它使用了JAVA_TOOL_OPTIONS
,所以这个解决方案也可以应用于running your other Java applications inside a proxy。
分离提示...我上面的示例使用 http://localhost:58080
。这是因为我设置了从我的 CLIENT_PROXY=localhost:58080
到实际网络代理的端口转发,方法是在我的 remote-access 客户端上使用 WSL 来运行:
ssh $PROXY_CLIENT -R $CLIENT_PROXY:$SERVER_PROXY
除了上面提到的技术,通过一些努力,您可以使用 jproxyloader 库通过代理运行 maven(页面上有如何执行此操作的示例:http://jproxyloader.sourceforge.net/)。这允许只为下载工件设置 socks 代理。
在 duanni (设置 -DsocksProxyHost) 提到的解决方案中,存在一个问题。如果您有针对本地数据库运行的集成测试(或其他不应通过代理连接到 url 的测试)。这些测试将停止工作,因为与数据库的连接也将被定向到代理。在 jProxyLoader 的帮助下,您可以仅为 nexus 主机设置代理。此外,如果您愿意,您可以通过另一个代理将连接传递到数据库。
有时您需要添加其他 <proxy></proxy>
标记,并在协议标记中指定 https:<protocol>https</protocol>
上面的帖子帮助解决了我的问题。除了上述内容之外,我还必须进行以下更改才能使其正常工作:
修改了 Maven 的 JRE 网络设置(\jre\lib\net.properties)以使用系统代理设置。 https.proxyHost=代理 DNS https.proxyPort=代理端口
在 settings.xml 中包含代理服务器设置。我没有提供用户名和密码设置来使用 NTLM 身份验证。
<username>
和<password>
元素(并且不提供空内容)。这花了我一段时间才弄清楚。