闲来无事,浏览网页看到有人说jar包为什么可以独立运行,想起前端时间写的jar打包后无法正常运行处理。jar解压缩后有多个文件夹,内部存放运行所需jar包和一些配置文件,本文做一个简单介绍。
JAR包和WAR包区别
在Java开发中,JAR
(Java ARchive)包和WAR
(Web Application ARchive)包都是用来打包文件和资源的归档文件,但它们的用途和内容有所不同。
1. 用途
- JAR包:通常用于存储Java类文件、与应用程序相关的元数据和资源(如文本、图片等)。JAR包可以作为库被其他应用程序依赖,或者包含可执行的Java应用程序。
- WAR包:专门用于分发Java Web应用程序。它包含Servlet、JSP、HTML、JavaScript、CSS等Web应用所需的所有组件。
2. 结构
- JAR包 :可以包含任意的文件和文件夹,通常包含一个
META-INF
目录,里面包含了MANIFEST.MF
文件,这个文件定义了包的版本、主类等信息。 - WAR包 :具有特定的目录结构,必须包含一个
WEB-INF
文件夹,其中包含web.xml
(描述了Web应用的结构和内容)、应用程序库(/WEB-INF/lib
目录下的JAR文件)和类文件(/WEB-INF/classes
目录)。
3. 使用场景
- JAR包:适用于任何Java应用,无论是桌面应用还是服务器端应用。
- WAR包:仅用于Web应用服务器如Tomcat、Jetty等,用于部署Web应用。
4. 执行
- JAR包 :如果包含主类,可以直接通过
java -jar
命令运行。 - WAR包:需要部署到支持Servlet和JSP的Web服务器或应用服务器上,不能直接运行。
JAR包和WAR包都是Java环境中用于打包文件的格式,但JAR包更通用,而WAR包专门用于Web应用的分发和部署。
解压缩后文件目录
JAR 包结构示例
myapp.jar
├── META-INF
│ ├── MANIFEST.MF
│ └── ...
├── com
│ └── example
│ ├── Main.class
│ ├── utils
│ │ ├── Helper.class
│ │ └── Constants.class
│ └── services
│ ├── UserService.class
│ └── ProductService.class
└── resources
├── config.properties
└── messages.properties
各个文件夹功能
1.META-INF:
- MANIFEST.MF: 这个文件包含关于 JAR 包的元数据,比如版本信息、主类(Main-Class)等。可以在这里指定程序的入口点。
plaintext
Manifest-Version: 1.0
Main-Class: com.example.Main
Class-Path: lib/dependency1.jar lib/dependency2.jar
Implementation-Title: My Application
Implementation-Version: 1.0.0
Implementation-Vendor: Example Corp
常见属性及功能解释:
Manifest-Version:
- 功能 : 指定清单文件的版本。通常是
1.0
。 - 示例 :
Manifest-Version: 1.0
Main-Class:
- 功能 : 指定JAR文件的主类,即包含
public static void main(String[] args)
方法的类。当使用java -jar
命令运行JAR文件时,Java虚拟机(JVM)会从这个类开始执行。 - 示例 :
Main-Class: com.example.Main
Class-Path:
- 功能: 指定运行时类路径。如果JAR文件依赖于其他JAR文件,可以在此处列出这些依赖。路径可以是相对路径或绝对路径。
- 示例 :
Class-Path: lib/dependency1.jar lib/dependency2.jar
Implementation-Title:
- 功能: 指定JAR文件的标题或名称。通常用于标识应用程序的名称。
- 示例 :
Implementation-Title: My Application
Implementation-Version:
- 功能: 指定JAR文件的版本。通常用于标识应用程序的版本号。
- 示例 :
Implementation-Version: 1.0.0
Implementation-Vendor:
- 功能: 指定JAR文件的供应商或开发者。通常用于标识开发该应用程序的公司或个人。
- 示例 :
Implementation-Vendor: Example Corp
2.com/example:
- Main.class : 主类,程序的入口点。通常包含
public static void main(String[] args)
方法。 - utils : 实用工具类文件夹。
- Helper.class: 一些辅助方法,可能用于日志记录、数据处理等。
- Constants.class: 常量定义类,存储全局常量。
- services : 业务逻辑类文件夹。
- UserService.class: 用户相关的服务类,可能包含用户注册、登录等方法。
- ProductService.class: 产品相关的服务类,可能包含产品查询、添加等方法。
3.resources:
- config.properties: 配置文件,存储应用程序的配置信息,比如数据库连接、API 密钥等。
- messages.properties: 国际化消息文件,存储应用程序中的文本信息,用于多语言支持。
为什么可以独立运行
Spring Boot 允许创建可独立运行的 JAR 文件,这种 JAR 文件被称为 "可执行 JAR" 或 "fat JAR"(有时也称为 "uber JAR")。这种 JAR 文件包含了所有必要的依赖库、类文件和资源,使得应用可以通过一个简单的 java -jar
命令运行,而无需额外的类路径设置。这是通过以下几个关键的配置和技术实现的:
1. 内嵌容器
Spring Boot 应用通常内嵌一个 Web 服务器(如 Tomcat、Jetty 或 Undertow),这意味着不需要部署到外部服务器。应用启动时,内嵌的 Web 服务器也会被启动,从而处理 HTTP 请求。
2. Spring Boot Starter
Spring Boot 使用一系列的 "starters" 来简化依赖管理。这些 starters 负责将应用所需的依赖库自动包含在最终的 JAR 文件中。例如,spring-boot-starter-web
会添加 Tomcat 和 Spring MVC 的依赖。
3. Spring Boot Maven 插件
这些插件负责构建过程中的重要任务,如打包应用和依赖项。特别是,它们会创建一个包含所有依赖的 JAR 文件,并且配置好 META-INF/MANIFEST.MF
文件,使其指向一个特殊的类加载器,这个类加载器能够从 JAR 文件内部加载类和资源。
4. 类加载器
Spring Boot 使用自定义的类加载器来从 JAR 文件内部的嵌套 JAR 文件中加载类。这意味着,尽管所有的库都被打包在一个单一的 JAR 文件中,Spring Boot 仍然能够从这些库中加载类。
5. MANIFEST.MF
配置
在 META-INF/MANIFEST.MF
文件中,Spring Boot 配置了 Main-Class
属性,该属性指向了 org.springframework.boot.loader.JarLauncher
。这是一个特殊的启动器,负责初始化 Spring Boot 应用。此外,还有 Start-Class
属性,它指定了包含 main
方法的实际入口类。
示例:MANIFEST.MF
中的关键配置
plaintext
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.MyApplication
这种配置方式使得 Spring Boot 应用可以作为一个独立程序运行,而不需要任何外部依赖,除了 Java 运行时环境。这极大地简化了部署和分发过程,使得开发者可以轻松地在不同环境中部署和运行他们的应用。