使用maven打出独立应用程序的jar包 博客分类: Java maven配置管理log4jXMLApache
程序员文章站
2024-02-21 13:07:46
...
Java独立应用程序的执行有两种方式:
java -jar 命令
和 java -classpath 命令
其中,因为java -jar 不接收classpath参数(或者说-classpath对它不起作用),因此必须把所有依赖的文件都打到一个jar里(比如 One jar)。这样就存在一个问题:修改这个独立应用程序的配置文件会很不方便。(ps:当前路径是它的类路径)。
所以除非不用配置信息或从命令行指定配置信息,更好的方式应该是使用java -cp(即-classpath)的方式,并从类路径中读取配置文件。
那么,一个独立应用程序的目录结构可以是如下形式:
1、一个lib文件夹用于存放这个独立应用程序所依赖的jar包。
2、把这个独立应用程序所依赖的配置文件(而且是可能需要修改的)放在与jar包同级目录下。
3、一个jar包,里面是主程序。
若要执行这个独立应用程序,可以使用脚本拼出classpath的值,然后调用java -cp 命令。
在Linux下使用shell脚本:
在windows平台下就要麻烦一些了,使用dos批处理:
下面是cpappend.bat:
cpappend.bat是不是见过?没错,tomcat下的,直接从那抄的,dos的批处理的写法我是没研究明白。
set CLASSPATH=%CLASSPATH%;lib/%1后面不要有空格。
注:类路径中,最好把配置文件的路径放在jar文件的路径之前,因为我们实际项目中遇到过:有的jar包中包含同名配置文件把我们自己的配置文件给覆盖了的情况。改一下在classpath中的顺序,这样就可以让程序优先使用我们的配置文件。
这样,方便修改配置的独立应用程序的执行方法已经出来了。下面的问题是,那些依赖的jar包,以及配置文件谁来拷出来?用maven来做这件事是最方便不过的了。
使用maven的resources插件。
下面我们要做的就是:在使用maven打包时,把程序依赖的jar包都拷出来,配置文件拷出来。同时,因为要使用外部的配置文件,所以要避免把配置文件打到jar包里。pom里的配置如下:
上面有几个需要特别说明的地方:
1、phase节点,表示要在什么阶段执行这个任务,比如
表示在打包(package)之前执行copy-dependencies的任务(关于copy-dependencies,请查阅resources插件的说明)。
2、最后一个plugin节点中的classifier节点,表示这种方式(排除了配置文件)打出的jar包通过什么来和别的jar包区分开,我设的值是lib,这样打出来的包名就是:xxxx-lib.jar
3、最后一个plugin节点中的:
可以写成:
我没这么写,是因为我还有其它的.xml文件不需要放在外面。
到这里,用maven打独立应用程序的jar包的方式就讲解完了。在这再补充一个小知识。
如果你有多个工程,统一用一个父pom来管理(这些工程的pom都继承自父pom),如果有的工程中使用了resources插件,你在使用maven打包时,会出现错误,maven命令无法成功执行。
提示的错误大意是:你在pom中指定要执行copy-resources任务,却没有resources插件。
解决的办法是在父pom中加入:
java -jar 命令
和 java -classpath 命令
其中,因为java -jar 不接收classpath参数(或者说-classpath对它不起作用),因此必须把所有依赖的文件都打到一个jar里(比如 One jar)。这样就存在一个问题:修改这个独立应用程序的配置文件会很不方便。(ps:当前路径是它的类路径)。
所以除非不用配置信息或从命令行指定配置信息,更好的方式应该是使用java -cp(即-classpath)的方式,并从类路径中读取配置文件。
那么,一个独立应用程序的目录结构可以是如下形式:
1、一个lib文件夹用于存放这个独立应用程序所依赖的jar包。
2、把这个独立应用程序所依赖的配置文件(而且是可能需要修改的)放在与jar包同级目录下。
3、一个jar包,里面是主程序。
若要执行这个独立应用程序,可以使用脚本拼出classpath的值,然后调用java -cp 命令。
在Linux下使用shell脚本:
CLASSPATH="." # 遍历应用程序依赖的jar包,并加入CLASSPATH。 for jarfile in `ls lib/.`; do CLASSPATH="${CLASSPATH}:lib/$jarfile" done #---------------下面是以前写错的部分,不需要这种方式把配置文件加入到类中径中。 # 因为类路径中设都应该是目录(而不是文件),jar文件也是按目录来处理的 # # 配置文件的遍历(与上类似) # 这里面我的配置文件都是xml的 #for configfile in `ls *.xml`; do # CLASSPATH="configfile:${CLASSPATH}" export CLASSPATH java -cp ${CLASSPATH} Test
在windows平台下就要麻烦一些了,使用dos批处理:
@echo off for %%i in (lib/*.jar) do call cpappend.bat %%i java -cp %CLASSPATH% Test
下面是cpappend.bat:
@echo off if ""%1"" == """" goto end set CLASSPATH=%CLASSPATH%;lib/%1 shift rem Process the remaining arguments :setArgs if ""%1"" == """" goto doneSetArgs set CLASSPATH=%CLASSPATH% %1 shift goto setArgs :doneSetArgs :end
cpappend.bat是不是见过?没错,tomcat下的,直接从那抄的,dos的批处理的写法我是没研究明白。
set CLASSPATH=%CLASSPATH%;lib/%1后面不要有空格。
注:类路径中,最好把配置文件的路径放在jar文件的路径之前,因为我们实际项目中遇到过:有的jar包中包含同名配置文件把我们自己的配置文件给覆盖了的情况。改一下在classpath中的顺序,这样就可以让程序优先使用我们的配置文件。
这样,方便修改配置的独立应用程序的执行方法已经出来了。下面的问题是,那些依赖的jar包,以及配置文件谁来拷出来?用maven来做这件事是最方便不过的了。
使用maven的resources插件。
下面我们要做的就是:在使用maven打包时,把程序依赖的jar包都拷出来,配置文件拷出来。同时,因为要使用外部的配置文件,所以要避免把配置文件打到jar包里。pom里的配置如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath><!-- 加载class --> <classpathPrefix>lib/</classpathPrefix><!-- 加载的class目录的前缀(依赖的jar目录) --> <mainClass>test.Test</mainClass><!-- 入口类名 --> </manifest> </archive> </configuration> </plugin> <!-- 把依赖的jar包拷到lib目录下 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> <!-- 以utf-8编码拷贝配置文件,拷贝过程中是可以做变量替换的,也就是说你的配置文件可以是个模板,里面的${}所包含的内容是可以拷贝过程中替换的 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.3</version> <executions> <execution> <id>copy-resources</id> <phase>package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>UTF-8</encoding> <outputDirectory>${project.build.directory}</outputDirectory><!-- 把配置文件拷到和jar包同一个路径下 --> <resources> <resource> <directory>src/main/resources/</directory> <includes> <include>config.xml</include> <include>log4j.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin> <!-- 打jar包时需要把配置文件给排除在外 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <classifier>lib</classifier> <excludes> <exclude>config.xml</exclude> <exclude>log4j.xml</exclude> </excludes> </configuration> </execution> </executions> </plugin>
上面有几个需要特别说明的地方:
1、phase节点,表示要在什么阶段执行这个任务,比如
<phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals>
表示在打包(package)之前执行copy-dependencies的任务(关于copy-dependencies,请查阅resources插件的说明)。
2、最后一个plugin节点中的classifier节点,表示这种方式(排除了配置文件)打出的jar包通过什么来和别的jar包区分开,我设的值是lib,这样打出来的包名就是:xxxx-lib.jar
3、最后一个plugin节点中的:
<exclude>config.xml</exclude> <exclude>log4j.xml</exclude>
可以写成:
<exclude>*.xml</exclude>
我没这么写,是因为我还有其它的.xml文件不需要放在外面。
到这里,用maven打独立应用程序的jar包的方式就讲解完了。在这再补充一个小知识。
如果你有多个工程,统一用一个父pom来管理(这些工程的pom都继承自父pom),如果有的工程中使用了resources插件,你在使用maven打包时,会出现错误,maven命令无法成功执行。
提示的错误大意是:你在pom中指定要执行copy-resources任务,却没有resources插件。
解决的办法是在父pom中加入:
<pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.3</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </pluginManagement>
上一篇: java 抛出异常处理的方法
下一篇: Java不指定长度的二维数组实例