最近公司做项目遇到一个需求,通过用户提供的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}<span class="hljs-tag"></<span class="hljs-name">version</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.eclipse.aether<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>aether-util<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">version</span>></span>${aetherVersion}
</version>
-
</dependency>
-
<dependency>
-
<groupId>org.eclipse.aether
</groupId>
-
<artifactId>aether-impl
</artifactId>
-
<version>${aetherVersion}<span class="hljs-tag"></<span class="hljs-name">version</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.eclipse.aether<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>aether-connector-basic<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">version</span>></span>${aetherVersion}
</version>
-
</dependency>
-
<dependency>
-
<groupId>org.eclipse.aether
</groupId>
-
<artifactId>aether-transport-file
</artifactId>
-
<version>${aetherVersion}<span class="hljs-tag"></<span class="hljs-name">version</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="31"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="32"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="33"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.eclipse.aether<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="34"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>aether-transport-http<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">version</span>></span>${aetherVersion}
</version>
-
</dependency>
-
<dependency>
-
<groupId>org.eclipse.aether
</groupId>
-
<artifactId>aether-transport-wagon
</artifactId>
-
<version>${aetherVersion}<span class="hljs-tag"></<span class="hljs-name">version</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">dependency</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="43"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.apache.maven<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="44"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>maven-aether-provider<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="45"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">version</span>></span>${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
我的源代码地址:[email protected]:xiaosiyuan/maven-download-jar.git 或
https://git.oschina.net/xiaosiyuan/maven-download-jar.git
</div>
</div>
</article>