스프링 부트 앱에서 META-INF/MANIFEST.MF 파일을 읽는 방법은 무엇입니까?
스프링 부트 웹 앱(jar 파일에 포함)에서 META-INF/MANIFEST.MF 파일을 읽으려고 합니다.
다음 코드를 시도하고 있습니다.
InputStream is = getClass().getResourceAsStream("/META-INF/MANIFEST.MF");
Properties prop = new Properties();
prop.load( is );
하지만 분명히 스프링 부트의 배경에는 다른 manifest.mf가 로드되어 있습니다(META-INF 폴더에 위치한 내 것이 아님).
스프링 부트 앱에서 매니페스트 앱을 읽는 방법을 아는 사람이 있습니까?
업데이트: 몇 가지 조사 후에 나는 일반적인 방법을 사용하여 manifest.mf 파일을 읽는 것을 봄 부팅 애플리케이션에서 이것이 액세스되고 있는 Jar라는 것을 알게 되었습니다.
org.springframework.boot.loader.jar.JarFile
저는 java.lang을 사용합니다.읽기 패키지Implementation-Version매니페스트에서 봄 부트의 속성.
String version = Application.class.getPackage().getImplementationVersion();
그Implementation-Version은 속을구합니에서 설정해야 .build.gradle
jar {
baseName = "my-app"
version = "0.0.1"
manifest {
attributes("Implementation-Version": version)
}
}
이것만 추가하면 됩니다.
InputStream is = this.getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
Properties prop = new Properties();
try {
prop.load( is );
} catch (IOException ex) {
Logger.getLogger(IndexController.class.getName()).log(Level.SEVERE, null, ex);
}
나를 위해 일하는 것.
참고:
getClass().getClassLoader()는 중요합니다.
그리고.
"/META-INF/MANIFIST.MF"가 아닌 "META-INF/MANIFIST.MF"
감사합니다 알렉산다르
거의 모든 jar 파일은 매니페스트 파일과 함께 제공되므로 코드는 클래스 경로에서 찾을 수 있는 첫 번째 파일을 반환합니다.
왜 매니페스트를 원합니까?자바에서 사용하는 파일입니다.한 사용자 ▁a▁in▁else처럼 다른 곳에 두세요. 예를 들어,.properties 파일 ㅠㅠㅠㅠㅠㅠㅠ.classjava.
업데이트 2
질문이 아닌 아래 댓글에서 언급한 것처럼, 실제 목표는 매니페스트의 버전 정보입니다.Java는 이미 해당 정보를 클래스와 함께 제공합니다.
설령 당신이 그것을 찾을 수 있을지라도, 직접 그 매니페스토를 읽으려고 하지 마세요.
업데이트 1
매니페스트 파일은 다음과 같은 것이 아닙니다.Properties파일입니다. 그것보다 훨씬 더 복잡한 구조입니다.
JAR 파일 사양의 Java 설명서에 있는 예제를 참조하십시오.
Manifest-Version: 1.0
Created-By: 1.7.0 (Sun Microsystems Inc.)
Name: common/class1.class
SHA-256-Digest: (base64 representation of SHA-256 digest)
Name: common/class2.class
SHA1-Digest: (base64 representation of SHA1 digest)
SHA-256-Digest: (base64 representation of SHA-256 digest)
당신이 볼 수 있듯이.Name그리고.SHA-256-Digest두 번 이상 발생합니다. 그Properties클래스는 그것을 처리할 수 없습니다, 왜냐하면 그것은 단지.Map키는 고유해야 합니다.
Spring docs에서 테스트하고 검색한 후 매니페스트 파일을 읽을 수 있는 방법을 찾았습니다.
먼저, Spring Boot은 리소스 로드 방법을 변경하는 자체 ClassLoader를 구현합니다.에 전화할 때.getResource()Spring Boot은 클래스 경로에서 사용할 수 있는 모든 JAR 목록에서 지정된 리소스 이름과 일치하는 첫 번째 리소스를 로드하며, 앱 jar가 첫 번째 선택 사항이 아닙니다.
따라서 다음과 같은 명령을 실행할 때:
getClassLoader().getResourceAsStream("/META-INF/MANIFEST.MF");
클래스 경로의 모든 jar에서 발견된 첫 번째 MEANFIG.MF 파일이 반환됩니다.제 경우에는 JDK 병 라이브러리에서 가져온 것입니다.
솔루션:
저는 "/META-INF/MANIFest.MF" 리소스가 포함된 앱에서 로드된 모든 Jars의 목록을 간신히 가져와서 해당 리소스가 제 애플리케이션 jar에서 온 것인지 확인했습니다.그렇다면 매니페스트.MF 파일을 읽고 다음과 같이 앱으로 돌아갑니다.
private Manifest getManifest() {
// get the full name of the application manifest file
String appManifestFileName = this.getClass().getProtectionDomain().getCodeSource().getLocation().toString() + JarFile.MANIFEST_NAME;
Enumeration resEnum;
try {
// get a list of all manifest files found in the jars loaded by the app
resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
while (resEnum.hasMoreElements()) {
try {
URL url = (URL)resEnum.nextElement();
// is the app manifest file?
if (url.toString().equals(appManifestFileName)) {
// open the manifest
InputStream is = url.openStream();
if (is != null) {
// read the manifest and return it to the application
Manifest manifest = new Manifest(is);
return manifest;
}
}
}
catch (Exception e) {
// Silently ignore wrong manifests on classpath?
}
}
} catch (IOException e1) {
// Silently ignore wrong manifests on classpath?
}
return null;
}
이 메서드는 Manifest 개체 내의 manifest.mf 파일에서 모든 데이터를 반환합니다.
JAVA를 사용하여 jar 파일에서 매니페스트.MF 파일을 읽는 것에서 솔루션의 일부를 빌렸습니다.
Spring의 리소스 해상도를 활용하고 있습니다.
@Service
public class ManifestService {
protected String ciBuild;
public String getCiBuild() { return ciBuild; }
@Value("${manifest.basename:/META-INF/MANIFEST.MF}")
protected void setManifestBasename(Resource resource) {
if (!resource.exists()) return;
try (final InputStream stream = resource.getInputStream()) {
final Manifest manifest = new Manifest(stream);
ciBuild = manifest.getMainAttributes().getValue("CI-Build");
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}
여기서 우리는CI-Build또한 예제를 쉽게 확장하여 다른 속성을 로드할 수 있습니다.
public Properties readManifest() throws IOException {
Object inputStream = this.getClass().getProtectionDomain().getCodeSource().getLocation().getContent();
JarInputStream jarInputStream = new JarInputStream((InputStream) inputStream);
Manifest manifest = jarInputStream.getManifest();
Attributes attributes = manifest.getMainAttributes();
Properties properties = new Properties();
properties.putAll(attributes);
return properties;
}
try {
final JarFile jarFile = (JarFile) this.getClass().getProtectionDomain().getCodeSource().getLocation().getContent();
final Manifest manifest = jarFile.getManifest();
final Map<Object, Object> manifestProps = manifest.getMainAttributes().entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
...
} catch (final IOException e) {
LOG.error("Unable to read MANIFEST.MF", e);
...
}
이 기능은 다음을 통해 앱을 실행하는 경우에만 작동합니다.java -jar명령입니다. 통합 테스트를 만들면 작동하지 않습니다.
- manifest.manifest 파일을 jar에서 사용할 수 있습니다.
- 아래 코드를 사용하여 프로그램 또는 응용 프로그램의 클래스 경로를 확인합니다.
String classpath = System.getProperty("java.class.path");
System.out.println("classpath:"+classpath);
코드 인쇄 jar 경로(-classpath: D:\ABC\target\) 위의 경우ABC.jar) 그러면 아래 코드를 사용할 수 있습니다.그렇지 않으면 IDE에서 jar 경로를 클래스 경로로 설정해야 합니다(편집 구성 -> 수정 옵션 -> jar 파일 클래스 경로 추가).
InputStream is = this.getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
Properties prop = new Properties();
try {
prop.load( is );
} catch (IOException ex) {
Logger.getLogger(IndexController.class.getName()).log(Level.SEVERE, null, ex);
}
언급URL : https://stackoverflow.com/questions/32293962/how-to-read-my-meta-inf-manifest-mf-file-in-a-spring-boot-app
'programing' 카테고리의 다른 글
| Oracle 및 SQL Server 성능 테스트를 게시하는 것은 라이센스 위반입니까? (0) | 2023.06.28 |
|---|---|
| 파일 업로드 각도? (0) | 2023.06.28 |
| Git 저장소에서 삭제된 여러 파일을 제거하는 방법 (0) | 2023.06.28 |
| 기본 및 하위 클래스를 사용한 Python 장치 테스트 (0) | 2023.06.28 |
| 복제된 원격 저장소와 원래 원격 저장소 간의 차이 (0) | 2023.06.28 |