ดึงข้อมูลรุ่นจาก maven pom.xml ในรหัส


256

เป็นวิธีที่ง่ายที่สุดในการดึงหมายเลขรุ่นจากรหัส pom.xml ของ Maven ในรหัสคือโดยทางโปรแกรม?

คำตอบ:


263

สมมติว่าคุณใช้ Java คุณสามารถ

  1. สร้าง.propertiesไฟล์ใน (โดยทั่วไป) src/main/resourcesไดเรกทอรีของคุณ(แต่ในขั้นตอนที่ 4 คุณสามารถบอกให้มันดูที่อื่น)

  2. กำหนดค่าของคุณสมบัติบางอย่างใน.propertiesไฟล์ของคุณโดยใช้คุณสมบัติ Maven มาตรฐานสำหรับเวอร์ชันโครงการ: foo.bar=${project.version}

  3. ในโค้ด Java ของคุณให้โหลดค่าจากไฟล์คุณสมบัติเป็นทรัพยากรจาก classpath (google สำหรับตัวอย่างมากมายของวิธีการทำเช่นนี้ แต่นี่เป็นตัวอย่างสำหรับ starters )

  4. ใน Maven ให้เปิดใช้งานการกรองทรัพยากรซึ่งจะทำให้ Maven คัดลอกไฟล์นั้นไปยังคลาสเอาต์พุตของคุณและแปลทรัพยากรระหว่างการคัดลอกนั้นแปลความหมายของคุณสมบัติ คุณสามารถหาข้อมูลได้ที่นี่แต่ส่วนใหญ่คุณทำได้ใน pom ของคุณ:

    <สร้าง>
      <ทรัพยากร>
        <ทรัพยากร>
          <ไดเรกทอรี> src / main ทรัพยากร / </ ไดเรกทอรี>
          <กรอง> จริง </ กรอง>
        </ ทรัพยากร>
      </ ทรัพยากร>   
    </ สร้าง>

นอกจากนี้คุณยังจะได้รับคุณสมบัติมาตรฐานอื่น ๆ เช่นproject.name, project.descriptionหรือแม้กระทั่งคุณสมบัติโดยพลการที่คุณใส่ใน pom ของคุณ<properties>ฯลฯ ทรัพยากรกรองรวมกับโปรไฟล์ Maven สามารถให้คุณสร้างพฤติกรรมตัวแปรเวลาที่สร้าง เมื่อคุณระบุโปรไฟล์เมื่อรันไทม์ด้วย-PmyProfileนั่นสามารถเปิดใช้งานคุณสมบัติที่สามารถแสดงในบิลด์ของคุณ


2
ฉันพบรหัสนี้ซึ่งไม่มีการเปลี่ยนแปลงการกำหนดค่า Maven
เวนเดล

7
ระวังการใช้การกรองโดยตรงsrc/main/resourcesเนื่องจากอาจประมวลผลไฟล์ทั้งหมดที่อยู่ในไดเรกทอรีนี้รวมถึงไฟล์ไบนารี เพื่อหลีกเลี่ยงพฤติกรรมที่คาดเดาไม่ได้มันจะดีกว่าที่จะทำกรองในsrc/main/resources-filteredไดเรกทอรีที่แนะนำที่นี่ อย่างไรก็ตามขอขอบคุณสำหรับเคล็ดลับที่ดีนี้!
SiZiOUS

1
คำตอบด้านล่างโดยใช้ MavenXppReader เพื่อรับโมเดลจริงมีประโยชน์จริง ๆ เนื่องจากไม่จำเป็นต้องเรียกใช้อะไรเพื่อค้นหาค่า ในกรณีที่คุณจำเป็นต้องรู้รุ่นก่อนที่จะทำงานอะไรให้ดูคำตอบด้านล่าง มันมีประโยชน์มากสำหรับฉันที่จะให้ gradle รู้ว่าโครงการ maven ที่ได้รับการตรวจสอบมีอะไรบ้างดังนั้นฉันจึงสามารถทราบตำแหน่งของ jar ล่วงหน้า
อาแจ็กซ์

92

คำตอบที่ยอมรับอาจเป็นวิธีที่ดีที่สุดและเสถียรที่สุดในการรับหมายเลขรุ่นลงในแอปพลิเคชันแบบคงที่แต่จริงๆแล้วไม่ได้ตอบคำถามเดิม: วิธีการดึงหมายเลขเวอร์ชันของสิ่งประดิษฐ์จาก pom.xml? ดังนั้นฉันต้องการเสนอทางเลือกอื่นที่แสดงวิธีการทำงานแบบไดนามิกในระหว่างรันไทม์:

คุณสามารถใช้ Maven ได้ เพื่อความแม่นยำมากขึ้นคุณสามารถใช้ห้องสมุด Maven

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-model</artifactId>
  <version>3.3.9</version>
</dependency>

จากนั้นทำสิ่งนี้ใน Java:

package de.scrum_master.app;

import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.FileReader;
import java.io.IOException;

