source

런타임에 Maven 아티팩트 버전 가져오기

factcode 2022. 9. 1. 23:10
반응형

런타임에 Maven 아티팩트 버전 가져오기

메이븐 아티팩트의 JAR에서 프로젝트를 발견했습니다.version Atribut은 다음 2개의 파일에 포함되어 있습니다.

META-INF/maven/${groupId}/${artifactId}/pom.properties
META-INF/maven/${groupId}/${artifactId}/pom.xml

런타임에 이 버전을 읽을 수 있는 권장 방법이 있습니까?

특정 라이브러리/클래스의 버전 정보를 얻기 위해 Maven 고유 파일에 액세스할 필요가 없습니다.

간단하게 사용할 수 있습니다.getClass().getPackage().getImplementationVersion().jar 파일에 저장된 버전 정보를 가져오려면MANIFEST.MF. 다행히 메이븐은 충분히 똑똑하다. 안타깝게도 Maven은 매니페스트에도 기본적으로 올바른 정보를 쓰지 않습니다!

그 대신, 이 명령어를 수정해야 합니다.<archive>의 설정 요소maven-jar-plugin세팅하다addDefaultImplementationEntries그리고.addDefaultSpecificationEntries로.true, 다음과 같이 합니다.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>                   
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
</plugin>

이 구성을 사내에 도입하는 것이 이상적입니다.pom아니면 다른 베이스 트레이너일 수도 있어요

의 상세 문서<archive>요소는 Maven Archive 문서에서 찾을 수 있습니다.

위의 답변에 대한 후속 조치를 취하십시오..war아티팩트, 동일한 구성을 적용해야만 했습니다.maven-war-plugin,보다는maven-jar-plugin:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1</version>
    <configuration>
        <archive>                   
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
</plugin>

이것으로 버전 정보가 에 추가되었습니다.MANIFEST.MF(프로젝트 기간 중)WEB-INF/lib.war)

다음은 pom.properties에서 버전을 가져와 매니페스트에서 가져오는 방법입니다.

public synchronized String getVersion() {
    String version = null;

    // try to load from maven properties first
    try {
        Properties p = new Properties();
        InputStream is = getClass().getResourceAsStream("/META-INF/maven/com.my.group/my-artefact/pom.properties");
        if (is != null) {
            p.load(is);
            version = p.getProperty("version", "");
        }
    } catch (Exception e) {
        // ignore
    }

    // fallback to using Java API
    if (version == null) {
        Package aPackage = getClass().getPackage();
        if (aPackage != null) {
            version = aPackage.getImplementationVersion();
            if (version == null) {
                version = aPackage.getSpecificationVersion();
            }
        }
    }

    if (version == null) {
        // we could not compute the version so use a blank
        version = "";
    }

    return version;
} 

사용하고 있다maven-assembly-plugin제 메이븐 포장을 위해서요.Joachim Sauer의 답변에서 Apache Maven Archiver를 사용하는 것도 효과적일 수 있습니다.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution .../>
    </executions>
</plugin>

archiever는 maven 공유 컴포넌트 중 하나이기 때문에 여러 maven Building 플러그인이 사용할 수 있으며 다음과 같은 두 개 이상의 플러그인을 도입할 경우 충돌이 발생할 수 있습니다.archive설정을 지정합니다.

나는 여기서 두 가지 주요 접근법에 대해 잠시 시간을 보냈지만, 그들은 나에게 효과가 없었다.저는 Netbeans를 빌드에 사용하고 있습니다.더 많은 일이 있을지도 모릅니다.Maven 3에서 몇 가지 오류와 경고가 있었지만 수정은 쉬웠다고 생각합니다.별 거 아니야.

DZone에 관한 이 기사에서 유지보수가 가능하고 구현이 간단해 보이는 답변을 찾았습니다.

