利用aether api实现从指定maven仓库下载jar包
最近公司做项目遇到一个需求,通过用户提供的groupId和artifactId以及version到指定maven库中下载jar包。平时的maven项目中,依赖的jar包都是通过pom文件设置,然后maven通过<dependency></dependency>去下载jar包,现在要做的就是maven下载的这一功能。
通过上网去查阅,知道了可以在命令行利用mvn dependency:copy -Dartifact=groupId:artifactId:version -DoutputDirectory=? -Dmdep.stripVerison=true的命令下载到本地仓库。但是有一个问题,利用mvn可能涉及到maven环境的问题,这样程序移植的时候会有很多问题。最好是由一个api借口,以jar包的形式引入,完全脱离本地的maven环境。
这个问题在网上搜索了好久,终于利用google找到了答案。它就是Aether。官方网址是http://wiki.eclipse.org/Aether 上面有相关的说明和API 文档。下面就来说一说具体的实现流程。
依据官方文档,首先应引入jar包,创建一个maven项目,在pom文件中添加如下依赖:
<properties>
<aetherVersion>1.0.0.v20140518</aetherVersion>
<mavenVersion>3.1.0</mavenVersion>
<wagonVersion>1.0</wagonVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-api</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-util</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-impl</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-connector-basic</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-file</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-http</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-wagon</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>${wagonVersion}</version>
</dependency>
</dependencies>
然后建立RepositorySystem,这个是用来操作maven仓库的主要接口:
/**
* 建立RepositorySystem
* @return RepositorySystem
*/
private static RepositorySystem newRepositorySystem()
{
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class );
locator.addService( TransporterFactory.class, FileTransporterFactory.class );
locator.addService( TransporterFactory.class, HttpTransporterFactory.class );
return locator.getService( RepositorySystem.class );
}
然后建立RepositorySystemSession对象:
/**
* create a repository system session
* @param system RepositorySystem
* @return RepositorySystemSession
*/
private static RepositorySystemSession newSession( RepositorySystem system,String target )
{
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
LocalRepository localRepo = new LocalRepository( /*"target/local-repo" */target);
session.setLocalRepositoryManager( system.newLocalRepositoryManager( session, localRepo ) );
return session;
}
接下来实现的是从指定maven仓库下载指定的jar包:
/**
* 从指定maven地址下载指定jar包
* @param artifact maven-jar包的三围定位(groupId:artifactId:version)
* @param repositoryURL maven库的URL地址
* @param username 若需要权限,则需使用此参数添加用户名,否则设为null
* @param password 同上
* @throws ArtifactResolutionException
*/
public static void DownLoad(Params params) throws ArtifactResolutionException
{
String groupId=params.getGroupId();
String artifactId=params.getArtifactId();
String version=params.getVersion();
String repositoryUrl=params.getRepository();
String target=params.getTarget();
String username=params.getUsername();
String password=params.getPassword();
RepositorySystem repoSystem = newRepositorySystem();
RepositorySystemSession session = newSession( repoSystem ,target);
RemoteRepository central=null;
if(username==null&&password==null)
{
central = new RemoteRepository.Builder( "central", "default", repositoryUrl ).build();
}else{
Authentication authentication=new AuthenticationBuilder().addUsername(username).addPassword(password).build();
central = new RemoteRepository.Builder( "central", "default", repositoryUrl ).setAuthentication(authentication).build();
}
/**
* 下载一个jar包
*/
Artifact artifact=new DefaultArtifact(groupId+":"+artifactId+":"+version);
ArtifactRequest artifactRequest=new ArtifactRequest();
artifactRequest.addRepository(central);
artifactRequest.setArtifact(artifact);
repoSystem.resolveArtifact(session, artifactRequest);
System.out.println("success");
/**
* 下载该jar包及其所有依赖jar包
*/
/*
*
Dependency dependency =
new Dependency( new DefaultArtifact( artifact ),null);
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot( dependency );
collectRequest.addRepository( central );
DependencyNode node = repoSystem.collectDependencies( session, collectRequest ).getRoot();
DependencyRequest dependencyRequest = new DependencyRequest();
dependencyRequest.setRoot( node );
repoSystem.resolveDependencies( session, dependencyRequest );
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
node.accept( nlg );
System.out.println( nlg.getClassPath() );*/
}
}
其中Params对象是相关的一些参数,包括groupId,artifactId,version,远程maven仓库的URL地址repository,下载后存放的路径target,访问maven仓库的username和password:
public class Params {
/**
* jar包在maven仓库中的groupId
*/
private String groupId;
/**
* jar包在maven仓库中的artifactId
*/
private String artifactId;
/**
* jar包在maven仓库中的version
*/
private String version;
/**
* 远程maven仓库的URL地址,默认使用bw30的远程maven-public库
*/
private String repository="http://ae.mvn.bw30.com/repository/maven-public/";
/**
* 下载的jar包存放的目标地址,默认为./target/repo
*/
private String target="temp";
/**
* 登录远程maven仓库的用户名,若远程仓库不需要权限,设为null,默认为null
*/
private String username=null;
/**
* 登录远程maven仓库的密码,若远程仓库不需要权限,设为null,默认为null
*/
private String password=null;
public Params() {
super();
}
public Params(String groupId, String artifactId) {
super();
this.groupId = groupId;
this.artifactId = artifactId;
}
public Params(String groupId, String artifactId, String username,
String password) {
super();
this.groupId = groupId;
this.artifactId = artifactId;
this.username = username;
this.password = password;
}
public Params(String groupId, String artifactId, String version,
String repository, /*String target,*/ String username, String password) {
super();
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.repository = repository;
/*this.target = target;*/
this.username = username;
this.password = password;
}
public Params(String groupId, String artifactId, String version,
String username, String password) {
super();
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.username = username;
this.password = password;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getRepository() {
return repository;
}
public void setRepository(String repository) {
this.repository = repository;
}
public String getTarget() {
return target;
}
/*public void setTarget(String target) {
this.target = target;
}*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
上面是根据三围来下载jar包,但是jar包的版本会有很多,所以有如下需求:给定groupId和artifactId,列出所有的version,用户选择某一version后再利用上面的方法下载,那么怎么列出所有的version呢?Aether API给出了一些借口,稍加组合即可:
/**
* 根据groupId和artifactId获取所有版本列表
* @param params Params对象,包括基本信息
* @return version列表
* @throws VersionRangeResolutionException
*/
public static List<Version> getAllVersions(Params params) throws VersionRangeResolutionException
{
String groupId=params.getGroupId();
String artifactId=params.getArtifactId();
String repositoryUrl=params.getRepository();
String target=params.getTarget();
String username=params.getUsername();
String password=params.getPassword();
RepositorySystem repoSystem = newRepositorySystem();
RepositorySystemSession session = newSession( repoSystem ,target);
RemoteRepository central=null;
if(username==null&&password==null)
{
central = new RemoteRepository.Builder( "central", "default", repositoryUrl ).build();
}else{
Authentication authentication=new AuthenticationBuilder().addUsername(username).addPassword(password).build();
central = new RemoteRepository.Builder( "central", "default", repositoryUrl ).setAuthentication(authentication).build();
}
Artifact artifact = new DefaultArtifact( groupId+":"+artifactId+":[0,)" );
VersionRangeRequest rangeRequest = new VersionRangeRequest();
rangeRequest.setArtifact( artifact );
rangeRequest.addRepository( central );
VersionRangeResult rangeResult = repoSystem.resolveVersionRange( session, rangeRequest );
List<Version> versions = rangeResult.getVersions();
System.out.println( "Available versions " + versions );
return versions;
}
在这里面最令人恶心的是由于之前是三围坐标,创建Artifact对象的时候传进去groupId:artifactId:verison的字符串就行了,现在没有verison了,找了好久的API都是必带verison的,甚至试了一下通配符也不成。后来找到了官方的example的源码,才发现原来是用[0,)来表示所有的verison,就是数学中的0到正无穷呀,想改成啥区间的version都可以了。
后面的需求就是解压下载下来的jar包,然后将其中的js文件夹再压缩供用户下载引用,压缩、解压的方法网上好多,就不再说明了。
另外,Aether官方提供的示例代码还实现很多其他的功能,有需要的可以下载来参考。
示例代码官方git地址:git://git.eclipse.org/gitroot/aether/aether-demo.git 或
ssh://git.eclipse.org/gitroot/aether/aether-demo.git 或
http://git.eclipse.org/gitroot/aether/aether-demo.git
我的源代码地址:git@git.oschina.net:xiaosiyuan/maven-download-jar.git 或
https://git.oschina.net/xiaosiyuan/maven-download-jar.git

浙公网安备 33010602011771号