public class Application {
    public static void main(String[] args) throws IOException, XmlPullParserException {
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = reader.read(new FileReader("pom.xml"));
        System.out.println(model.getId());
        System.out.println(model.getGroupId());
        System.out.println(model.getArtifactId());
        System.out.println(model.getVersion());
    }
}

บันทึกคอนโซลมีดังนี้:

de.scrum-master.stackoverflow:my-artifact:jar:1.0-SNAPSHOT
de.scrum-master.stackoverflow
my-artifact
1.0-SNAPSHOT

Update 2017-10-31:เพื่อตอบคำถามติดตามผลของ Simon Sobisch ฉันได้แก้ไขตัวอย่างเช่นนี้:

package de.scrum_master.app;

import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Application {
  public static void main(String[] args) throws IOException, XmlPullParserException {
    MavenXpp3Reader reader = new MavenXpp3Reader();
    Model model;
    if ((new File("pom.xml")).exists())
      model = reader.read(new FileReader("pom.xml"));
    else
      model = reader.read(
        new InputStreamReader(
          Application.class.getResourceAsStream(
            "/META-INF/maven/de.scrum-master.stackoverflow/aspectj-introduce-method/pom.xml"
          )
        )
      );
    System.out.println(model.getId());
    System.out.println(model.getGroupId());
    System.out.println(model.getArtifactId());
    System.out.println(model.getVersion());
  }
}

1
มันเกือบจะเหมือนกับสิ่งที่ฉันใช้และทำงานได้ดีเมื่อเริ่มต้นจาก eclipse แต่ไม่เริ่มเมื่อจากpackaged jar ปกติ(คลาสการพึ่งพาไม่ได้รวมอยู่) และไม่ทำงานเมื่อบรรจุด้วย maven-assembly-plugin ที่jar-with-dependenciesฉันได้รับ a java.io.FileNotFoundException: pom.xml(มันอยู่ในโหลสุดท้ายMETA-INF/maven/my.package/myapp/pom.xml) - คำใบ้ใด ๆ ที่จะแก้ปัญหานี้?
Simon Sobisch

1
โซลูชันของฉันมีวัตถุประสงค์เพื่อทำงานแบบไดนามิกในสภาพแวดล้อมการพัฒนาเช่นเมื่อใช้ในการทดสอบหรือเครื่องมือที่เริ่มจาก IDE หรือคอนโซล คำตอบที่ได้รับการยอมรับสำหรับคำถามนี้แสดงหลายวิธีในการจัดแพคเกจหมายเลขรุ่นแบบคงที่ลงในส่วนของคุณ ฉันไม่ได้สมมติว่า pom.xml จะพร้อมใช้งานภายใน JAR เลย ดีสำหรับคุณที่คุณมีมันแม้ว่า บางทีคุณสามารถปรับพา ธ เมื่อเปิดโปรแกรมอ่านไฟล์และอาจทำให้มันขึ้นอยู่กับสถานการณ์ของ classloader ฉันจะต้องลองด้วยตัวเอง อย่าลังเลที่จะถามคำถามติดตามหากสิ่งนี้ไม่ได้ช่วย
kriegaex

2
สวัสดี @SimonSobisch ฉันเพิ่งปรับปรุงคำตอบเพื่อแสดงวิธีการทำสิ่งที่คุณต้องการ แต่โปรดระวังความจริงที่ว่าฉันเพิ่งทำมันเร็วและสกปรกฉันไม่ชอบรหัสที่มีโครงสร้างที่ซ้อนกัน
kriegaex

75

สิ่งประดิษฐ์ที่บรรจุมีMETA-INF/maven/${groupId}/${artifactId}/pom.propertiesไฟล์ที่มีเนื้อหาเหมือน:

#Generated by Maven
#Sun Feb 21 23:38:24 GMT 2010
version=2.5
groupId=commons-lang
artifactId=commons-lang

แอปพลิเคชั่นหลายตัวใช้ไฟล์นี้เพื่ออ่านเวอร์ชันของแอปพลิเคชั่น / jar ในขณะรันไทม์โดยไม่จำเป็นต้องตั้งค่า

ปัญหาเดียวของวิธีการข้างต้นคือไฟล์นี้ (ปัจจุบัน) สร้างขึ้นในระหว่างpackageขั้นตอนและจะไม่ปรากฏในระหว่างการทดสอบ ฯลฯ (มีปัญหาจิราที่จะเปลี่ยนแปลงสิ่งนี้ดูMJAR-76 ) หากนี่เป็นปัญหาสำหรับคุณแล้วแนวทางที่อธิบายโดย Alex เป็นวิธีที่จะไป


10
สำหรับผู้ที่กำลังมองหาตัวอย่างที่อ่านคุณสมบัติโพสต์นี้มีหลายวิธี - javablog.fr/ …
chrismarx

43

นอกจากนี้ยังมีวิธีการที่อธิบายไว้ในวิธีง่ายๆในการแสดงหมายเลขเวอร์ชันแอปของคุณโดยใช้ Maven :

