一、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容器了。