Spring Boot 打成可执行/可依赖jar包

3,578 阅读4分钟

第一次使用Sprig Boot, 正当我折服于他的强大时,老板跟我说,你要写一个基于Spring boot的runner, 然后小A会写一个SDK,你把SDK依赖进去就可以了。 我: 什么,我就写一个runner,然后就没有然后了。 他: 当然不是,你还要写配置呢, 所有的配置文件。 我: 好吧好吧,你是老板,你说咋写就咋写。

但是我不能就没有然后了呀,我可是一个上进的好少年,Spring boot本身打出来的包就是可以运行的,我这个runner不是多余的吗, 它不会糊涂吗?抱着这个想法, 我在本地试了一下,果然,引入依赖后根本无法识别包在哪里。 这是为什么呢,那我们一点点来看哈。

假设项目结构

<groupId>com.shuanger</groupId>
<artifactId>package_example</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>

Spring boot 生成可执行的jar包

无论你用什么方式创建的spring boot应用,你应该都会看到下面的maven依赖,这个spring-boot-maven-plugin是用来干什么的呢?他就是用来的maven package基础上,再一次的专门为spring boot再打一次包,俗称repackage。

maven 配置

<plugins>
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
  </plugin>
</plugins>

此时运行mvn package 命令, 会在项目的target目录中看到生成的jar包: package_example-1.0.0.jar, 同时也会看到package_example-1.0.0.jar.original, 该文件仅包含应用本地资源(如编译后的classes目录下的文件),未引入第三方依赖资源,索引占用的空间很小, 我们今天的主角是package_example-1.0.0.jar,此时你进入target目录下,运行如下命令:

java -jar package_example-1.0.0.jar

这就是一个可以执行的jar包

需要注意的使用这种配置的前提是使用了spring-boot-starter-parent作为parent,如果使用的是自己定义的parent,需要修改maven配置如下:

<plugins>
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
          <goals>
             <goal>repackage</goal>
          </goals>
        </execution>
    </executions>
  </plugin>
</plugins>

使用上述配置,也会生成跟前面提到的一样的jar包。

Spring Boot 生成可依赖的jar包

为了生成可以被依赖的jar包,可以采用两种方式,一种方式是使用spring-boot-maven-plugin, 一种是使用maven-jar-plugin。 下面我们分别看一下二者的配置。 首先我们来看看使用Spring-boot-maven-plugin的maven配置:

maven 配置

<plugins>
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
          <goals>
             <goal>repackage</goal>
          </goals>
        </execution>
    </executions>
    <configuration>
      <classifier>exec</classifier>
    </configuration>
  </plugin>
</plugins>

使用上述配置会在target下生成两个jar包,一个是可以被依赖的jar包:package_example-1.0.0.jar。 一个是执行的jar包:package_example-1.0.0-exec.jar。

如上配置打出来的可以被依赖的jar包包含的一些不需要的文件,比如application.properties/application.yml.这些配置文件可能会在引用它的项目中造成不必要的覆盖。 所以我们想排除这是文件,这时就需要使用maven-jar-plugin。 让我们看看使用maven-jar-plugin的maven配置:

maven 配置

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
  <artifactId>maven-jar-plugin</artifactId>
    <executions>
	  <execution>
	    <id>lib</id>
		<phase>package</phase>
		<goals>
		  <goal>jar</goal>
		</goals>
		<configuration>
		 <classifier>lib</classifier>
		  <excludes>
                     <exclude>application.yml</exclude>
		  </excludes>
		</configuration>
        </execution>
     </executions>
</plugin>

使用上述配置,也会在target下生成两个jar包,一个是可以被依赖的jar包:package_example-1.0.0-lib.jar。 一个是执行的jar包:package_example-1.0.0.jar.那生成的可执行的jar包和可被依赖的jar包有什么区别呢。来让我们看一看两个包的结构:

                                           可执行的jar包:

                                           可被依赖的jar包

看到没,可执行的jar包多了一个BOOT-INF目录,

  • BOOT-INF/classes目录存放应用编译后的class文件
  • BOOT_INF/lib目录存放应用依赖的jar包
  • META-INF/目录存放应用相关的元信息,如MANIFEST.MF文件
  • org/目录存放Spring Boot相关的class文件

这里需要注意的是引用使用了classifier生成的包时,如可被依赖的package_example-1.0.0-lib.jar包时要加入classifier,配置如下:

<dependency>
   <groupId>com.shuanger</groupId>
   <artifactId>package_example</artifactId>
   <version>1.0.0</version>
   <classifier>lib</classifier>
</dependency>

好了,今天的Spring boot打包就写到这里,如果有新的发现我会继续补充。