เพิ่มลงใน pom.xml

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>test.App</mainClass>
            <addDefaultImplementationEntries>
              true
            </addDefaultImplementationEntries>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

จากนั้นใช้สิ่งนี้:

App.class.getPackage().getImplementationVersion()

ฉันได้พบวิธีการนี้จะง่ายขึ้น


18
-1 - วิธีนี้ไม่ได้ผลสำหรับฉัน ค่าของเป็นgetImplementationVersion() null(เวอร์ชัน maven 3.0.4)
Jesse Webb

7
ขึ้นอยู่กับเฟส ... ใช้งานได้เฉพาะเมื่อมีการบรรจุสิ่งประดิษฐ์ดังนั้นจึงไม่สามารถใช้กับการทดสอบหน่วย: - /
wikier

2
สำหรับ.warสิ่งประดิษฐ์อย่าลืมใช้maven-war-pluginแทนmaven-jar-plugin
cs_pupil

สำหรับฉันมันใช้งานได้ในTomcat 8แต่ไม่ทำงานในTomcat 7 ( getImplementationVersion()คืนค่าว่าง)
อัลฟองโซนิชิกาว่า

18

หากคุณใช้บรรจุภัณฑ์ mvn เช่น jar หรือ war ให้ใช้:

getClass().getPackage().getImplementationVersion()

มันอ่านคุณสมบัติ "Implementation-Version" ของ META-INF / MANIFEST.MF ที่สร้างขึ้น (ซึ่งถูกตั้งค่าเป็นเวอร์ชันของ pom.xml) ในไฟล์เก็บถาวร


18

เพื่อเติมเต็มสิ่งที่ @kieste โพสต์ไว้ซึ่งฉันคิดว่าเป็นวิธีที่ดีที่สุดในการให้ Maven บิลด์ข้อมูลมีอยู่ในรหัสของคุณหากคุณใช้ Spring-boot: เอกสารที่http://docs.spring.io/spring-boot/ เอกสาร / ปัจจุบัน / การอ้างอิง / htmlsingle / # การผลิตพร้อมแอปพลิเคชันข้อมูลมีประโยชน์มาก

คุณเพียงแค่ต้องเปิดใช้งานแอคทูเอเตอร์และเพิ่มคุณสมบัติที่คุณต้องการในapplication.propertiesหรือapplication.yml

Automatic property expansion using Maven

You can automatically expand info properties from the Maven project using resource filtering. If you use the spring-boot-starter-parent you can then refer to your Maven project properties via @..@ placeholders, e.g.

project.artifactId=myproject
project.name=Demo
project.version=X.X.X.X
project.description=Demo project for info endpoint
info.build.artifact=@project.artifactId@
info.build.name=@project.name@
info.build.description=@project.description@
info.build.version=@project.version@

6

ใช้ห้องสมุดนี้เพื่อความสะดวกในการแก้ปัญหาง่ายๆ เพิ่มในรายการสิ่งที่คุณต้องการแล้วค้นหาด้วยสตริง

 System.out.println("JAR was created by " + Manifests.read("Created-By"));

http://manifests.jcabi.com/index.html


3

บางครั้งบรรทัดคำสั่ง Maven นั้นเพียงพอเมื่อทำการสคริปต์บางอย่างที่เกี่ยวข้องกับรุ่นของโครงการเช่นสำหรับการดึงสิ่งประดิษฐ์ผ่าน URL จากที่เก็บ:

mvn help:evaluate -Dexpression=project.version -q -DforceStdout

ตัวอย่างการใช้งาน:

VERSION=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )
ARTIFACT_ID=$( mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout )
GROUP_ID_URL=$( mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout | sed -e 's#\.#/#g' )
curl -f -S -O http://REPO-URL/mvn-repos/${GROUP_ID_URL}/${ARTIFACT_ID}/${VERSION}/${ARTIFACT_ID}-${VERSION}.jar

1
    <build>
            <finalName>${project.artifactId}-${project.version}</finalName>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>3.2.2</version>
                        <configuration>
                            <failOnMissingWebXml>false</failOnMissingWebXml>
                            <archive>
                                <manifest>
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                </manifest>
                            </archive>
                        </configuration>
                    </plugin>
                 </plugins>
            </pluginManagement>
</build>

รับรุ่นโดยใช้ this.getClass().getPackage().getImplementationVersion()

PS อย่าลืมเพิ่ม:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>

0

จากการอ้างอิงถึงคำตอบของ ketankk :

น่าเสียดายที่การเพิ่มสิ่งนี้สับสนกับวิธีที่แอปพลิเคชันของฉันจัดการกับทรัพยากร:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>   
</build>

แต่การใช้สิ่งนี้ภายในแท็ก <manifest> ของ maven-assemble-plugin ทำให้เคล็ดลับ:

<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>

ดังนั้นฉันสามารถรับเวอร์ชันโดยใช้

String version = getClass().getPackage().getImplementationVersion();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.