java Maven 中的多个部署
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/635154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple deployments in maven
提问by Mauli
We have a internal artifactory repository. At the moment all snapshots will be deployed there. We also want to have a different server with a web interface, and want to copy the to it the created artifacts.
我们有一个内部工件存储库。目前,所有快照都将部署在那里。我们还希望有一个带有 Web 界面的不同服务器,并希望将创建的工件复制到它。
For our builds we use Hudson, but the post-build action "Deploy artifacts to Maven repository" together with scp doesn't work. So there is the question of doing it in some other elegant way. Why isn't maven able to have several distribution repositories? Any ideas?
对于我们的构建,我们使用 Hudson,但构建后操作“将工件部署到 Maven 存储库”与 scp 一起不起作用。所以存在以其他一些优雅的方式来做这件事的问题。为什么 maven 不能拥有多个分发存储库?有任何想法吗?
The nicest thing would be if artifactory would support an (automatic!) incremental export to a standard maven repository after each new deployment.
最好的事情是,在每次新部署后,artifactory 是否支持(自动!)增量导出到标准 Maven 存储库。
回答by jon077
I don't think maven supports deploying to multiple repositories for a single profile, but perhaps profiles could change the id and urls of the repository.
我认为 maven 不支持为单个配置文件部署到多个存储库,但配置文件可能会更改存储库的 id 和 url。
<distributionManagement>
<repository>
<id>${repo-id}</id>
<name>${repo-name}</name>
<url>${repo-url}</url>
</repository>
</distributionManagement>
Then use profiles to pick which repo to deploy to:
然后使用配置文件选择要部署到的存储库:
<profiles>
<profile>
<id>repo1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<repo-id>repo1</repo-id>
<repo-name>Repo1 Name </repo-name>
<repo-url>http://url.com/maven2</repo-url>
</properties>
</profile>
<profile>
<id>repo2</id>
<properties>
<repo-id>repo2</repo-id>
<repo-name>Repo2 Name </repo-name>
<repo-url>http://url2.com/maven2</repo-url>
</properties>
</profile>
</profiles>
回答by Rich Seller
If you are willing to use a custom plugin, you can configure Maven to deploy to a list of "mirror" locations at the same time as the standard deployment. I'd recommend defining this in a profile so you can control what deployments are mirrored (it might not be appropriate to do this on every build).
如果您愿意使用自定义插件,您可以将 Maven 配置为在标准部署的同时部署到“镜像”位置列表。我建议在配置文件中定义它,以便您可以控制镜像哪些部署(在每个构建中都这样做可能不合适)。
To define a new plugin you need to create a new Maven project and specify the POM has packaging maven-plugin:
要定义一个新插件,您需要创建一个新的 Maven 项目并指定 POM 已打包maven-plugin:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>maven-mirror-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.0.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
In src/main/java define a Mojo. The code below declares a "mirror" goal, it takes a list of mirrorRepository items (containing a repositoryId and url) to mirror the artifact deployment to. The plugin uses the same approach to deployment as the maven-deploy-plugin, and takes most of the same parameters.
在 src/main/java 中定义一个 Mojo。下面的代码声明了一个“镜像”目标,它需要一个 mirrorRepository 项目列表(包含一个 repositoryId 和 url)来将工件部署镜像到。该插件使用与 maven-deploy-plugin 相同的部署方法,并采用大部分相同的参数。
Note that you still need to define a server in your settings.xml for each repository with appropriate permissions to do the deployment or the build will fail!
请注意,您仍然需要在 settings.xml 中为每个存储库定义一个具有适当权限的服务器来进行部署,否则构建将失败!
package name.seller.rich;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeployer;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
/**
* @goal mirror
* @phase deploy
*/
public class MirrorMojo extends AbstractMojo {
/**
* @parameter expression=
* "${component.org.apache.maven.artifact.deployer.ArtifactDeployer}"
* @required
* @readonly
*/
private ArtifactDeployer deployer;
/**
* Map that contains the layouts
*
* @component role=
* "org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout"
*/
private Map repositoryLayouts;
/**
* Component used to create a repository
*
* @component
*/
private ArtifactRepositoryFactory repositoryFactory;
/**
* The type of remote repository layout to deploy to. Try <i>legacy</i> for
* a Maven 1.x-style repository layout.
*
* @parameter expression="${repositoryLayout}" default-value="default"
* @required
*/
private String repositoryLayout;
/**
* Parameter used to update the metadata to make the artifact as release.
*
* @parameter expression="${updateReleaseInfo}" default-value="false"
*/
private boolean updateReleaseInfo;
/**
* Whether to deploy snapshots with a unique version or not.
*
* @parameter expression="${uniqueVersion}" default-value="true"
*/
private boolean uniqueVersion;
/**
* @parameter expression="${mirrorRepositories}"
* @required
*/
private MirrorRepository[] mirrorRepositories;
/**
* @parameter expression="${localRepository}"
* @required
* @readonly
*/
private ArtifactRepository localRepository;
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* Deploy all artifacts for the project to each mirror repository.
*/
public void execute() throws MojoExecutionException, MojoFailureException {
ArtifactRepositoryLayout layout;
layout = (ArtifactRepositoryLayout) repositoryLayouts
.get(repositoryLayout);
for (int i = 0; i < mirrorRepositories.length; i++) {
MirrorRepository mirrorRepository = mirrorRepositories[i];
ArtifactRepository deploymentRepository = repositoryFactory
.createDeploymentArtifactRepository(mirrorRepository
.getRepositoryId(), mirrorRepository.getUrl(),
layout, uniqueVersion);
String protocol = deploymentRepository.getProtocol();
if ("".equals(protocol) || protocol == null) {
throw new MojoExecutionException("No transfer protocol found.");
}
deployToRepository(deploymentRepository);
}
}
/**
* Deploy all artifacts to the passed repository.
*/
private void deployToRepository(ArtifactRepository repo)
throws MojoExecutionException {
String protocol = repo.getProtocol();
if (protocol.equalsIgnoreCase("scp")) {
File sshFile = new File(System.getProperty("user.home"), ".ssh");
if (!sshFile.exists()) {
sshFile.mkdirs();
}
}
File pomFile = project.getFile();
Artifact artifact = project.getArtifact();
// Deploy the POM
boolean isPomArtifact = "pom".equals(project.getPackaging());
if (!isPomArtifact) {
ArtifactMetadata metadata = new ProjectArtifactMetadata(artifact,
pomFile);
artifact.addMetadata(metadata);
}
if (updateReleaseInfo) {
artifact.setRelease(true);
}
try {
List attachedArtifacts = project.getAttachedArtifacts();
if (isPomArtifact) {
deployer.deploy(pomFile, artifact, repo, localRepository);
} else {
File file = artifact.getFile();
if (file != null && !file.isDirectory()) {
deployer.deploy(file, artifact, repo, localRepository);
} else if (!attachedArtifacts.isEmpty()) {
getLog()
.info(
"No primary artifact to deploy, deploy attached artifacts instead.");
} else {
String message = "The packaging for this project did not assign a file to the build artifact";
throw new MojoExecutionException(message);
}
}
for (Iterator i = attachedArtifacts.iterator(); i.hasNext();) {
Artifact attached = (Artifact) i.next();
deployer.deploy(attached.getFile(), attached, repo,
localRepository);
}
} catch (ArtifactDeploymentException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
}
}
The mojo references a MirrorRepository type to encapsulate the repositoryId and url, it is a simple bean:
mojo 引用了一个 MirrorRepository 类型来封装 repositoryId 和 url,它是一个简单的 bean:
package name.seller.rich;
public class MirrorRepository {
private String repositoryId;
private String url;
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Here's an example configuration using the plugin. Note all the deploy formats are supported (http, scp, ftp):
这是使用插件的示例配置。请注意,所有部署格式都受支持(http、scp、ftp):
<plugin>
<groupId>name.seller.rich</groupId>
<artifactId>maven-mirror-plugin</artifactId>
<executions>
<execution>
<id>mirror</id>
<phase>deploy</phase>
<goals>
<goal>mirror</goal>
</goals>
</execution>
</executions>
<configuration>
<mirrorRepositories>
<mirrorRepository>
<repositoryId>mirror</repositoryId>
<url>http://path/to/mirror</url>
</mirrorRepository>
</mirrorRepositories>
<!--any other deploy configuration needed-->
</configuration>
</plugin>
回答by Olivier
Artifactory doeshave an automatic export feature. From the documentation:
Artifactory确实具有自动导出功能。从文档:
You can automatically and periodically back up the whole Artifactory system. The backup process creates a timestamped directory (or zip file) in the target backup dir, and is basically identical to running full system export with metadata. [...] Each backup can have its own schedule and excluded certain repositories [...]
The content of the backup (when extracted) is in standard Maven format and can be loaded into any external Maven repository [...]
Artifactory supports backing up incrementally to the same target directory (named "current") in the target backup dir. This kind of backup is only writing deltas to the output dir, resulting in extremely fast backups.
您可以自动定期备份整个 Artifactory 系统。备份过程会在目标备份目录中创建一个带时间戳的目录(或 zip 文件),这与运行带有元数据的完整系统导出基本相同。[...] 每个备份都可以有自己的计划并排除某些存储库 [...]
备份的内容(提取时)采用标准 Maven 格式,可以加载到任何外部 Maven 存储库 [...]
Artifactory 支持增量备份到目标备份目录中的同一目标目录(名为“current”)。这种备份只是将增量写入输出目录,从而实现极快的备份。
Isn't that exactly what you need? To transfer the files, you can either mount a shared directory to the remote server and do the backup there, or do the backup locally and then rsync it.
这不正是你所需要的吗?要传输文件,您可以将共享目录挂载到远程服务器并在那里进行备份,或者在本地进行备份,然后进行 rsync。
回答by James Kingsbery
I think in Artifactory, by default, it maintains different logical repositories for uploading snapshots and non-snapshots. Using permissions, you can make the snapshot repository visible only to some.
我认为在 Artifactory 中,默认情况下,它维护不同的逻辑存储库,用于上传快照和非快照。使用权限,您可以使快照存储库仅对某些人可见。
If that is not sufficient, another solution that works with Artifactory 2.0 is to have Artifactory use a MySQL database that does asynchronous replication to another MySQL database, which in turn is being read by a separate installation of Artifactory. If that's too real time, you can simply have two different installations that do updates based on business rules.
如果这还不够,另一个适用于 Artifactory 2.0 的解决方案是让 Artifactory 使用一个 MySQL 数据库,该数据库对另一个 MySQL 数据库进行异步复制,而另一个 MySQL 数据库又由 Artifactory 的单独安装读取。如果这太实时了,您可以简单地使用两个不同的安装来根据业务规则进行更新。

