Lấy phiên bản từ maven pom.xml trong mã


256

Cách đơn giản nhất để truy xuất số phiên bản từ mã pom.xml của maven, tức là theo lập trình?

Câu trả lời:


263

Giả sử bạn đang sử dụng Java, bạn có thể

  1. Tạo một .propertiestệp trong (phổ biến nhất) src/main/resourcesthư mục của bạn (nhưng trong bước 4, bạn có thể yêu cầu nó tìm ở nơi khác).

  2. Đặt giá trị của một số thuộc tính trong .propertiestệp của bạn bằng thuộc tính Maven tiêu chuẩn cho phiên bản dự án: foo.bar=${project.version}

  3. Trong mã Java của bạn, tải giá trị từ tệp thuộc tính dưới dạng tài nguyên từ đường dẫn lớp (google cho các ví dụ đa dạng về cách thực hiện việc này, nhưng đây là một ví dụ cho người mới bắt đầu ).

  4. Trong Maven, cho phép lọc tài nguyên - điều này sẽ khiến Maven sao chép tệp đó vào các lớp đầu ra của bạn và dịch tài nguyên trong quá trình sao chép đó, diễn giải thuộc tính. Bạn có thể tìm thấy một số thông tin ở đây nhưng bạn chủ yếu chỉ làm điều này trong pom của bạn:

    <xây dựng>
      <tài nguyên>
        <tài nguyên>
          <thư mục> src / main / resource </ thư mục>
          <lọc> đúng </ lọc>
        </ tài nguyên>
      </ tài nguyên>   
    </ xây dựng>

Bạn cũng có thể nhận được các thuộc tính tiêu chuẩn khác như project.name, project.descriptionhoặc thậm chí các thuộc tính tùy ý bạn đặt trong pom của mình <properties>, v.v. Lọc tài nguyên, kết hợp với cấu hình Maven, có thể cung cấp cho bạn hành vi xây dựng biến khi xây dựng. Khi bạn chỉ định một cấu hình trong thời gian chạy với -PmyProfile, có thể kích hoạt các thuộc tính mà sau đó có thể hiển thị trong bản dựng của bạn.


2
Tôi tìm thấy một mã này mà không thay đổi cấu hình Maven.
Wendel

7
Cảnh giác với việc sử dụng tính năng lọc trực tiếp src/main/resources, vì điều này có thể xử lý tất cả các tệp nằm trong thư mục này, bao gồm các tệp nhị phân. Để tránh các hành vi không thể đoán trước, tốt hơn là thực hiện lọc trên một src/main/resources-filteredthư mục, như được đề xuất ở đây . Dù sao, cảm ơn bạn cho thủ thuật tốt đẹp này!
SiZiOUS

1
Câu trả lời dưới đây bằng cách sử dụng MavenXppReader để có được mô hình thực sự rất hữu ích, vì nó không cần phải chạy bất cứ thứ gì để tìm giá trị. Trong trường hợp bạn cần biết phiên bản trước khi mọi thứ được chạy, hãy xem các câu trả lời dưới đây; nó rất hữu ích cho tôi để cho gradle biết dự án maven đã kiểm tra phiên bản nào, vì vậy tôi có thể biết vị trí jar đầu ra trước đó.
Ajax

92

Câu trả lời được chấp nhận có thể là cách tốt nhất và ổn định nhất để đưa số phiên bản vào ứng dụng một cách tĩnh , nhưng thực tế không trả lời câu hỏi ban đầu: Làm cách nào để lấy số phiên bản của tạo phẩm từ pom.xml? Vì vậy, tôi muốn đưa ra một giải pháp thay thế cho thấy cách thực hiện một cách linh hoạt trong thời gian chạy:

Bạn có thể sử dụng Maven chính nó. Để chính xác hơn, bạn có thể sử dụng thư viện Maven.

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

Và sau đó làm một cái gì đó như thế này trong 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());
    }
}

Nhật ký giao diện điều khiển như sau:

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

Cập nhật 2017-10-31: Để trả lời câu hỏi tiếp theo của Simon Sobisch, tôi đã sửa đổi ví dụ như thế này:

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
Điều này gần giống với những gì tôi sử dụng và hoạt động tốt khi bắt đầu từ nhật thực, nhưng không phải khi bắt đầu từ bình packaged bình thường (các lớp phụ thuộc không được tích hợp) và không hoạt động khi được đóng gói với maven-assembly-plugin jar-with-dependenciestôi nhận được a java.io.FileNotFoundException: pom.xml(nó nằm trong bình cuối cùng như META-INF/maven/my.package/myapp/pom.xml) - có gợi ý nào để giải quyết vấn đề này không?
Simon Sobisch

