SpringBoot入门之spring-boot-maven-plugin
spring-boot-maven-plugin插件是将springboot的应用程序打包成fat jar的插件。首先我们说一下啥叫fat jar。fat jar 我们暂且叫他胖jar吧,实在是找不到官方叫法了。我们一般的jar,里面放的是.class文件已经resources目录下的东西,但是fat jar 它可以把jar作为内容包含进去。也就是说,spring boot 借助spring-boot-maven-plugin将所有应用启动运行所需要的jar都包含进来,从逻辑上将具备了独立运行的条件。
我们将普通插件maven-jar-plugin生成的包和spring-boot-maven-plugin生成的包unzip,比较一下他们直接的区别,发现使用spring-boot-maven-plugin生成的jar中主要增加了两部分,第一部分是lib目录,这里存放的是应用的Maven依赖的jar包文件,第二部分是spring boot loader相关的类,这个我们下一节再说spring boot 的加载流程。
在项目中需要先加入spring-boot-maven-plugin。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.2.RELEASE</version>
<configuration>
<mainClass>test.ApplicationMain</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
默认是在package阶段执行spring-boot-maven-plugin repackage这个目标。我们看一下RepackageMojo的关键方法execute
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (this.project.getPackaging().equals("pom")) {
getLog().debug("repackage goal could not be applied to pom project.");
return;
}
if (this.skip) {
getLog().debug("skipping repackaging as per configuration.");
return;
}
//得到项目中的原始的jar,就是使用maven-jar-plugin生成的jar
File source = this.project.getArtifact().getFile();
//要写入的目标文件,就是fat jar
File target = getTargetFile();
Repackager repackager = new Repackager(source) {
//从source中寻找spring boot 应用程序入口的main方法。
@Override
protected String findMainMethod(JarFile source) throws IOException {
long startTime = System.currentTimeMillis();
try {
return super.findMainMethod(source);
}
finally {
long duration = System.currentTimeMillis() - startTime;
if (duration > FIND_WARNING_TIMEOUT) {
getLog().warn("Searching for the main-class is taking some time, "
+ "consider using the mainClass configuration "
+ "parameter");
}
}
}
};
//如果插件中指定了mainClass就直接使用
repackager.setMainClass(this.mainClass);
if (this.layout != null) {
getLog().info("Layout: " + this.layout);
repackager.setLayout(this.layout.layout());
}
//寻找项目运行时依赖的jar,过滤后
Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(),
getFilters(getAdditionalFilters()));
//将Artifact转化成Libraries
Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack,
getLog());
try {
LaunchScript launchScript = getLaunchScript();
//进行repackage
repackager.repackage(target, libraries, launchScript);
}
catch (IOException ex) {
throw new MojoExecutionException(ex.getMessage(), ex);
}
if (this.classifier != null) {
getLog().info("Attaching archive: " + target + ", with classifier: "
+ this.classifier);
this.projectHelper.attachArtifact(this.project, this.project.getPackaging(),
this.classifier, target);
}
else if (!source.equals(target)) {
this.project.getArtifact().setFile(target);
getLog().info("Replacing main artifact " + source + " to " + target);
}
}
基本上重要的步骤都有注释,应该不难理解的。再来看下面,当然也不是重点,看看就行。
public void repackage(File destination, Libraries libraries,
LaunchScript launchScript) throws IOException {
if (destination == null || destination.isDirectory()) {
throw new IllegalArgumentException("Invalid destination");
}
if (libraries == null) {
throw new IllegalArgumentException("Libraries must not be null");
}
if (alreadyRepackaged()) {
return;
}
destination = destination.getAbsoluteFile();
File workingSource = this.source;
//如果源jar与目标jar的文件路径及名称是一致的
if (this.source.equals(destination)) {
//将源jar重新命名为原名称+.original,同时删除原来的源jar
workingSource = new File(this.source.getParentFile(),
this.source.getName() + ".original");
workingSource.delete();
renameFile(this.source, workingSource);
}
destination.delete();
try {
//将源jar变成JarFile
JarFile jarFileSource = new JarFile(workingSource);
try {
repackage(jarFileSource, destination, libraries, launchScript);
}
finally {
jarFileSource.close();
}
}
finally {
if (!this.backupSource && !this.source.equals(workingSource)) {
deleteFile(workingSource);
}
}
}
这一步所做的是清理工作,如果源jar同目标文件路径名称等一致,将源jar重命名,原来的文件删除。为目标文件腾位置。下面的重点来了。
private void repackage(JarFile sourceJar, File destination, Libraries libraries,
LaunchScript launchScript) throws IOException {
JarWriter writer = new JarWriter(destination, launchScript);
try {
final List<Library> unpackLibraries = new ArrayList<Library>();
final List<Library> standardLibraries = new ArrayList<Library>();
libraries.doWithLibraries(new LibraryCallback() {
@Override
public void library(Library library) throws IOException {
File file = library.getFile();
if (isZip(file)) {
if (library.isUnpackRequired()) {
unpackLibraries.add(library);
}
else {
standardLibraries.add(library);
}
}
}
});
//按照规则写入manifest文件
writer.writeManifest(buildManifest(sourceJar));
Set<String> seen = new HashSet<String>();
writeNestedLibraries(unpackLibraries, seen, writer);
//写入源jar中的内容
writer.writeEntries(sourceJar);
//写入标准的jar,依赖的jar
writeNestedLibraries(standardLibraries, seen, writer);
if (this.layout.isExecutable()) {
//写入spring boot loader的类
writer.writeLoaderClasses();
}
}
finally {
try {
writer.close();
}
catch (Exception ex) {
// Ignore
}
}
}
上面就是一通写,将所需要的内容全部写入到目标文件中。然后就有了我们的fat jar。
作者:数齐
链接:https://www.jianshu.com/p/19b9634ab412
SpringBoot入门之spring-boot-maven-plugin的更多相关文章
- Spring Boot的Maven插件Spring Boot Maven plugin详解
Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...
- Spring Boot Maven Plugin(二):run目标
简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...
- Spring Boot Maven Plugin(一):repackage目标
简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...
- Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class
[背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...
- spring boot入门教程——Spring Boot快速入门指南
Spring Boot已成为当今最流行的微服务开发框架,本文是如何使用Spring Boot快速开始Web微服务开发的指南,我们将使创建一个可运行的包含内嵌Web容器(默认使用的是Tomcat)的可运 ...
- 微服务下 Spring Boot Maven 工程依赖关系管理
单体 Spring Boot Maven 工程 最基本的 pom.xml 包含工程信息.Spring Boot 父工程.属性配置.依赖包.构建插件 <?xml version="1.0 ...
- Kafka 入门和 Spring Boot 集成
目录 Kafka 入门和 Spring Boot 集成 标签:博客 概述 应用场景 基本概念 基本结构 和Spring Boot 集成 集成概述 集成环境 kafka 环境搭建 Spring Boot ...
- 图书-技术-SpringBoot:《Spring Boot 企业级应用开发实战》
ylbtech-图书-技术-SpringBoot:<Spring Boot 企业级应用开发实战> Spring Boot 企业级应用开发实战,全书围绕如何整合以 Spring Boot 为 ...
- spring boot学习总结(一)-- 基础入门 Hello,spring boot!
写在最前 SpringBoot是伴随着Spring4.0诞生的: 从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架: SpringBoot帮助开发者快速启动 ...
- Spring Boot入门 and Spring Boot与ActiveMQ整合
1.Spring Boot入门 1.1什么是Spring Boot Spring 诞生时是 Java 企业版(Java Enterprise Edition,JEE,也称 J2EE)的轻量级代替品.无 ...
随机推荐
- Matlab以MEX方式调用C源代码【转载】
原文地址:http://blog.sina.com.cn/s/blog_468651400100coas.html 这是自己整理的一个对应的文档:<Matlab以MEX方式调用C源代码> ...
- canvas globalCompositeOperation
source-over 默认,相交部分由后绘制图形的填充(颜色,渐变,纹理)覆盖source-in 只绘制相交部分,由后绘制图形的填充覆盖,其余部分透明 source-out 只绘制后绘制图形不相 ...
- 每天一个linux命令(权限):【转载】 /etc/group文件详解
Linux /etc/group文件与/etc/passwd和/etc/shadow文件都是有关于系统管理员对用户和用户组管理时相关的文件.linux /etc/group文件是有关于系统管理员对用户 ...
- Cookie简单实例
Cookie简单实例 1.创建CookieServlet package com.servlet.study; import java.io.IOException; import java.io.P ...
- Hive中日期处理
1.日期函数UNIX时间戳转日期函数:from_unixtime() 函数 格式 返回值 说明 from_unixtime from_unixtime(bigint unixtime[, string ...
- 在iOS上实现二维码功能
http://blog.csdn.net/abcmx/article/details/8011904 如今二维码随处可见,无论是实物商品还是各种礼券都少不了二维码的身影.而手机等移动设备又成为二维码的 ...
- 《selenium2 python 自动化测试实战》(17)——几个cookies操作
之前我们已经学过利用cookies跳过验证码登录了,那时候我们用的方法是add_cookie()方法,这里再给大家介绍两个,一般情况下我们用不到,了解一下就可以,而且如果真的用到的时候百度也很快的: ...
- simulink使用system test测试 (matlab2014a)
simulink中有个工具system test,tools->systemtest->launch system test 打开.打开之后界面是这样的 选择insert->test ...
- spring--集合注入(常规方法)
数据,list,set,map,Properties 集合注入 package Spring_collections; /** * Created by luozhitao on 2017/8/11. ...
- 查找大文件 & 索引节点(inode)爆满 解决办法
经常遇到磁盘满或者文件节点满的情况,整理如下 查找大文件 查找超过某个大小的文件, 如1G find . -type f -size +1G 查找文件大小的时候,现实文件属性 find . -type ...