陈颂光
全栈工程师,能够独立开发从解释器到网站和桌面/移动端应用的各类软件。
关注我的 GitHub

Ant项目利用Ivy借力Maven仓库

进行开发时难免要依赖于第三方的包,而这些包还可能依赖于其它包,这是开发者共同面对的问题。就Java开发而言,Maven中央仓库大概是JAR包最齐全的地方,因此是解决依赖的理想地方。对于使用Ant而不是Maven为构建工具的项目,也可以使用Ivy插件来与Maven仓库打交道(至于maven插件已不维护 ,但似乎仍能用),解决依赖关系。值得一提的是,Maven、Ant、Ivy全是Apache基金会的项目。

从Maven仓库解决依赖

增加Ant构建文件目标

在项目的build.xml中加入一些目标:

	<property name="ivy.install.version" value="2.4.0"/>
	<property name="ivy.jar.dir" value="ivy"/>
	<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
	<target name="check-for-ivy">
		<available property="ivy.downloaded" file="${ivy.jar.file}"/>
	</target>
	<target name="download-ivy" depends="check-for-ivy" unless="ivy.downloaded">
		<mkdir dir="${ivy.jar.dir}"/>
		<get src="http://central.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" dest="${ivy.jar.file}" usetimestamp="true"/>
	</target>
	<target name="install-ivy" depends="download-ivy">
		<path id="ivy.lib.path">
			<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
		</path>
		<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
	</target>
	<target name="clean-ivy">
		<delete dir="${ivy.jar.dir}"/>
	</target>
	<target name="clean-ivy-cache" depends="install-ivy">
		<ivy:cleancache/>
	</target>
	<target name="resolve" depends="install-ivy">
		<ivy:retrieve />
	</target>

如你所见执行resolve目标会先确保Ivy已安装(不然会导致自动下载并安装Ivy到ivy目录),再把所有依赖下载到lib目录。同时还要保证已声明ivy名字空间,如:

<project name="项目名" default="default" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">

然后确保需要依赖的目标依赖于上面的resolve目标,比如Netbeans项目中加入:

	<target name="-post-init" depends="resolve">
	</target>

描述依赖

在项目目录下的ivy.xml文件中指定你需要的依赖,它形如:

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation=
                   "http://ant.apache.org/ivy/schemas/ivy.xsd">
	<info organisation="你的项目的Maven组ID(不上传的话可以乱写)" module="你的项目的Maven构件ID(不上传的话可以乱写)"/>
	<dependencies defaultconfmapping="default->master,compile" defaultconf="default">
		<dependency org="所需构件的Maven组ID" name="所需构件的Maven构件ID" rev="所需版本号"/>
		<!-- 重复直至描述了你直接需要的所有构件 -->
	</dependencies>
</ivy-module>

设置Ivy(可选)

假如你不仅需要正式发布的版本,还需要快照版本,在项目目录下创建一个文件ivysettings.xml内容如下:

<ivysettings>
	<property name="ivy.shared.default.root"             value="${ivy.default.ivy.user.dir}/shared" override="false"/>
	<property name="ivy.shared.default.ivy.pattern"      value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
	<property name="ivy.shared.default.artifact.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
	<property name="ivy.local.default.root"             value="${ivy.default.ivy.user.dir}/local" override="false"/>
	<property name="ivy.local.default.ivy.pattern"      value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
	<property name="ivy.local.default.artifact.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
	<settings defaultResolver="default"/>
	<resolvers>
		<ibiblio name="public" m2compatible="true"/>
		<ibiblio name="snapshot" m2compatible="true" root="https://oss.sonatype.org/content/repositories/snapshots/" /><!-- 关键是这一行 -->
		<filesystem name="shared">
			<ivy pattern="${ivy.shared.default.root}/${ivy.shared.default.ivy.pattern}" />
			<artifact pattern="${ivy.shared.default.root}/${ivy.shared.default.artifact.pattern}" />
		</filesystem>
		<filesystem name="local">
			<ivy pattern="${ivy.local.default.root}/${ivy.local.default.ivy.pattern}" />
			<artifact pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
		</filesystem>
		<chain name="main" dual="true">
			<resolver ref="shared"/>
			<resolver ref="public"/>
			<resolver ref="snapshot"/>
		</chain>
		<chain name="default" returnFirst="true" checkmodified="true">
			<resolver ref="local"/>
			<resolver ref="main"/>
		</chain>
	</resolvers>
</ivysettings>

发布到Maven仓库

增加Ant构建文件目标

