【问题标题】:How does spring-boot:run work with maven?spring-boot:run 如何与 maven 一起工作?
【发布时间】:2019-08-30 01:21:00
【问题描述】:

我正在学习 maven 构建过程,并且存在一些争论点,因为它没有多大意义。

按照我对 maven 的理解,有默认的生命周期(默认、站点、干净),每个生命周期都有多个阶段。有一些与几个阶段相关的内置插件,通过添加额外的插件,您可以为预先存在的阶段添加额外的功能。

当您指定一个阶段直接在 maven 中运行时,它将在同一个生命周期内经历到目前为止的所有阶段,并以执行您指定的阶段结束。然而,据我所知,spring-boot:run 是一个目标,因此在运行时不应调用其他阶段。话虽如此,通过 maven 运行 spring-boot:run 确实会运行其他阶段(default-clipre-unit-testdefault-resourcesreserve-container-port 和其他一些阶段)。在我看来,spring 创建了一些新阶段(例如reserve-container-port),但我不确定如何找到这些配置所在的 jar 文件。

因此,我的问题是双重的:

  1. spring-boot:run 是我理解的目标吗?如果是这样,运行这个目标又如何运行其他阶段?据我所知,仅将一个阶段指定为目标将按顺序运行其他先前阶段,而不是直接指定目标。
  2. 所有这些的配置文件在哪里?我可以在哪个 spring jar 文件中找到让上述所有功能正常工作的配置文件。

【问题讨论】:

    标签: java spring maven spring-boot


    【解决方案1】:

    spring-boot:run 是我理解的目标吗

    事实上,spring-boot 是一个 maven 插件,run 是它的目标之一。

    这里是这个插件的the official documentation

    在本文档中,我没有找到执行此目标的默认 maven 阶段。但是在github source code,我发现这个目标是在TEST_COMPILE阶段执行的

    仅将一个阶段指定为目标将按顺序运行其他先前阶段,而不是直接指定目标。

    事实上,这就是 maven 的工作方式。这是introduction to the maven lifecycle

    所有这些的配置文件在哪里?

    它在你的 spring-boot pom parent 中定义:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>${spring-boot-starter-parent.version}</version>
    </parent>
    

    希望得到帮助:)

    【讨论】:

    • 感谢您抽出宝贵时间回答,但您还没有真正触及为什么运行 spring-boot:run 目标会导致其他阶段运行。您介意澄清一下这是如何工作的吗?
    • introduction to the maven lifecycle link 中,有一些答案,但我认为这个bealdung article(我鼓励你试一试;))给了我们我们正在寻找的东西:要运行特定目标,而不执行其整个阶段(和前面的阶段),我们可以使用命令:mvn :
    • 我明白,但这不是我要问的。在我的问题中,我指出运行 spring-boot:run 目标也会运行其他阶段,这似乎与您所说的直接矛盾。我试图弄清楚为什么会这样。
    • 在了解了更多关于 Maven 的知识后,我为之前误导的 cmets 道歉。我对整个 Maven 有一个根本性的误解,这似乎是正确的答案。
    • 官方文档 404 的 URL。我想现在应该是这个:docs.spring.io/spring-boot/docs/current/reference/html/…
    【解决方案2】:

    由于其他答案错过了我正在寻找的一些信息,我想我会添加我的研究结果以防其他人好奇。进去看看

    C:\HOME_DIR.m2\repository\org\springframework\boot\spring-boot-maven-plugin\VERSION_NUMBER\META-INF\maven\plugin.xml

    给出了spring with maven的大部分相关目标的配置文件。具体来说,下面的 sn-p 描述了spring-boot:run 目标的工作原理。

    <mojo>
          <goal>run</goal>
          <description>Run an executable archive application.</description>
          <requiresDependencyResolution>test</requiresDependencyResolution>
          <requiresDirectInvocation>false</requiresDirectInvocation>
          <requiresProject>true</requiresProject>
          <requiresReports>false</requiresReports>
          <aggregator>false</aggregator>
          <requiresOnline>false</requiresOnline>
          <inheritedByDefault>true</inheritedByDefault>
          <phase>validate</phase>
          <executePhase>test-compile</executePhase>
          <implementation>org.springframework.boot.maven.RunMojo</implementation>
          <language>java</language>
          <instantiationStrategy>per-lookup</instantiationStrategy>
          <executionStrategy>once-per-session</executionStrategy>
          <since>1.0.0</since>
          <threadSafe>false</threadSafe>
          ...
    </mojo>
    

    具体来说,&lt;executePhase&gt; 标记(在https://maven.apache.org/developers/mojo-api-specification.html 有部分详细说明),(我相信)它让这个目标在运行时执行不同的阶段。

    我之前错过了这个细节(它似乎也没有很好地记录在任何地方)。不管怎样,这个解释对我来说已经足够令人满意了。如果有人找到此标签的更好文档,我将不胜感激:)

    【讨论】:

      【解决方案3】:

      从maven的角度直接回答你的问题:

      关于生命周期、阶段和相关插件的所有内容 - 你已经正确理解了。

      但是,您错过了一点,在 maven 中可以直接运行插件的目标。 将这些目标视为执行某些操作的代码的逻辑单元,如果您希望可以运行,则可以将其视为具有“main”方法的类,为其提供参数等等。

      在 maven 的插件世界中,插件中与目标相关联的一段代码称为 Mojo,这是一个 maven 可以执行的类。

      所以一个插件至少包含一个 mojo,如果插件开发人员决定它应该做许多相关的事情,它可能会包含很多。这是一个 example 的插件,目前有 4 个不同的目标(插件本身代码中的 Mojos)。

      所以,这个直接调用的语法是:

      mvn plugin-groupId:plugin-artifactId:plugin-version:goal
      mvn plugin-groupId:plugin-artifactId:goal
      mvn plugin-prefix:goal
      

      在某些情况下(请参阅official maven documentation),您可以省略其中的一些语法,这正是您的情况。

      当然,当你像这样直接运行目标时,它会完全绕过生命周期执行阶段和所有内容,所以如果你想直接运行测试的目标,但你从未编译过测试,它会失败。示例:

      mvn test // run all phases of the default lifecycle including compilation, tests 
               // compilation, test execution - will succeed on a "clean" project
      
      mvn surefire:test // run directly a goal called "test" inside plugin called "surefire"
      

      mvn spring-boot:run 也会发生同样的事情

      你正在运行 spring boot maven 插件,maven 将插件的版本解析为构建的版本,因为你没有指定它,然后运行一个名为“run”的目标

      【讨论】:

      • 我明白你在这里所说的一切,但我的问题主要是为什么运行目标直接运行其他阶段,正如我在问题中指出的那样。这似乎与您在此处所说的直接矛盾(“当您像这样直接运行目标时,它完全绕过了生命周期执行与阶段和所有内容”)。在 spring-boot:run 的情况下,为什么运行直接目标最终会运行其他阶段,您是否有任何线索?
      猜你喜欢
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多