이미 리소스/구성 서브폴더가 있고 파일 이름을 app.properties로 지정했습니다.이것에 의해, 서포트 URL등에서 보존할 수 있는 정보를 보다 잘 반영할 수 있습니다.

유일한 경고는 Netbeans가 IDE 필터링을 해제해야 한다는 경고를 보낸다는 것입니다.장소와 방법을 알 수 없습니다.현시점에서는 효과가 없습니다.내가 그 다리를 건너야 한다면, 아마도 그것에 대한 작업이 있을 것이다.행운을 빌어요.

Eclipse 및 Maven 빌드에서 이 작업을 실행하려면addDefaultImplementationEntries ★★★★★★★★★★★★★★★★★」addDefaultSpecificationEntries는 다른합니다.

public synchronized static final String getVersion() {
    // Try to get version number from pom.xml (available in Eclipse)
    try {
        String className = getClass().getName();
        String classfileName = "/" + className.replace('.', '/') + ".class";
        URL classfileResource = getClass().getResource(classfileName);
        if (classfileResource != null) {
            Path absolutePackagePath = Paths.get(classfileResource.toURI())
                    .getParent();
            int packagePathSegments = className.length()
                    - className.replace(".", "").length();
            // Remove package segments from path, plus two more levels
            // for "target/classes", which is the standard location for
            // classes in Eclipse.
            Path path = absolutePackagePath;
            for (int i = 0, segmentsToRemove = packagePathSegments + 2;
                    i < segmentsToRemove; i++) {
                path = path.getParent();
            }
            Path pom = path.resolve("pom.xml");
            try (InputStream is = Files.newInputStream(pom)) {
                Document doc = DocumentBuilderFactory.newInstance()
                        .newDocumentBuilder().parse(is);
                doc.getDocumentElement().normalize();
                String version = (String) XPathFactory.newInstance()
                        .newXPath().compile("/project/version")
                        .evaluate(doc, XPathConstants.STRING);
                if (version != null) {
                    version = version.trim();
                    if (!version.isEmpty()) {
                        return version;
                    }
                }
            }
        }
    } catch (Exception e) {
        // Ignore
    }

    // Try to get version number from maven properties in jar's META-INF
    try (InputStream is = getClass()
        .getResourceAsStream("/META-INF/maven/" + MAVEN_PACKAGE + "/"
                + MAVEN_ARTIFACT + "/pom.properties")) {
        if (is != null) {
            Properties p = new Properties();
            p.load(is);
            String version = p.getProperty("version", "").trim();
            if (!version.isEmpty()) {
                return version;
            }
        }
    } catch (Exception e) {
        // Ignore
    }

    // Fallback to using Java API to get version from MANIFEST.MF
    String version = null;
    Package pkg = getClass().getPackage();
    if (pkg != null) {
        version = pkg.getImplementationVersion();
        if (version == null) {
            version = pkg.getSpecificationVersion();
        }
    }
    version = version == null ? "" : version.trim();
    return version.isEmpty() ? "unknown" : version;
}

Java 빌드가 타겟클래스를 "target/classes" 이외의 장소에 배치하는 경우 segmentsToRemove 값을 조정해야 할 수 있습니다.

spring boot 어플리케이션에서는 최근 jdk를 버전 12로 업데이트하기 전까지 승인된 답변의 솔루션이 작동했습니다.다른 모든 답변도 시도해 봤지만 제대로 작동하지 않았다.

첫 했습니다. 뒤에 .@SpringBootApplication

@PropertySources({ 
        @PropertySource("/META-INF/maven/com.my.group/my-artefact/pom.properties")
})

값및.appVersion이치노

@Value("${version}")
private String appVersion;

그게 도움이 됐으면 좋겠어요.

스프링 부트를 사용하는 경우 BuildProperties 클래스를 사용할 수 있습니다.

오픈에서 다음 토막을 참고하십시오.API 컨피규레이션클래스의 예:

@Configuration
@RequiredArgsConstructor // <- lombok
public class OpenApi {