在项目的build.xml中加入一些目标:

	<property name="ivy.install.version" value="2.4.0"/>
	<property name="ivy.jar.dir" value="ivy"/>
	<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
	<target name="check-for-ivy">
		<available property="ivy.downloaded" file="${ivy.jar.file}"/>
	</target>
	<target name="download-ivy" depends="check-for-ivy" unless="ivy.downloaded">
		<mkdir dir="${ivy.jar.dir}"/>
		<get src="http://central.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" dest="${ivy.jar.file}" usetimestamp="true"/>
		<get src="http://central.maven.org/maven2/org/bouncycastle/bcpg-jdk14/1.45/bcpg-jdk14-1.45.jar" dest="${ivy.jar.dir}/bcbcpg-jdk14-1.45.jar" usetimestamp="true"/><!-- 用于数字签名 -->
		<get src="http://central.maven.org/maven2/org/bouncycastle/bcprov-jdk14/1.45/bcprov-jdk14-1.45.jar" dest="${ivy.jar.dir}/bcprov-jdk14-1.45.jar" usetimestamp="true"/><!-- 用于数字签名 -->
	</target>
	<target name="install-ivy" depends="download-ivy">
		<path id="ivy.lib.path">
			<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
		</path>
		<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
	</target>
	<target name="clean-ivy">
		<delete dir="${ivy.jar.dir}"/>
	</target>
	<target name="clean-ivy-cache" depends="install-ivy">
		<ivy:cleancache/>
	</target>
	<target name="resolve" depends="install-ivy">
		<ivy:retrieve />
	</target>
	<property name="deploy" value="dist/deploy"/>
	<property name="jar" value="${deploy}/${project.name}.jar"/>
	<property name="javadoc-jar" value="${deploy}/${project.name}-javadoc.jar"/>
	<property name="sources-jar" value="${deploy}/${project.name}-sources.jar"/>
	<target name="snapshot" depends="resolve,jar">
		<mkdir dir="${deploy}"/>
		<copy file="dist/${project.name}.jar" tofile="${jar}"/>
		<ivy:makepom ivyfile="ivy.xml" pomfile="${deploy}/pom.xml"/>
		<ivy:publish resolver="nexus-snapshots"
						  revision="版本号-SNAPSHOT"
						  overwrite="true" 
						  publishivy="false" >
			<artifacts pattern="${deploy}/[artifact](-[classifier]).[ext]"/>
			<artifact name="pom" ext="xml" type="ivy" />
			<artifact name="${project.name}" ext="jar" type="jar"/>
		</ivy:publish>
	</target>
	
	<target name="stage" depends="resolve,default">
		<mkdir dir="${deploy}"/>
		<copy file="dist/${project.name}.jar" tofile="${jar}"/>
		<jar jarfile="${sources-jar}">
			<fileset dir="src"/>
		</jar>
		<jar jarfile="${javadoc-jar}">
			<fileset dir="dist/javadoc"/>
		</jar>
		<ivy:makepom ivyfile="ivy.xml" pomfile="${deploy}/pom.xml"/>
		<ivy:publish resolver="nexus-releases"
						  revision="版本号"
						  overwrite="true" 
						  publishivy="false" >
			<artifacts pattern="${deploy}/[artifact](-[classifier]).[ext]"/>
			<artifact name="pom" ext="xml" type="ivy" />
			<artifact name="${project.name}" ext="jar" type="jar"/>
			<artifact name="${project.name}" ext="jar" type="sources" classifier="sources" />
			<artifact name="${project.name}" ext="jar" type="javadoc" classifier="javadoc" />
		</ivy:publish>
	</target>

同时还要保证已声明ivy名字空间,如:

<project name="项目名" default="default" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">

描述依赖

在项目目录下的ivy.xml文件中指定你需要的依赖和你要发布构件的信息,它们将用于生成pom.xml,它形如:

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation=
                   "http://ant.apache.org/ivy/schemas/ivy.xsd">
	<info organisation="你的项目的Maven组ID" module="你的项目的Maven构件ID" revision="版本号">
		<license name="许可证" url="许可证URL"/>
		<ivyauthor name="作者" url="作者URL"/>
		<repository name="代码仓库" url="代码仓库URL"/>
		<description>构件简介</description>
	</info>
	<dependencies defaultconfmapping="default->master,compile" defaultconf="default">
		<dependency org="所需构件的Maven组ID" name="所需构件的Maven构件ID" rev="所需版本号"/>
		<!-- 重复直至描述了你直接需要的所有构件 -->
	</dependencies>
</ivy-module>

设置Ivy

你还需要在项目目录下创建一个文件ivysettings.xml内容如下:

<ivysettings>
  <settings defaultResolver="nexus"/>
  <signers>
    <pgp name="本机用户名" password="解锁密钥环的口令"/>
  </signers>
  <credentials host="oss.sonatype.org"
                      realm="Sonatype Nexus Repository Manager"
                      username="你的Sonatype用户名" passwd="你的Sonatype密码"/>
  <property name="nexus-public"
                   value="https://oss.sonatype.org/content/groups/public"/>
  <property name="nexus-releases" value="https://oss.sonatype.org/service/local/staging/deploy/maven2"/>
  <property name="nexus-snapshots" value="https://oss.sonatype.org/content/repositories/snapshots"/>
  <resolvers>
    <ibiblio name="nexus" m2compatible="true" root="${nexus-public}"/>
    <ibiblio name="nexus-releases" m2compatible="true" root="${nexus-releases}" signer="本机用户名(与ivysettings.xml中一样)"/>
    <ibiblio name="nexus-snapshots" m2compatible="true" root="${nexus-snapshots}" checkmodified="true" 
changingPattern="*-SNAPSHOT"/>
  </resolvers>
</ivysettings>

由于含有你的隐私信息,不要泄露这个文件,例如切勿把这文件它推入到公开的代码仓库,而应该让版本控制系统忽略它。

关键词 ivy maven ant java