一、Jar
1.Jar包的作用
简单来说,jar包就是别人已经写好的一些类,然后对这些类进行打包。所以jar包本质上是一个类的工具包,引入这个jar包后就可以用这个包的类了,Maven的dependency引入的都是其他项目的jar包。可以将这些jar包引入到你的项目中,可以直接使用这些jar包中的类和属性,这些jar包一般放在lib目录下(IdeaJ中引入的maven依赖的jar包都在External Libraries中)。
JAR 文件格式以流行的 ZIP 文件格式为基础。与 ZIP 文件不同的是,JAR 文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和 JVM 这样的工具直接使用。在 JAR 中包含特殊的文件,如 manifests 和部署描述符,用来指示工具如何处理特定的 JAR。
2.Jar包的结构
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
Jar包解压后是两个文件夹
(1)BOOT_INF文件夹
在BOOT-INF中lib目录包含了Maven的jar依赖和第三方导入的jar依赖,这样才能顺利的运行该jar。classes目录则包含了全量的程序员编写的类对应的class文件。其中在BOOT-INF/classes目录中包含配置文件application.properties,该文件记录了项目的配置信息,如果是打成了war包,则可以直接修改该配置文件,重启tomcat即可修改相关的配置。
(2)META_INF文件夹
在META-INF目录中有三个较为重要的文件,pom.xml,pom.properties和与maven同级的MANIFEST.MF,
第一个:pom.xml,即项目对应的pom.xml,
第二个: pom.properties
#Created by Apache Maven 3.3.9
version=0.0.1-SNAPSHOT
groupId=com.cetc52
artifactId=platform
对应了项目的三个坐标。
第三个MANIFEST.MF
Manifest-Version: 1.0
Implementation-Title: platform
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: lenovo
Implementation-Vendor-Id: com.cetc52
Spring-Boot-Version: 2.0.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.cetc52.platform.PlatformApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_131
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-boot-starter-parent/platform
二、war
war包是Sun提出的一种web应用程序格式,与jar类似,是很多文件的压缩包。war包中的文件按照一定目录结构来组织。根据其根目录下包含有html和jsp文件,或者包含有这两种文件的目录,另外还有WEB-INF目录。通常在WEB-INF目录下含有一个web.xml文件和一个classes目录,web.xml是这个应用的配置文件,而classes目录下则包含编译好的servlet类和jsp,或者servlet所依赖的其他类(如JavaBean)。通常这些所依赖的类也可以打包成jar包放在WEB-INF下的lib目录下。
war是一个可以直接运行的web模块,通常用于网站,打成包部署到容器中。以Tomcat来说,将war包放置在其\webapps\目录下,然后启动Tomcat,这个包就会自动解压,就相当于发布了。
需要注意的是,如果要在外部的tomcat服务器上运行,那么必须要打成war包。
三、jar和war的对比
要注意的是,虽然WAR文件和JAR文件的文件格式是一样的,并且都是使用jar命令来创建,但就其应用来说,WAR文件和JAR文件是有根本区别的。JAR文件的目的是把类和相关的资源封装到压缩的归档文件中,而对于WAR文件来说,一个WAR文件代表了一个Web应用程序,它可以包含 Servlet、HTML页面、Java类、图像文件,以及组成Web应用程序的其他资源,而不仅仅是类的归档文件。
一般来说,使用SpringBoot自带的tomcat服务器的话,可以打成jar包;然是如果是要发布到远程的tomcat服务器的话,必须要打成war包发布。
四、SpringBoot打包
多模块的话,需要把前面的依赖的模块都打成jar包,最后要部署的包打成war包。Robin的包就是bean,dao,service和Controller都是打成了jar包(packging标签写的是jar),最后的app打成了war包(packaging标签写的是war),最后发布的就是war包,只有war包才能发布到远程服务器上,jar包只能在本地的SpringBoot自带的tomcat服务器上运行。
2.SpringBoot打包流程:(要写代码)
SpringBoot默认达成jar包,使用SpringBoot构想web应用,默认使用内置的Tomcat。但考虑到项目需要集群部署或者进行优化时,就需要打成war包部署到外部的Tomcat服务器中。
本文所使用SpringBoot版本为:2.0.3.RELEASE
(1)修改pom.xml文件将默认的jar方式改为war:
com.example
application
0.0.1-SNAPSHOT
war
(2)排除内置的Tomcat容器(两种方式都可):
方式一:排除spring-boot-starter-web中的Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
方式二:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
相当于compile,但是打包阶段做了exclude操作-->
<scope>provided</scope>
</dependency>
(3)继承SpringBootServletInitializer类,并实现configure方法:
为什么继承该类?看看SpringBootServletInitializer源码注释:Note that a WebApplicationInitializer is only needed if you are building a war file and deploying it. If you prefer to run an embedded web server then you won’t need this at all.(注意,如果您正在构建WAR文件并部署它,则需要WebApplicationInitializer。如果你喜欢运行一个嵌入式Web服务器,那么你根本不需要这个。)
可以用下面两种方式继承SpringBootServletInitializer。
方式一,启动类继承SpringBootServletInitializer实现configure:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
方式二,新增加一个类继承SpringBootServletInitializer实现configure:
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//此处的Application.class为带有@SpringBootApplication注解的启动类
return builder.sources(Application.class);
}
}
(4)注意事项:
使用外部Tomcat部署访问的时候,application.properties(或者application.yml)中的下列配置将失效,请使用tomcat的端口,tomcat,webapps下项目名进行访问。
server.port=xxx
server.servlet.context-path=xxx
为了防止应用上下文所导致的项目访问资源加载不到的问题,建议pom.xml文件中标签下添加标签:
<build>
<!-- 应与application.properties(或application.yml)中context-path保持一致 -->
<finalName>war包名称</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
使用mvn命令行打包,运行:
clean是清除之前的包,-Dmaven.test.skip=true是忽略测试代码
(5)打包命令
a:以jar 方式打包,使用内置Tomcat:mvn clean install -Dmaven.test.skip=true
运行打好的包的命令:java -jar 包名.jar
b:war方式打包,使用外置Tomcat:mvn clean package -Dmaven.test.skip=true
运行打好的包(war包是服务器自动运行的):${Tomcat_home}/bin/目录下执行startup.bat(windows)或者startup.sh(linux)
(6)jar和war启动的区别
jar包:执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器
war包: 先是启动Servlet服务器,服务器启动Springboot应用(springBootServletInitizer),然后启动IOC容器。SpringBootServletInitializer实例执行onStartup方法的时候会通过createRootApplicationContext方法来执行run方法,接下来的过程就同以jar包形式启动的应用的run过程一样了,在内部会创建IOC容器并返回,只是以war包形式的应用在创建IOC容器过程中,不再创建Servlet容器了。