使用场景
我有一个jar包,可执行jar包,比如说叫exe.jar。
这个jar包依赖了其他的几个jar包,比如说json.jar,template.jar.
我想在exe.jar的同级目录下放一个lib文件夹,把json.jar,template.jar放到lib下面。
然后在exe.jar的同级目录,启动命令行,执行:java -jar exe.jar
。
如此这般程序便可以正常启动。
遇到的问题
lib下的jar包不在classpath中,会报classnotfound的异常。
解决方法
将org.springframework.boot:spring-boot-loader中的类抽取出来,与自己项目编译后的类打包在一起。
在manifest文件中加两个配置项。
Main-Class=org.springframework.boot.loader.PropertiesLauncher;
Start-Class=${your main class}
其中的Main-Class
是java规定的标准属性,Start-Class
是spring-boot-loader自定义的属性
原理描述
spring-boot-loader是如何做到的呢?
对源码进行阅读之后我们可知,它是这么操作的:
- PropertiesLauncher启动后会获取lib下面的所有jar包。根据这些jar包的url以及当前的ClassLoader创建一个URLClassLoader.
- 启动一个新的线程RunThread,将上面创建的URLClassLoader设置为RunThread的classloader。
- 在RunThread中先读取jar包中manifest的文件中得Start-Class,然后通过反射调用Start-Class的main方法,并把args传递过去。
- 启动成功。
其他方案
- 有个叫OneJar什么的项目,原理与spring-boot-loader类似。
- 使用JavaAgent技术,启动时动态加载jar包到classpath中。
缺点:启动命令比较特殊。 - 将所有的jar包中的类都抽取出来跟项目class打包到一起。
缺点:每次更新,体积比较大。 - 在manifest文件中配置classpath属性,将所有引用的lib目录下的jar包都列在里面。
缺点:jar包的名字和数量固定死了,不能改变。
后续
这篇文章只是讲了一些大致流程以及原理,没有具体使用的工具和详细操作。
怎么办呢?请期待我后续的文章吧。
##我是后续 打包示例项目看这里http://git.oschina.net/landyking/BlogCodeShow/tree/master/springboot/howtopackage