1
Giải pháp của tôi có nghĩa là hoạt động linh hoạt trong môi trường phát triển, ví dụ như khi được sử dụng trong các thử nghiệm hoặc công cụ bắt đầu từ IDE hoặc bảng điều khiển. Câu trả lời được chấp nhận cho câu hỏi này cho thấy một số cách để đóng gói số phiên bản một cách tĩnh vào các vật phẩm của bạn. Tôi đã không cho rằng pom.xml sẽ có sẵn trong JAR. Tốt cho bạn rằng bạn có nó ở đó, mặc dù. Có lẽ bạn chỉ có thể điều chỉnh đường dẫn khi mở trình đọc tệp và có thể làm cho nó phụ thuộc vào tình huống trình nạp lớp. Tôi sẽ phải cố gắng cho bản thân mình. Vui lòng đặt câu hỏi tiếp theo nếu điều này không có ích.
kriegaex

2
Xin chào @SimonSobisch, tôi vừa cập nhật câu trả lời của mình để chỉ cho bạn cách làm những gì bạn muốn. Nhưng xin lưu ý rằng thực tế là tôi đã làm nó nhanh & bẩn, tôi không đặc biệt thích mã với các hàm tạo.
kriegaex

75

Các tạo phẩm được đóng gói chứa một META-INF/maven/${groupId}/${artifactId}/pom.propertiestệp có nội dung như sau:

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

Nhiều ứng dụng sử dụng tệp này để đọc phiên bản ứng dụng / jar khi chạy, không cần thiết lập.

Vấn đề duy nhất với cách tiếp cận ở trên là tệp này (hiện tại) được tạo trong packagegiai đoạn và do đó sẽ không có mặt trong các thử nghiệm, v.v. (có một vấn đề Jira để thay đổi điều này, xem MJAR-76 ). Nếu đây là một vấn đề cho bạn, thì cách tiếp cận được mô tả bởi Alex là cách để đi.


10
Đối với những người đang tìm kiếm một ví dụ đọc các thuộc tính, bài đăng này đi qua một số phương pháp - javablog.fr/ mẹo
chrismarx

43

Ngoài ra còn có phương pháp được mô tả theo cách Dễ dàng để hiển thị số phiên bản ứng dụng của bạn bằng Maven :

Thêm phần này vào 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>

Sau đó sử dụng:

App.class.getPackage().getImplementationVersion()

Tôi đã tìm thấy phương pháp này để đơn giản hơn.


18
-1 - Giải pháp này không hiệu quả với tôi; giá trị của getImplementationVersion()null. (phiên bản maven 3.0.4)
Jesse Webb

7
tùy thuộc vào giai đoạn ... chỉ hoạt động khi cổ vật đang được đóng gói, do đó không hoạt động trên các bài kiểm tra đơn vị: - /
wikier 16/12/13

2
Đối với .warcác vật phẩm, hãy nhớ sử dụng maven-war-pluginthay vìmaven-jar-plugin
cs_pupil

Đối với tôi, điều này không hoạt động trong Tomcat 8 , nhưng không hoạt động trong Tomcat 7 ( getImplementationVersion()trả về null).
Alfonso Nishikawa

18

Nếu bạn sử dụng bao bì mvn như bình hoặc chiến tranh, hãy sử dụng:

getClass().getPackage().getImplementationVersion()

Nó đọc một thuộc tính "Phiên bản triển khai" của META-INF / MANIFEST.MF được tạo (được đặt thành phiên bản của pom.xml) trong kho lưu trữ.


18

Để bổ sung cho những gì @kieste đã đăng, mà tôi nghĩ là cách tốt nhất để có thông tin xây dựng Maven có sẵn trong mã của bạn nếu bạn đang sử dụng Spring-boot: tài liệu tại http://docs.spring.io/spring-boot/ docs / current / Reference / htmlsingle / # sản xuất-ready-application-information rất hữu ích.

Bạn chỉ cần kích hoạt bộ truyền động và thêm các thuộc tính bạn cần trong application.propertieshoặcapplication.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

Sử dụng Thư viện này để dễ dàng cho một giải pháp đơn giản. Thêm vào bảng kê khai bất cứ điều gì bạn cần và sau đó truy vấn theo chuỗi.

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

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


3

Đôi khi dòng lệnh Maven là đủ khi kịch bản một cái gì đó liên quan đến phiên bản dự án, ví dụ như để truy xuất giả tạo thông qua URL từ kho lưu trữ:

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

Ví dụ sử dụng:

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>

Nhận phiên bản bằng cách sử dụng this.getClass().getPackage().getImplementationVersion()

PS Đừng quên thêm:

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

0

Với tham chiếu đến câu trả lời của ketankk :

Thật không may, việc thêm này lại gây rối với cách ứng dụng của tôi xử lý các tài nguyên:

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

Nhưng sử dụng thẻ này trong thẻ <manifest> của maven-lắp ráp-plugin đã thực hiện thủ thuật:

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

Vì vậy, tôi đã có thể có được phiên bản bằng cách sử dụng

String version = getClass().getPackage().getImplementationVersion();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.