简体   繁体   English

与maven的依赖管理

[英]dependency management with maven

I have lately become a big fan of Maven for controlling the build cycle for my application. 我最近成为Maven的忠实粉丝,用于控制我的应用程序的构建周期。 However I've encountered some rough edges with Maven's dependency management. 但是,我遇到了Maven依赖管理的一些粗糙边缘。 I'm wondering if these are limitations of the tool and paradigm, necessary evils of dependancy management, or if I"m just using the tool incorrectly. 我想知道这些是否是工具和范例的限制,依赖管理的必要弊端,或者我是否只是错误地使用了工具。

  1. First is the matter of transitive dependencies. 首先是传递依赖的问题。 As I understand it, if you provide a dependency, Maven will in turn find any dependencies of that dependency. 据我了解,如果你提供一个依赖,Maven将反过来找到该依赖的任何依赖。 That is great, but for many of my dependencies, this has not worked. 这很好,但对于我的许多依赖项,这没有用。 For example, including Hibernate in my project: 例如,在我的项目中包含Hibernate:

     <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.2.GA</version> </dependency> 

    Results in a missing dependency of slf4j. 导致slf4j缺少依赖性。 I need to manually add this dependency which I assumed would be Maven's job. 我需要手动添加这个依赖项,我认为这将是Maven的工作。 The same goes for Spring. 春天也是如此。 If I add Spring-MVC as a dependency, shouldn't all of the basic servlet dependencies be added for me (because Spring-MVC would need this stuff)? 如果我将Spring-MVC添加为依赖项,那么不应该为我添加所有基本的servlet依赖项(因为Spring-MVC需要这些东西)? I'm referring to the servlet, jsp, jstl libraries. 我指的是servlet,jsp,jstl库。

  2. Second is the management of repositories. 其次是存储库的管理。 Maven comes shipped with a default main repository, but I've found that in many cases this repository is not up to date. Maven附带一个默认的主存储库,但我发现在很多情况下这个存储库不是最新的。 For example, ifyou want spring3, you have to manually add the springsource repository, and if you want hibernate 3.5+ you have to add the jboss repository. 例如,如果你想要spring3,你必须手动添加springource存储库,如果你想要hibernate 3.5+,你必须添加jboss存储库。 It seems to defeat the point of automatic dependency management when you have to hunt down the correct repositories yourself. 当你必须自己寻找正确的存储库时,它似乎打败了自动依赖管理的重点。 This hunting soon gets complicated. 这种狩猎很快变得复杂。 For example to add Spring3, you may want the spring release repo, the spring externals repo and the spring milestone repo. 例如,要添加Spring3,您可能需要spring release repo,spring externals repo和spring milestone repo。

  3. Closely related to number 2 is ensuring you have the correct version of an artifact. 与数字2密切相关的是确保您拥有正确版本的工件。 I have been burned several times by including the wrong versions of dependent artifacts for a given artifact. 通过为给定的工件包含错误版本的依赖工件,我已被多次烧毁。 For example the wrong version of the servlet/jsp/jstl apis for spring3, or the wrong version of persistence / annotation apis for hibernate. 例如,spring3的servlet / jsp / jstl apis的错误版本,或者hibernate的错误版本的持久性/注释apis。 The repositories are filled with many versions, some with confusing names like productx-3.ga, productx-3-rc1, productx-3-SNAPSHOT, productx-3-cr, product-3-beta, etc. Some of these are obvious (rc= release candidate), but it can be confusing trying to determine the order of these versions. 存储库中充满了许多版本,其中一些版本名称如productx-3.ga,productx-3-rc1,productx-3-SNAPSHOT,productx-3-cr,product-3-beta等等。其中一些显而易见(rc =发布候选版本),但尝试确定这些版本的顺序可能会令人困惑。

  4. Finally, the issue of the type a dependency. 最后,类型一个依赖的问题。 I probably just don't understand this well enough, but many repo artifacts are of type "pom" not "jar". 我可能只是不太了解这一点,但许多repo工件都是“pom”而不是“jar”。 Several times i have added a dependency jar to my project only to find out at build time that the repo jar does not actually exist (example is org.hibernate ejb3-persistence in the jboss repo). 有几次我在项目中添加了一个依赖jar,只是为了在构建时发现repo jar实际上并不存在(例子是jboss repo中的org.hibernate ejb3-persistence)。

