背景:
周五同事和我探讨一个话题,他在我们搭建的nexus仓库中搜到的slf4j版本是3.1(打个比方),位于代理的Central Repository,但是他需要的版本是3.2(打个比方), 但是此nexus中没有slf4j的3.2版本,但是当他点击进Central Repository并且选择browse Remote Index时候,却看到有3.2版本(和其他版本)的构件,为什么呢?
原因分析:
经过分析,我找到了原因,原来搜索仓库和点击某仓库选择browse Remote Index走的是不一样的机制。
对于仓库搜索,其等效于仓库查询:
其调用的请求是:http://localhost:8081/nexus/service/local/repositories?_dc=1416624550968 ,这个请求的响应入口在${bundleBaseDir}/nexus/WEB-INF/plugin-repository/nexus-restlet1x-plugin-2.10.0-02目录下的nexus-restlet1x-plugin-2.10.0-02.jar包中的RepositoryListPlexusResource类的get()方法:
其中listRepositories()方法定义在父类AbstractRepositoryPlexusResource中,它用于构造响应json payload.构造完响应对象就是每个被nexus代理的repository类的详细信息,为了突出重点,我这里只贴了一部分(比如代理的central repository的信息):
从这里看出,请求查看的配置URI是http://localhost:8081/nexus/service/local/repositories/central,它打开后是一个XML格式的仓库配置文件。而仓库中缓存的中央仓库的内容则可以通过contentResourceURI来访问。缓存的内容存储在nexus所在文件系统的effectiveLocalStorageUrl (即${bundleBasedir}/../sonatype-work /nexus/storage/{repositoryId}),缓存的内容所代理的真正远程仓库地址配置在remoteUri中。而我们知道,只有maven应用配置了指向本地仓库,当使用某构件时候,nexus发现自己没有,这才会从中央仓库下载指定的构件并且存储在storage子目录下。否则,它是绝对不会主动从远程仓库吧这些构件都下载到本地的(这个很容易想,因为代理的仓库都非常巨大,涉及构件多个版本,你总不能把自己搭的服务器去和真正远程仓库去比把,存储的数量级也不一样)。
实验也证实了我们这一点,比如刚安装的这个干净的nexus, 这个${bundleBasedir}/../sonatype-work /nexus/storage/{repositoryId})里面是没有具体的构件的,只有一个archetype-catalog.xml:
干净的nexus local 存储截图如下(以代理的repositoryId=central 为例):
这个archetype-catalog.xml只用于标示此仓库中构件的目录。
所以,我们相信,如果在nexus仓库中搜到了slf4j版本是3.1的构件,那么肯定我们有某个项目的<dependency>或者间接<dependency>中用到了这个构件,因此同事在构件仓库搜索中是搜到了这个构件的。但是因为从来没任何的项目用到slf4j版本是3.2的构件,所以构件仓库搜索中搜不到。
关于某仓库的“Browse Remote ”:
从web 客户端工具可以看出,它实际请求的URL是:
这个请求会被位于${bundleBaseDir}\nexus\WEB-INF\plugin-repository\nexus-rrb-plugin-2.10.0-02目录下的nexus-rrb-plugin-2.10.0-02中的RemoteBrowserResource类的get()方法所响应。
在get方法中,它会先获取repositoryId(比如我们例子中的id=central),接着调用getResourceStoreRequest(request)方法来获取remote的列表,它其中会调用getValidRemoteIPAddress(request))方法来获取真正要访问的远程IP地址,比如我们的central就是访问前面多次提到的repo1.maven.org。 所以这一步必需要联网,否则无法解析出repo1.maven.org. 比如我做了个实验,我故意吧网络断开,则当点击”Browse Remote”并刷新时,就无法显示结果:
所以我们相信,当我们点击central repository并且查看“browse remote"时候,在联网的情况下,他总能找到这个构件(比如例子中版本是3.2的 slf4j),因为你搜索的是中央仓库。
总结:
(1)对于在仓库浏览器中浏览或者搜索构件,其搜索的是存在nexus服务器本地${bundleBasedir}/../sonatype-work /nexus/storage目录下的构件,如果找不到就找不到了。这些构件当maven应用配置指向nexus地址,并且nexus在自己层面找不到构件,才从相应的所代理的远程仓库中下载构件,并且存入storage目录。
(2)对于点击某仓库,查看其"browse remote",则只要网络通,就总能看到某版本构件,因为你直接查看了远程仓库的构件索引。