将Springboot的“fat jar” 变成 “thin jar”
来源:互联网 发布:smart白板软件下载 编辑:程序博客网 时间:2024/05/16 11:39
大家都知道spring boot有个很吸引人的特性,那就是可以直接把应用打包成为一个jar/war,而且这个jar/war是可以直接启动的,称之为“fat jar”。
但是有时候我们有这样的需求:
- 1.将项目中通常版本号确定不会用什么变动的依赖包,不打包进运行包,而是放到外部某个文件夹中,在启动运行包时,再去读取加载
- 2.经常需要变动的项目模块打包进运行包
这样做的好处:运行包显著变小,传递更加快捷,在经常需要变更的环境下非常有用处!
关于“fat jar”启动不清楚的,可以参考:http://blog.csdn.net/hengyunabc/article/details/50120001,可能和当前版本有些出入,但基本原理是这样。
1.”fat jar” to “thin jar”
1)添加配置:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.4.0.RELEASE</version> <configuration> <layout>ZIP</layout> <executable>true</executable> <includes> <include> <groupId>nothing</groupId> <artifactId>nothing</artifactId> </include> <include> <groupId>org.cyzy</groupId> <artifactId>common</artifactId> </include> </includes> </configuration></plugin>
layout
设置为ZIP,此模式下spring-boot-maven-plugin会将Manifest.MF文件中的Main-Class设置为org.springframework.boot.loader.PropertiesLauncher。
PropertiesLauncher源码注释:
Launcher for archives with user-configured classpath and main class via a properties file. This model is often more flexible and more amenable to creating well-behaved OS-level services than a model based on executable jars. loader.path: a comma-separated list of directories (containing file resources and/or nested archives in *.jar or *.zip or archives) or archives to append to the classpath. BOOT-INF/classes,BOOT-INF/lib in the application archive are always used loader.main: the main method to delegate execution to once the class loader is set up. No default, but will fall back to looking for a Start-Class in a MANIFEST.MF, if there is one in ${loader.home}/META-INF.
PropertiesLauncher会从其被启动加载路径的指定路径下:BOOT-INF/classes和BOOT-INF/lib,加载内部classes和lib,同时还提供了通过配置系统变量从外部加载classes和lib的能力。而默认的JarLauncher只能从其被启动加载路径的指定路径下:BOOT-INF/classes和BOOT-INF/lib,加载内部classes和lib。
includes
将需要保留的jar包,按照groupId和artifactId(注意两个都是必填项)include进来。
nothing 代表不存在的依赖包,意思就是什么依赖包都不引入
org.cyzy.common 才是真正的需要保留的依赖包
2)启动
java -Dloader.path=E:/tmp/test/lib -jar gps-server-1.0-SNAPSHOT.jar
PropertiesLauncher会
1.创建LaunchedURLClassLoader(extends URLClassLoader)加载classes和resources,从:
- gps-server-1.0-SNAPSHOT.jar(JarFileArchive)中的BOOT-INF/classes和BOOT-INF/lib
- loader.path 指定的外部的目录或Archive
2.从loader.man系统属性或gps-server-1.0-SNAPSHOT.jar中的META-INF/MANIFEST.MF的Start-Class中获取应用的入口类
3.然后启动入口类:
Thread.currentThread().setContextClassLoader(classLoader); Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName); Method mainMethod = mainClass.getDeclaredMethod("main", String[].class); mainMethod.invoke(null, new Object[] { this.args });
2.”fat war” to “thin war”
首先下载spring-boot-tools源码:https://github.com/spring-projects/spring-boot/tree/master/spring-boot-tools
因为项目工程starter都是1.4.0.RELEASE的,所以1.4.0.RELEASE为例。
1).修改spring-boot-loader中的PropertiesLauncher
根据启动类所在路径决定读取的内部的classes和lib的位置。war包读WEB-INF/classes和WEB-INF/lib;其他的读BOOT-INF/classes和BOOT-INF/lib。
private String getBootInf(Archive parent, String property) { boolean isWar = false; try { if(parent.getUrl().getPath().contains(".war!")){ isWar = true; } } catch (Exception e) {} if("cp".equals(property)){ if(isWar){ return WarLauncher.WEB_INF_CLASSES; }else{ return JarLauncher.BOOT_INF_CLASSES; } } if("lp".equals(property)){ if(isWar){ return WarLauncher.WEB_INF_LIB; }else{ return JarLauncher.BOOT_INF_LIB; } } return "";}private void addNestedEntries(List<Archive> lib) { // The parent archive might have "BOOT-INF/lib/" and "BOOT-INF/classes/" // directories, meaning we are running from an executable JAR. We add nested // entries from there with low priority (i.e. at end). String ncp = getBootInf(this.parent, "cp"); String nlp = getBootInf(this.parent, "lp"); try { log("root archive path:" + parent.getUrl().getPath()); log("nested class path:" + ncp); log("nested lib path:" + nlp); } catch (MalformedURLException e) {} try { lib.addAll(this.parent.getNestedArchives(new EntryFilter() { @Override public boolean matches(Entry entry) { if (entry.isDirectory()) { return entry.getName().startsWith(ncp); } return entry.getName().startsWith(nlp); } })); } catch (IOException ex) { // Ignore }}
2).修改spring-boot-loader-tools中的Layouts
如果当前repackage的是war包,则启动类使用PropertiesLauncher
public static class War implements Layout { ... @Override public String getLauncherClassName() { return "org.springframework.boot.loader.PropertiesLauncher"; } ...}
1) 2)步源码修改完成后,安装到本地仓库。
3).修改配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <packagingIncludes> app/**, bower**/**, content/**, i18n/**, m/**, swagger-ui/**, templates/**, 404.html, favicon.ico, index.html, session-expired.html, robots.txt, WEB-INF/classes/**, WEB-INF/lib/spring-boot-1.4.0.RELEASE.jar </packagingIncludes> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <includes> <include> <groupId>nothing</groupId> <artifactId>nothing</artifactId> </include> </includes> </configuration> </plugin>
packagingIncludes:
不知道为啥,使用:<packagingExcludes>WEB-INF/lib/**</packagingExcludes>
的方式未生效,所以反过来把需要保留的全都包括进来。 同时需要配合spring-boot-maven-plugin的includes一同使用,否则repackage时候又把依赖包打入WEB-INF/lib/。
注意:spring-boot-1.4.0.RELEASE.jar需要打入WEB-INF/lib,否则应用可能会找不到war包中的web resources。
4).启动
java -Dloader.path=E:/tmp/lib2 -jar xxxx.war
- 将Springboot的“fat jar” 变成 “thin jar”
- fat-jar的使用
- MyEclipse的jar导出插件fat jar
- 图解Fat jar的使用
- 图解Fat jar的使用
- 图解Fat jar的使用 .
- 图解Fat jar的使用 .
- FAT jar将java工程打包成jar文件
- ◦将一个java文件变成Jar包的过程
- Fat jar 非常不错的打包插件
- MyEclipse下的打包插件fat jar
- fat-jar的安装和使用
- fat jar 的在线安装地址
- 用eclipse的fat-jar插件生成jar包
- fat-jar安装
- fat.jar 打包真好用
- fat-jar使用
- eclipse插件Fat Jar
- 国家发展军事, 个人发展武力,
- 看完首页文章谈谈关于C++学习的一点感想
- Oracle命令(二):Oracle用户
- Makefile "hello world"
- android怎样修改状态栏颜色
- 将Springboot的“fat jar” 变成 “thin jar”
- Oracle数据库运维、备份常用指令
- RecyclerView使用解析
- 关于时间戳转时间
- 又拍网架构中的数据库分库设计
- 改变继承UIButton的两个子类状态
- 交叉开发环境搭建
- c/c++调用libcurl库发送http请求的两种基本用法
- 关于ST-Link的internal command error问题的解决方法