可执行Jar项目

  一个复杂Jar的运行,要解决classpath问题,否则运行时会有ClassNotFoundException抛出。而用java,需要手动维护一个classpath文件,或者将所有的库位置放到命令行参数里。有没有更好的办法?

Jar+库目录方式

  核心配置在于两点,一是manifest.mf,二是复制依赖,两者缺一不可。
  关于这两点,我们先一个个讲。

<!-- 配置生成的jar文件 -->
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<version>2.4</version>
	<configuration>
		<archive>
			<manifest>
				<addClasspath>true</addClasspath>
				<classpathPrefix>lib/</classpathPrefix>
				<mainClass>com.maya.prepay.server.main.Main</mainClass>
			</manifest>
		</archive>
	</configuration>
</plugin>

  Manifest.mf的文件中有些东西根本就是没用的,什么created-by这样的信息,那就是扯淡的。真正有用的东西是两个,一个是main类,这个配置决定它的jar在运行时启动哪个class。另外一个就是依赖,这个可以保证平稳地调用第三方的jar。
  Main类的配置就在于

<mainClass>com.maya.prepay.server.main.Main</mainClass>

  这么一行代码。
  而classpath的配置就比较复杂了。有以下两行配置:

<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>

  但是classpath配置了这么两行没用啊,如果真正生产上要用,还需要去手动拷贝依赖。对于maven管理的项目,依赖的jar位于不同目录下,拷贝起来那是十分伤脑筋的。怎么办?
这就需要下一个技术点了。Copy依赖,代码如下:

			<!-- 配置将依赖放入同一个文件夹 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.9</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>prepare-package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<includeTypes>jar</includeTypes>
							<type>jar</type>
							<outputDirectory>${project.build.directory}/lib</outputDirectory>
							<overWriteReleases>true</overWriteReleases>
							<overWriteSnapshots>true</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>

  这种代码,死记硬背就行了。

Uber-jar方式

  Jar+库目录的方式,只是实现了jar的可执行。但是在部署、分发程序的时候,需要传递jar和库目录,用起来十分不方便。
  可以将所有依赖和源代码都打包到一个jar包里。这样运行的时候就非常方便,直接运行一个大jar包就行。当然这个jar包体积会非常大。
  这种jar包叫做uber-jar,又叫fat jar。Uber其实是super的意思,因为super是大多数编程语言关键字,所以很多时候用uber做变量名以表达super的含义。
  这需要用到maven-shade-plugin插件或者maven-assembly-plugin。以maven-shade-plugin为例子。在pom.xml中配置好需要运行的主类,和package时的goal就可以了。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.zhongmin.demo.Main</mainClass>
                    </transformer>
                </transformers>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

  编译之后生成的包在target下
在这里插入图片描述
  可以看到,有两个jar,一个是original-xxx.jar,另一个是可执行的jar。大小也不一样,
可执行的jar足足有745K大小,而源代码编译后的jar包只有3KB大小。
  这个编译结果与spring-boot项目的编译结果不一致。Shade插件,是把依赖的jar包全部解压,然后和源代码编译后的classpath放在一起。而spring boot是把依赖的jar包进行拷贝,使用一个classloader去加载这些jar包。两者原理不一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值