With some experimenting, I can usually get a build to work, but is dependency management in general this complicated? 通过一些实验,我通常可以获得一个构建工作,但一般来说依赖管理这个复杂吗? I still prefer this approach to manually adding jar files to my project, but I would be interested to learn how to improve my maven dependency management skills. 我仍然更喜欢这种方法手动将jar文件添加到我的项目中,但我有兴趣学习如何提高我的maven依赖管理技能。

Can't answer all parts of the question, but about some of them: 无法回答问题的所有部分,但关于其中一些问题:

  • Some transitive dependecies are marked optional , so people who don't need these features wouldn't download them, but people, who need, have to set them explicitly in their poms. 一些传递性依赖被标记为optional ,因此不需要这些功能的人不会下载它们,但是需要的人必须在他们的poms中明确地设置它们。

  • Maven Central repository contains only releases. Maven Central存储库仅包含版本。 Therefore, it doesn't contain Hibernate 3.5 (which is beta) as well as it hadn't contained Spring 3 until it was released (by the way, you don't need to specify special Spring repository for Spring 3 any more - release is already in Maven Central) 因此,它不包含Hibernate 3.5(它是beta)以及在它发布之前它没有包含Spring 3(顺便说一下,你不需要为Spring 3指定特殊的Spring存储库 - 释放已经在Maven Central)

  • slf4j is a very special kind of dependency - its runtime behavior depends on which implementation of slf4j you use. slf4j是一种非常特殊的依赖 - 它的运行时行为取决于你使用的slf4j的实现。 Therefore, to control its behavior you have to specify slf4j implementation explicitly 因此,要控制其行为,您必须明确指定slf4j实现

  • About management skills: to get useful information for maintaining your pom.xml you can use mvn dependency:tree (especially with -Dverbose=true ) and mvn dependency:analyze . 关于管理技能:要获得维护pom.xml有用信息,可以使用mvn dependency:tree (特别是-Dverbose=true )和mvn dependency:analyze It can be also useful to check pom file of your dependency to look for optional dependencies. 检查依赖项的pom文件以查找可选的依赖项也很有用。

First is the matter of transitive dependencies. 首先是传递依赖的问题。 As I understand it, if you provide a dependency, Maven will in turn find any dependencies of that dependency. 据我了解,如果你提供一个依赖,Maven将反过来找到该依赖的任何依赖。 That is great, but for many of my dependencies, this has not worked. 这很好,但对于我的许多依赖项,这没有用。 (...) (......)

As already pointed out, some dependencies may be marked as optional (and are not pulled transitively). 如前所述,某些依赖关系可能被标记为可选 (并且不会被传递)。 The idea is that some dependencies are only used for certain features and will not be needed if that feature isn't used. 这个想法是某些依赖项仅用于某些功能,如果不使用该功能则不需要。 If a user wants to use functionality related to an optional dependency, they will have to redeclare that optional dependency in their own project. 如果用户想要使用与可选依赖项相关的功能,则必须在自己的项目中重新声明该可选依赖项。 So this just works as designed :) 所以这只是按设计工作:)

Second is the management of repositories. 其次是存储库的管理。 Maven comes shipped with a default main repository, but I've found that in many cases this repository is not up to date. Maven附带一个默认的主存储库,但我发现在很多情况下这个存储库不是最新的。 (...) (......)

Even if the idea behind the concept of a central repo is noble, you can't objectively expect it to contain all jars in the world. 即使中央回购概念背后的想法是高尚的,你也不能客观地期望它包含世界上所有的罐子。 One of the most obvious reason is that uploading artifacts to the Central Repository just takes time and resources are not infinite. 其中一个最明显的原因是将工件上传到中央存储库只需要时间和资源不是无限的。 And because companies like RedHat JBoss or SpringSource or Sun or even me need flexibility, reactivity (in one word, control), it's not surprising that they use their own repository. 而且因为像RedHat JBoss或SpringSource或Sun这样的公司甚至我都需要灵活性,反应性(总之,控制权),因此他们使用自己的存储库并不奇怪。 And, actually, I'm pretty happy that they expose them. 实际上,我很高兴他们揭露了他们。 But indeed, projects need to document where to find their artifacts if they are not available in central . 但实际上,项目需要记录在哪里找到他们的工件,如果他们在中央不可用。 Just in case, you may find this How to find dependencies on public Maven repositories? 为了以防万一,您可能会发现如何查找公共Maven存储库的依赖项? helpful. 很有帮助。 In a corporate environment, the best way to handle this would be to setup a centralized (corporate) proxying repository. 在企业环境中,处理此问题的最佳方法是设置集中式(公司)代理存储库。 See this page for such solutions. 有关此类解决方案,请参阅此页

Closely related to number 2 is ensuring you have the correct version of an artifact. 与数字2密切相关的是确保您拥有正确版本的工件。 (...) (......)

Sorry but you need a bit to know what you're are doing. 对不起,你需要知道你在做什么。 A project can't guess for you what JSTL version you are going to use. 一个项目无法猜测你将要使用的JSTL版本。 Then, regarding the various versions of artifacts, the naming convention used by projects has nothing to do with maven, this is a project/vendor choice (except for SNAPSHOT that maven handles specially). 然后,关于各种版本的工件,项目使用的命名约定与maven无关,这是项目/供应商的选择(maven专门处理的SNAPSHOT除外)。 FWIW, common used schemes include: M1 = Milestone 1, RC1 = Release Candidate 1, GA = General Availability (final release), CR = Customer Release (often a bug-fix release). FWIW,常用的方案包括:M1 =里程碑1,RC1 =候选发布者1,GA =一般可用性(最终版本),CR =客户发布(通常是错误修复版本)。 You may also see alpha, beta. 您可能还会看到alpha,beta。 This really depends on the project lifecycle and convention (nothing really unusual here though). 这实际上取决于项目的生命周期和约定(尽管这里没什么特别的)。

Finally, the issue of the type a dependency. 最后,类型一个依赖的问题。 I probably just don't understand this well enough, but many repo artifacts are of type "pom" not "jar". 我可能只是不太了解这一点,但许多repo工件都是“pom”而不是“jar”。 (...) (......)

I think that you're indeed lacking of experience. 我认为你确实缺乏经验。 You seem to be fighting with dependencies while things just go smoothly for me :) Maybe using a repository search engine will help. 你似乎正在与依赖关系战斗,而事情对我来说很顺利:)也许使用存储库搜索引擎会有所帮助。

You can also exclude some transitive dependencies, like the following example: 您还可以排除某些传递依赖项,如以下示例所示:

<dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.15</version>
        <exclusions>
            <exclusion>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
            </exclusion>
            <exclusion>
                <groupId>javax.jms</groupId>
                <artifactId>jms</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jdmk</groupId>
                <artifactId>jmxtools</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jmx</groupId>
                <artifactId>jmxri</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

I don't remember the details, but apparently some other dependencies were being discovered when we wanted to use log4j, and we had no interest (or need) in them in our case, so my cow orker just said "no thanks to these" and it works. 我不记得细节了,但是当我们想要使用log4j时,显然还有一些其他依赖项被发现了,我们在这种情况下对它们没有任何兴趣(或者需要),所以我的牛人只是说“不,谢谢这些”它的工作原理。

  1. Transitive dependencies are only there if they have been encoded explicitly in your direct dependencies' POM's. 只有在直接依赖关系'POM'中明确编码它们时,才会存在传递依赖关系。 Sometimes you actually do not want them, either because there are alternative implementations or you're using only part of a library and you don't want to drag in dependencies for things you're actually not using. 有时你实际上并不想要它们,要么是因为有其他实现,要么你只使用了库的一部分而你不想为你实际上没有使用的东西拖入依赖项。

  2. You are using a repository manager such as Nexus , aren't you? 您正在使用Nexus等存储库管理器,不是吗? I advise you to setup one even if you code alone. 即使您单独编码,我也建议您设置一个。

  3. I find that Maven actually helps with this problem. 我发现Maven确实帮助解决了这个问题。 I would hate having to perform this trial-and-error from ftp sites and download pages. 我不想从ftp站点和下载页面执行此试错。

  4. Yes, I hate that too :-) 是的,我也讨厌这个:-)

Read the book ! 读这本书 I actually learned most of what I know from this other book , but given it comes from the same people, I expect them to be rather interchangeable. 我实际上从其他书中学到了我所知道的大部分内容 ,但鉴于它来自同一个人,我希望它们可以互换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM