提供的 Ivy 依赖项

Posted

技术标签:

【中文标题】提供的 Ivy 依赖项【英文标题】:Ivy dependency as provided 【发布时间】:2016-10-16 21:02:49 【问题描述】:

问题:我需要在 Eclipse 类路径上有一个不应部署到 Tomcat 的库。 (在 maven 项目中,它将提供范围)

说明:

我已经设置了一个具有一些 Ivy 依赖项的项目,并且必须将配置外部化为 JNI(邮件/会话)才能做到这一点,我必须将 mail-1.4.7.jar 放在 Tomcat lib 文件夹中。

问题是我有一个依赖项将javax.mail-1.5.2.jar 添加到我的类路径中,所以我将其更改为:

<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.2">
    <exclude org="com.sun.mail" name="javax.mail"/>
</dependency>

现在的问题是我的项目由于缺少javax.mail.MessagingException等邮件类而中断(编译错误)

所以我必须添加邮件依赖项,但仅限于 Eclipse。我已经尝试了一些配置,如 here 从我从 Maven 行为中了解到的,但无济于事。

仅在项目中保留邮件依赖项会破坏 Tomcat,将其保留在 tomcat 和项目上都会破坏项目。当我从我的项目库文件夹(WEB-INF\lib)中手动删除它时,部署项目后,它可以正常工作。

底线(部署后):

tomcatFolder                    
  |_lib
  |   |_...
  |   |_mail-1.4.7.jar
  |   |_...
  |_webapps
        |_myproject
             |_WEB-INF
                  |_lib
                     |_...
                     |_javax.mail-1.5.2.jar //need to remove it at deploy time only
                     |_...

现在无法将其更改为 maven。但它正在处理中:)

【问题讨论】:

【参考方案1】:

这确实是这个问题的重复:

How to copy runtime libraries without the provided ones in IVY

但是.. 从您的问题来看,我怀疑您没有使用常春藤配置映射。这是不幸的,因为这是 ivy 用来在逻辑上将依赖项分组到功能组中的机制,类似于 Maven 维护范围的方式。以下帖子试图弥合这种理解

How are maven scopes mapped to ivy configurations by ivy

此外,您还使用 Eclipse,这意味着除非您使用 ivy plugin,否则您实际上拥有两种构建机制。 (常春藤和日食)。我建议先修复您的 ANT 构建,然后再看看如何维护 Eclipse 类路径。

示例

第一部分描述如何在 ivy 文件中声明和使用配置,第二部分解释如何在构建逻辑中使用 ivy ANT 任务。

ivy.xml

您应该始终声明 ivy 配置并使用它们来控制您的类路径。在我的构建中,我总是至少有三个:编译、运行时和测试。请注意 extends 属性是如何用于创建配置之间的关系的,因为运行时还应该包含编译依赖项。

为提供的范围 jar 添加一个额外的很容易。简单的单机配置:

<ivy-module version="2.0">
    <info organisation="com.myspotontheweb" module="demo"/>

    <configurations>
        <conf name="compile"  description="Required to compile application"/>
        <conf name="runtime"  description="Additional run-time dependencies" extends="compile"/>
        <conf name="test"     description="Required for test only" extends="runtime"/>
        <conf name="provided" description="Needed for compile, but will be present on the target platform."/>
    </configurations>

    <dependencies>
        <!-- compile dependencies -->
        <dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/>

        <!-- runtime dependencies -->
        <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/>

        <!-- test dependencies -->
        <dependency org="junit" name="junit" rev="4.11" conf="test->default"/>

        <!-- provided dependencies -->
        <dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" conf="provided->master"/>
    </dependencies>

</ivy-module>

配置映射让事情变得特别。简单的解释是,当从 Maven 存储库中拉取时,它们分为两种基本类型:

conf="local_configuration->default" conf="local_configuration->master"

第一种方法包括远程模块及其所有依赖项。第二种方法包括远程模块和 exclude 它的依赖项。这意味着您不需要以下排除技巧:

<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.2">
    <exclude org="com.sun.mail" name="javax.mail"/>
</dependency>

如果您想要的只是 log4j-core jar,您只需使用以下内容:

<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.2" conf="provided->master"/>

补充说明:

在 ivy 映射到远程“默认”配置时,只会拉下您需要的 jar。它将排除可选依赖项和其他内容,例如 javadocs。 当模块作者的依赖关系错误时,有时需要“排除”。

build.xml

解析目标将下拉依赖项,生成报告并创建编译和测试类路径。注意使用配置来确定应该使用哪些 jar 分组:

<target name="resolve" description="Use ivy to resolve classpaths">
    <ivy:resolve/>

    <ivy:report todir='$build.dir/ivy-reports' graph='false' xml='false'/>

    <ivy:cachepath pathid="compile.path" conf="compile,provided"/>
    <ivy:cachepath pathid="test.path"    conf="test,provided"/>
</target>

编译目标会照常使用这些类路径引用:

<target name="compile" depends="resolve,resources" description="Compile code">
    <mkdir dir="$build.dir/classes"/>
    <javac srcdir="$src.dir" destdir="$build.dir/classes" includeantruntime="false" debug="true" classpathref="compile.path"/>
</target>

<target name="compile-tests" depends="compile" description="Compile tests">
    <mkdir dir="$build.dir/test-classes"/>
    <javac srcdir="$test.src.dir" destdir="$build.dir/test-classes" includeantruntime="false" debug="true">
        <classpath>
            <path refid="test.path"/>
            <pathelement path="$build.dir/classes"/>
        </classpath>
    </javac>
</target>

以及测试目标:

<target name="test" depends="compile-tests" description="Run unit tests">
    <mkdir dir="$build.dir/test-reports"/>
    <junit printsummary="yes" haltonfailure="yes">
        <classpath>
            <path refid="test.path"/>
            <pathelement path="$build.dir/classes"/>
            <pathelement path="$build.dir/test-classes"/>
        </classpath>
        <formatter type="xml"/>
        <batchtest fork="yes" todir="$build.dir/test-reports">
            <fileset dir="$test.src.dir">
                <include name="**/*Test*.java"/>
                <exclude name="**/AllTests.java"/>
            </fileset>
        </batchtest>
    </junit>
</target>

最后,ivy 检索任务用于构建 war 文件。仅使用“运行时”配置 jar:

<target name="package" depends="test" description="Create the WAR file">
    <ivy:retrieve pattern="$build.dir/lib/[artifact].[ext]" conf="runtime"/>

    <war destfile="$war.file" webxml="$resources.dir/web.xml">
        <fileset dir="$resources.dir" excludes="web.xml"/>
        <lib dir="$build.dir/lib"/>
    </war>
</target>

总之,cachepath ivy 任务用于根据 ivy 配置创建类路径引用,retrieve 任务用于组装 war 文件。

【讨论】:

这是一个非常好的解释。谢谢你。我会在星期一回去工作的时候试试!!真的很感激!!再次感谢您。

以上是关于提供的 Ivy 依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Apache Ivy:解决嵌入在安装程序中的依赖项

从 Ivy.xml 下载依赖项

如何避免使用 Ivy 复制依赖项

如何让 Ivy 将我的依赖项的依赖项捆绑到他们自己的 jar 中?

遗留存储库的 Ivy 依赖项管理

Apache Ant 和 Ivy:生成了错误的依赖项