问题描述
IDEA创建SpringBoot 2.6.13项目(仅引入SpringMVC依赖),对生成的代码不做修改直接Maven打包。但运行报错:
# java -jar xxx.jar
no main manifest attribute, in xxx.jar
检查jar包,
# jar -xvf xxx.jar
# cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Build-Jdk-Spec: 1.8
Created-By: Maven JAR Plugin 3.3.0
解决办法
pom.xml
中注释掉创建时spring-boot-maven-plugin
的<configuration>
的<skip>true</skip>
(忽略配置):
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.MinWebDemoApplication</mainClass>
<!-- <skip>true</skip>-->
重新用maven打包(先clean, 再package),即可✅。
注意到,此时META-INF/MANIFEST.MF
包含了Start-Class和Main-Class
# jar -xvf xxx.jar
# cat META-INF/MANIFEST.MF
...
Start-Class: com.example.MinWebDemoApplication
...
Main-Class: org.springframework.boot.loader.JarLauncher
附录
root@node01:~/web-app# java -jar min-web-demo-0.0.1-SNAPSHOT.jar
no main manifest attribute, in min-web-demo-0.0.1-SNAPSHOT.jar
root@node01:~/web-app# jar -xvf min-web-demo-0.0.1-SNAPSHOT.jar
created: META-INF/
inflated: META-INF/MANIFEST.MF
created: com/
created: com/example/
created: com/example/demos/
created: com/example/demos/web/
created: static/
created: META-INF/maven/
created: META-INF/maven/com.example/
created: META-INF/maven/com.example/min-web-demo/
inflated: application.properties
inflated: com/example/demos/web/BasicController.class
inflated: com/example/demos/web/PathVariableController.class
inflated: com/example/demos/web/User.class
inflated: com/example/MinWebDemoApplication.class
inflated: static/index.html
inflated: META-INF/maven/com.example/min-web-demo/pom.xml
inflated: META-INF/maven/com.example/min-web-demo/pom.properties
root@node01:~/web-app# cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Build-Jdk-Spec: 1.8
Created-By: Maven JAR Plugin 3.3.0
root@node01:~/web-app# jar -xvf min-web-demo-0.0.2-SNAPSHOT.jar
created: META-INF/
inflated: META-INF/MANIFEST.MF
created: org/
created: org/springframework/
created: org/springframework/boot/
created: org/springframework/boot/loader/
inflated: org/springframework/boot/loader/ClassPathIndexFile.class
inflated: org/springframework/boot/loader/ExecutableArchiveLauncher.class
inflated: org/springframework/boot/loader/JarLauncher.class
inflated: org/springframework/boot/loader/LaunchedURLClassLoader$DefinePackageCallType.class
inflated: org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
inflated: org/springframework/boot/loader/LaunchedURLClassLoader.class
inflated: org/springframework/boot/loader/Launcher.class
inflated: org/springframework/boot/loader/MainMethodRunner.class
inflated: org/springframework/boot/loader/PropertiesLauncher$1.class
inflated: org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class
inflated: org/springframework/boot/loader/PropertiesLauncher$ClassPathArchives.class
inflated: org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class
inflated: org/springframework/boot/loader/PropertiesLauncher.class
inflated: org/springframework/boot/loader/WarLauncher.class
created: org/springframework/boot/loader/archive/
inflated: org/springframework/boot/loader/archive/Archive$Entry.class
inflated: org/springframework/boot/loader/archive/Archive$EntryFilter.class
inflated: org/springframework/boot/loader/archive/Archive.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive$AbstractIterator.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive$ArchiveIterator.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive$EntryIterator.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive$SimpleJarFileArchive.class
inflated: org/springframework/boot/loader/archive/ExplodedArchive.class
inflated: org/springframework/boot/loader/archive/JarFileArchive$AbstractIterator.class
inflated: org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class
inflated: org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class
inflated: org/springframework/boot/loader/archive/JarFileArchive$NestedArchiveIterator.class
inflated: org/springframework/boot/loader/archive/JarFileArchive.class
created: org/springframework/boot/loader/data/
inflated: org/springframework/boot/loader/data/RandomAccessData.class
inflated: org/springframework/boot/loader/data/RandomAccessDataFile$1.class
inflated: org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class
inflated: org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class
inflated: org/springframework/boot/loader/data/RandomAccessDataFile.class
created: org/springframework/boot/loader/jar/
inflated: org/springframework/boot/loader/jar/AbstractJarFile$JarFileType.class
inflated: org/springframework/boot/loader/jar/AbstractJarFile.class
inflated: org/springframework/boot/loader/jar/AsciiBytes.class
inflated: org/springframework/boot/loader/jar/Bytes.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryEndRecord$1.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64End.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64Locator.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryParser.class
inflated: org/springframework/boot/loader/jar/CentralDirectoryVisitor.class
inflated: org/springframework/boot/loader/jar/FileHeader.class
inflated: org/springframework/boot/loader/jar/Handler.class
inflated: org/springframework/boot/loader/jar/JarEntry.class
inflated: org/springframework/boot/loader/jar/JarEntryCertification.class
inflated: org/springframework/boot/loader/jar/JarEntryFilter.class
inflated: org/springframework/boot/loader/jar/JarFile$1.class
inflated: org/springframework/boot/loader/jar/JarFile$JarEntryEnumeration.class
inflated: org/springframework/boot/loader/jar/JarFile.class
inflated: org/springframework/boot/loader/jar/JarFileEntries$1.class
inflated: org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class
inflated: org/springframework/boot/loader/jar/JarFileEntries$Offsets.class
inflated: org/springframework/boot/loader/jar/JarFileEntries$Zip64Offsets.class
inflated: org/springframework/boot/loader/jar/JarFileEntries$ZipOffsets.class
inflated: org/springframework/boot/loader/jar/JarFileEntries.class
inflated: org/springframework/boot/loader/jar/JarFileWrapper.class
inflated: org/springframework/boot/loader/jar/JarURLConnection$1.class
inflated: org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class
inflated: org/springframework/boot/loader/jar/JarURLConnection.class
inflated: org/springframework/boot/loader/jar/StringSequence.class
inflated: org/springframework/boot/loader/jar/ZipInflaterInputStream.class
created: org/springframework/boot/loader/jarmode/
inflated: org/springframework/boot/loader/jarmode/JarMode.class
inflated: org/springframework/boot/loader/jarmode/JarModeLauncher.class
inflated: org/springframework/boot/loader/jarmode/TestJarMode.class
created: org/springframework/boot/loader/util/
inflated: org/springframework/boot/loader/util/SystemPropertyUtils.class
created: BOOT-INF/
created: BOOT-INF/classes/
created: BOOT-INF/classes/com/
created: BOOT-INF/classes/com/example/
created: BOOT-INF/classes/com/example/demos/
created: BOOT-INF/classes/com/example/demos/web/
created: BOOT-INF/classes/static/
created: META-INF/maven/
created: META-INF/maven/com.example/
created: META-INF/maven/com.example/min-web-demo/
inflated: BOOT-INF/classes/application.properties
inflated: BOOT-INF/classes/com/example/demos/web/BasicController.class
inflated: BOOT-INF/classes/com/example/demos/web/PathVariableController.class
inflated: BOOT-INF/classes/com/example/demos/web/User.class
inflated: BOOT-INF/classes/com/example/MinWebDemoApplication.class
inflated: BOOT-INF/classes/static/index.html
inflated: META-INF/maven/com.example/min-web-demo/pom.xml
inflated: META-INF/maven/com.example/min-web-demo/pom.properties
created: BOOT-INF/lib/
extracted: BOOT-INF/lib/spring-boot-2.6.13.jar
extracted: BOOT-INF/lib/spring-boot-autoconfigure-2.6.13.jar
extracted: BOOT-INF/lib/logback-classic-1.2.11.jar
extracted: BOOT-INF/lib/logback-core-1.2.11.jar
extracted: BOOT-INF/lib/log4j-to-slf4j-2.17.2.jar
extracted: BOOT-INF/lib/log4j-api-2.17.2.jar
extracted: BOOT-INF/lib/jul-to-slf4j-1.7.36.jar
extracted: BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar
extracted: BOOT-INF/lib/snakeyaml-1.29.jar
extracted: BOOT-INF/lib/jackson-databind-2.13.4.2.jar
extracted: BOOT-INF/lib/jackson-annotations-2.13.4.jar
extracted: BOOT-INF/lib/jackson-core-2.13.4.jar
extracted: BOOT-INF/lib/jackson-datatype-jdk8-2.13.4.jar
extracted: BOOT-INF/lib/jackson-datatype-jsr310-2.13.4.jar
extracted: BOOT-INF/lib/jackson-module-parameter-names-2.13.4.jar
extracted: BOOT-INF/lib/tomcat-embed-core-9.0.68.jar
extracted: BOOT-INF/lib/tomcat-embed-el-9.0.68.jar
extracted: BOOT-INF/lib/tomcat-embed-websocket-9.0.68.jar
extracted: BOOT-INF/lib/spring-web-5.3.23.jar
extracted: BOOT-INF/lib/spring-beans-5.3.23.jar
extracted: BOOT-INF/lib/spring-webmvc-5.3.23.jar
extracted: BOOT-INF/lib/spring-aop-5.3.23.jar
extracted: BOOT-INF/lib/spring-context-5.3.23.jar
extracted: BOOT-INF/lib/spring-expression-5.3.23.jar
extracted: BOOT-INF/lib/slf4j-api-1.7.36.jar
extracted: BOOT-INF/lib/spring-core-5.3.23.jar
extracted: BOOT-INF/lib/spring-jcl-5.3.23.jar
extracted: BOOT-INF/lib/spring-boot-jarmode-layertools-2.6.13.jar
inflated: BOOT-INF/classpath.idx
inflated: BOOT-INF/layers.idx
root@node01:~/web-app# cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.example.MinWebDemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.6.13
Created-By: Maven JAR Plugin 3.3.0
Main-Class: org.springframework.boot.loader.JarLauncher
root@node01:~/web-app# java -jar min-web-demo-0.0.2-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.13)
2024-02-15 12:54:39.935 INFO 48664 --- [ main] com.example.MinWebDemoApplication : Starting MinWebDemoApplication using Java 1.8.0_392 on node01 with PID 48664 (/root/web-app/min-web-demo-0.0.2-SNAPSHOT.jar started by root in /root/web-app)
2024-02-15 12:54:39.937 INFO 48664 --- [ main] com.example.MinWebDemoApplication : No active profile set, falling back to 1 default profile: "default"
2024-02-15 12:54:40.659 INFO 48664 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-02-15 12:54:40.670 INFO 48664 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-15 12:54:40.670 INFO 48664 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68]
2024-02-15 12:54:40.725 INFO 48664 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-15 12:54:40.725 INFO 48664 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 742 ms
2024-02-15 12:54:40.886 INFO 48664 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
2024-02-15 12:54:40.960 INFO 48664 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-15 12:54:40.967 INFO 48664 --- [ main] com.example.MinWebDemoApplication : Started MinWebDemoApplication in 1.343 seconds (JVM running for 1.751)