    private final BuildProperties buildProperties; // <- you can also autowire it

    @Bean
    public OpenAPI yourBeautifulAPI() {
        return new OpenAPI().info(new Info()
            .title(buildProperties.getName())
            .description("The description")
            .version(buildProperties.getVersion())
            .license(new License().name("Your company")));
    }
}

매우 늦은 답변인 것은 알지만, 이 링크에서 가 한 일을 공유하겠습니다.

pom.xml에 다음 코드를 추가했습니다.

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>build-info</id>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

또한 이 어드바이스 컨트롤러는 버전을 모델 속성으로 가져옵니다.

import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class CommonControllerAdvice
{
       @Autowired
       BuildProperties buildProperties;
    
       @ModelAttribute("version")
       public String getVersion() throws IOException
       {
          String version = buildProperties.getVersion();
          return version;
       }
    }

제가 찾은 가장 우아한 해결책은 J사의 입니다.Chomel: 링크

속성을 가진 해킹은 필요 없습니다.향후 링크가 끊기는 문제를 피하기 위해 여기서 링크를 복제합니다.

YourClass.class.getPackage().getImplementationVersion();

그리고 (아직 manifest 파일이 jar/war에 없는 경우 Intelij Idea의 Maven에 이미 포함되어 있습니다) pom.xml의 작은 변경도 필요합니다.

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

Maven과 호환되며 모든 클래스(따라서 서드파티 클래스에도 사용 가능)에서 사용할 수 있는 심플한 솔루션:

    private static Optional<String> getVersionFromManifest(Class<?> clazz) {
        try {
            File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
            if (file.isFile()) {
                JarFile jarFile = new JarFile(file);
                Manifest manifest = jarFile.getManifest();
                Attributes attributes = manifest.getMainAttributes();
                final String version = attributes.getValue("Bundle-Version");
                return Optional.of(version);
            }
        } catch (Exception e) {
            // ignore
        }
        return Optional.empty();
    }

없는 .Optional<> thatnull존재하지 않는 경우(빠른 디버깅/디버깅용):

    private static String getVersionFromManifest(Class<?> clazz) {
        try {
            File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
            if (file.isFile()) {
                JarFile jarFile = new JarFile(file);
                Manifest manifest = jarFile.getManifest();
                Attributes attributes = manifest.getMainAttributes();
                return attributes.getValue("Bundle-Version");
            }
        } catch (Exception e) {
            // ignore
        }
        return null;
    }

Maven 프로젝트와 함께 전쟁 파일에 있는 EJB용 Java 8 변형.EAP 7.0에서 테스트 완료.

@Log4j // lombok annotation
@Startup
@Singleton
public class ApplicationLogic {

    public static final String DEVELOPMENT_APPLICATION_NAME = "application";

    public static final String DEVELOPMENT_GROUP_NAME = "com.group";

    private static final String POM_PROPERTIES_LOCATION = "/META-INF/maven/" + DEVELOPMENT_GROUP_NAME + "/" + DEVELOPMENT_APPLICATION_NAME + "/pom.properties";

    // In case no pom.properties file was generated or wrong location is configured, no pom.properties loading is done; otherwise VERSION will be assigned later
    public static String VERSION = "No pom.properties file present in folder " + POM_PROPERTIES_LOCATION;

    private static final String VERSION_ERROR = "Version could not be determinated";

    {    
        Optional.ofNullable(getClass().getResourceAsStream(POM_PROPERTIES_LOCATION)).ifPresent(p -> {

            Properties properties = new Properties();

            try {

                properties.load(p);

                VERSION = properties.getProperty("version", VERSION_ERROR);

            } catch (Exception e) {

                VERSION = VERSION_ERROR;

                log.fatal("Unexpected error occured during loading process of pom.properties file in META-INF folder!");
            }
        });
    }
}

언급URL : https://stackoverflow.com/questions/2712970/get-maven-artifact-version-at-runtime

반응형