[TOC] ## 一、应用场景 有些公司都不提供外网给项目组人员,因此就不能使用maven访问远程的仓库地址,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库。 如果某个IP地址恶意的下载中央仓库内容,例如全公司100台机器使用同一个IP反复下载,这个IP(甚至是IP段)会进入黑名单,因此稍有规模的使用Maven时,应该用Nexus架设私服。总归主要是两点: 1. 自己maven私服更容易维护,公司开发从maven私服迁出jar到本地仓库更快 2. 有些公司未开放外网给开发人员 ### respository介绍 * **proxy**:是远程仓库的代理。比如说在nexus中配置了一个central repository的proxy,当用户向这个proxy请求一个artifact,这个proxy就会先在本地查找,如果找不到的话,就会从远程仓库下载,然后返回给用户,相当于起到一个中转的作用; * **Hosted**:是宿主仓库,用户可以把自己的一些构件,deploy到hosted中,也可以手工上传构件到hosted里。比如说oracle的驱动程序,ojdbc6.jar,在central repository是获取不到的,就需要手工上传到hosted里; * **Group**:是仓库组,在maven里没有这个概念,是nexus特有的。目的是将上述多个仓库聚合,对用户暴露统一的地址,这样用户就不需要在pom中配置多个地址,只要统一配置group的地址就可以了右边那个Repository Path可以点击进去,看到仓库中artifact列表。不过要注意浏览器缓存。 ## 二. 下载镜像 ~~~ docker pull sonatype/nexus3 ~~~ ## 三. 创建数据目录 ~~~ mkdir -vp /opt/nexus/nexus-data && chown -R 200 /opt/nexus/nexus-data ~~~ ## 四. 启动容器 ~~~ docker run -d -p 8081:8081 --name nexus --restart=always -v /opt/nexus/nexus-data:/nexus-data sonatype/nexus3 ~~~ ## 五、访问 [http://ip:8081](http://ip:8081/) > 默认用户名/密码: admin/admin123 ## 六、创建一个用户 点击Security>Users 创建一个用户,我这里测试创建的用户/密码是:test/test,因为后面提交本地项目jar到私服仓库会用到 ## 七、创建一个maven仓库 设置>Repository>Repositories>Create repository>maven2(hosted)创建maven项目 ![](https://img.kancloud.cn/5a/74/5a748ad1fd20784a5975ba5ab9c9fba4_2387x1170.png) >[info] 注意Deployment policy一定要设置成allow redeploy ## 八、maven项目提交jar到maven私服 ### 1\. 配置私服仓库的账号 设本地maven的settings.xml配置,在servers标签里添加用户密码支持 ~~~ <server> <id>releases</id> <username>test</username> <password>test</password> </server> <server> <id>snapshots</id> <username>test</username> <password>test</password> </server> ~~~ ### 2\. 配置发布的私服仓库地址 在项目的pom.xml中添加远程发布的私服仓库地址 ~~~ <distributionManagement> <repository> <id>releases</id> <name>releases Repository</name> <url>http://192.168.28.138:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>snapshots</id> <url>http://192.168.28.138:8081/repository/maven-snapshots/</url> <uniqueVersion>true</uniqueVersion> </snapshotRepository> </distributionManagement> ~~~ > 必需保证server的id与构建项目的pom.xml中的repository的id一致 ### 3\. 批量提交jar包 ~~~ mvn clean deploy ~~~ > maven会根据模块的版本号(pom文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本。**如果是快照版本,那么在mvn deploy时会自动发布到快照版本库中,会覆盖老的快照版本,而在使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。如果是正式发布版本,那么在mvn deploy时会自动发布到正式版本库中,而使用正式版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载**。 ### 4\. 提交某个jar 命令格式如下: ~~~ mvn deploy:deploy-file -DgroupId=groupId -DartifactId=artifactId -Dversion=version -Dfile=本地jar包路径 -DrepositoryId=releases/snapshots -Durl=仓库地址 ~~~ * 提交到releases的例子 ~~~ mvn deploy:deploy-file -DgroupId=net.dopan.pigframe -DartifactId=auth-core -Dversion=1.0.0 -Dpackaging=jar -Dfile=auth-core.jar -Durl=http://192.168.28.138:8081/repository/maven-releases/ -DrepositoryId=releases ~~~ * 提交到snapshots的例子 ~~~ mvn deploy:deploy-file -DgroupId=net.dopan.pigframe -DartifactId=auth-core -Dversion=1.0.0-SNAPSHOT -Dpackaging=jar -Dfile=auth-core.jar -Durl=http://192.168.28.138:8081/repository/maven-snapshots/ -DrepositoryId=snapshots ~~~ ### 5\.指定maven地址下载jar包到本地 在项目的pom.xml中添加上远程仓库地址 ~~~ <repositories> <repository> <id>public</id> <name>public</name> <releases> <enabled>true</enabled> <updatePolicy>always</updatePolicy> <checksumPolicy>warn</checksumPolicy> </releases> <snapshots> <enabled>true</enabled> </snapshots> <url>http://192.168.28.138:8081/repository/maven-public/</url> </repository> </repositories> ~~~ ## 九、gradle项目提交jar到maven私服 ### 1.在根项目`build.gradle`添加 ~~~ apply plugin: 'maven-publish' version = '1.0.0-SNAPSHOT' ext { // 注意不同环境的项目version不一样 发布到SNAPSHOT仓库必须用1.0.0-SNAPSHOT格式 // 开发测试环境SNAPSHOT仓库 companyMavenRepo = 'http://192.168.28.138:8081/nexus/content/repositories/snapshots/' // 正式环境jar仓库 //companyMavenRepo = 'http://192.168.28.138:8081/nexus/content/repositories/thirdparty/' companyMavenRepoUsername = 'admin' companyMavenRepoPassword = 'admin123' } configurations.all { // check for updates every build resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } ~~~ ### 2.子项目`build.gradle`添加 ~~~ task sourceJar(type: Jar) { from sourceSets.main.allJava } publishing { publications { maven(MavenPublication) { //指定group/artifact/version信息,可以不填。默认使用项目group/name/version作为groupId/artifactId/version groupId "${project.group}" artifactId project.archivesBaseName //version project.version //如果是war包填写components.web,如果是jar包填写components.java from components.java //配置上传源码 artifact sourceJar { classifier "sources" } } } repositories { maven { //指定要上传的maven私服仓库 url = "${companyMavenRepo}" //认证用户和密码 credentials { username "${companyMavenRepoUsername}" password "${companyMavenRepoPassword}" } } } } ~~~ ### 3.执行命令publish就可以发布到仓库 ![](https://img.kancloud.cn/00/e1/00e1e0d81d5d5e1c5c4a3f5ef098ac90_375x364.png) ![](https://img.kancloud.cn/4a/f6/4af63ad46be61147179f5f77edf10672_1469x331.png) ### 4.gradle更新snapshot的jar 通常,gradle下载引用的jar文件的话,会缓存到本地,不会重复去下载。 但是,我们引用的是snapshot的jar,这种jar文件一般是其他项目组的代码,这种jar一般都进行迭代开发,会重复更新上传到nexus代码仓库中,我们必须在每次启动的时候能更新最新依赖的jar。 ~~~ version = '1.0.0-SNAPSHOT' ~~~ 所以,必须在build.gradle中配置。 默认是24小时,gradle会检查一次依赖,可以设置每次build都进行检查。 ~~~ configurations.all { // check for updates every build resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } ~~~ 如果需要重新下载dependencies 执行 `./gradlew build --refresh-dependencies` 即可。 ## 十、Maven快照机制(SNAPSHOT) 以下引用自[https://ayayui.gitbooks.io/tutorialspoint-maven/content/book/maven\_snapshots.html](https://ayayui.gitbooks.io/tutorialspoint-maven/content/book/maven_snapshots.html): **1.场景** 一个大型的软件应用通常包含多个模块,并且通常的场景是多个团队开发同一应用的不同模块。举个例子,设想一个团队开发应用的前端,项目为**app-ui(app-ui.jar:1.0)**,而另一个团队开发应用的后台,使用的项目是**data-service(data-service.jar:1.0)**。 现在可能出现的情况是开发**data-service**的团队正在进行快节奏的bug修复或者项目改进,并且他们几乎每隔一天就要发布库到远程仓库。 现在如果**data-service**团队每隔一天上传一个新版本,那么将会出现下面的问题: * **data-service**团队每次发布更新的代码时都要告知**app-ui**团队。 * **app-ui**团队需要经常地更新他们**pom.xml**文件到最新版本。 为了解决这种情况, **快照(SNAPSHOT)**的概念派上了用场。 **2.什么是快照**(SNAPSHOT)**?** **快照**(SNAPSHOT)***\*是一种特殊的版本,指定了某个当前的开发进度的副本。不同于常规的版本,Maven每次构建都会在远程仓库中检查新的****快照*\*。 现在**data-service**团队会每次发布更新代码的快照到仓库中,比如说**data-service:1.0-SNAPSHOT**来替代旧的快照jar包。 注意:每次更新jar包时,版本好不变,且后缀必须带上-SNAPSHOT。 **3.项目快照(Snapshot) VS 版本(Version)** **版本(Version)**的情况下,如果Maven以前下载过指定的版本文件,比如说**data-service:1.0**,**Maven**将不会再从仓库下载新的可用的**1.0**文件。若要下载更新的代码,**data-service**的版本需要升到**1.1**。 **快照(Snapshot)**的情况下,每次**app-ui**团队构建他们的项目时,**Maven**将自动获取最新的快照(**data-service:1.0-SNAPSHOT**)。 备注:**版本(Version)**存放在Release发布仓库。**快照(Snapshot)**存放在Snapshot快照仓库。 注意:**版本(Version)**的概念,只要不带有**\-SNAPSHOT**的关键字时,都会认为这是一个在**Release发布仓库**的jar包。其中在**Release发布仓库**的jar包命名除了具体的版本号之后还可以带上比如:1.0-Release、1.0-rc1等等的字样。 **4.原理详解** **Maven**中的仓库分为两种,**Snapshot快照仓库**和**Release发布仓库**。**Snapshot快照仓库**用于保存开发过程中的不稳定版本,**Release正式仓库**则是用来保存稳定的发行版本。定义一个组件/模块为**快照版本**,只需要在**pom.xml**文件中在该模块的版本号后加上**\-SNAPSHOT**即可(注意这里必须是大写),如下所示: ~~~ <groupId>net.dopan.pigframe</groupId> <artifactId>test</artifactId> <version>0.1-SNAPSHOT</version> <packaging>jar</packaging> ~~~ **Maven**会根据模块的版本号(**pom.xml**文件中的**version)**中是否带有**\-SNAPSHOT**来判断是**快照版本**还是**正式版本**。如果是**快照版本**,那么在**mvn deploy**时会自动发布到**快照版本库**中,而使用**快照版本**的模块,在**不更改版本号**的情况下,直接编译打包时,**Maven**会**自动从镜像服务器上下载最新的快照版本**。如果是**正式发布版本**,那么在**mvn deploy**时会自动发布到**正式版本库**中,而使用**正式版本**的模块,在**不更改版本号**的情况下,编译打包时如果本地已经存在该版本的模块则**不会主动去镜像服务器上下载**。 所以,我们在开发阶段,可以将公用库的版本设置为快照版本,而被依赖组件则引用快照版本进行开发,在公用库的快照版本更新后,我们也不需要修改**pom.xml**文件提示版本号来下载新的版本,直接**Maven**执行相关编译、打包命令即可重新下载最新的快照库了,从而也方便了我们进行开发。 虽然,**快照**的情况下,**Maven**在日常工作中会自动获取最新的快照,你也可以在任何**Maven**命令中使用**\-U参数**强制**Maven**下载最新的快照构建。命令如下: ~~~ mvn clean package -U ~~~