在实际的项目中,我们经常会碰到这样的需求:“通过执行某条命令搞定一些的事情”。
如果开发人员比较擅长一些脚本语言,那么很幸运,他可以直接写好脚本,然后直接在命令行执行就好了。
如果开发人员恰好只擅长一些静态语言,比如Java、C......,也可以借助一些工具来生成最终可以执行的文件,然后直接在命令行中调用就好了。
那这样看来,好像没有什么难的事情。的确,如果事情仅仅只是这样,当然比较简单,关键问题是经常开发环境与测试环境还有生产环境往往不是完全一样。那么我们需要经常在不同的环境下更改配置来达到当前环境的要求,这样一来,需要手工操作的事情就比较多了,尤其是在测试与多方联调时,部署的人员肯定要骂人了。
好吧,说了这么多废话,我们现在开始正式面对这样的问题并且用一种相对优雅的方式来解决它吧。
假设,我们现在使用Java来做这件事情。那我们会按照迭代的方式来慢慢来做。
首先我们先做一个可以执行的jar。这个比较简单,大部分的程序员都可以直接使用自己的IDE来直接将项目导出成一个可以执行的jar。但是现在已经不是一个人就可以完成所有事情的时代,在注重团队配合的年代,我们当然要选择一种不依赖开发人员个人环境的方式来完成这件事情。很庆幸,我们有maven 。我们可以在maven中很轻易的完成这样的事情,同时也不会依赖某个人的环境。
我们需要在pom.xml中加上下面的配置就OK了。
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<archive>
<manifest>
<mainClass>com.wolf.Process</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
OK,根据上面的配置,我们可以很轻易的使用 mvn:assembly:assembly 这个命令得到一个可以执行的jar,并且这个jar中还会将这个项目说要依赖的第三方的jar都打到这个jar中,我们可以直接使用java -jar xxxx.jar来执行我们指定的代码了。
如果,我们需要在生成这个可执行的jar的事情做一些更加个性化的东西应该怎么办呢?比如,项目中需要依赖spring,但是这样直接生成的jar在执行的时候,却报一个schema namespace的错误,原因是自动生成的jar中的META-INF目录中包含的spring-schemas和spring-handlers文件缺少一些我们需要的schema的定义和解析方式。那其实也很好解决,我们可以指定assembly.xml让 maven 帮我们处理这个问题。具体配置如下:
pom.xml
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.wolf.Process</mainClass>
</manifest>
</archive>
<descriptors>
<descriptor>src/main/resources/META-INF/assemble.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
assemble.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>META-INF/spring.handlers</exclude>
<exclude>META-INF/spring.schemas</exclude>
</excludes>
</unpackOptions>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<files>
<file>
<source>src/main/resources/META-INF/spring.handlers</source>
<outputDirectory>META-INF</outputDirectory>
</file>
<file>
<source>src/main/resources/META-INF/spring.schemas</source>
<outputDirectory>META-INF</outputDirectory>
</file>
</files>
</assembly>
现在我们第一个需求解决了,可以用一种通用的方式来生成一个可以执行的jar,那么我们接下来要解决的是另外一个问题,如何生成指定目标环境的jar。
其实也很简单,我们只要引入maven 的profile配置就可以了。具体配置如下:
pom.xml
<profiles>
<profile>
<id>windows</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/resources/META-INF/assemble-linux.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
<activation>
<property><name>windows</name></property>
</activation>
</profile>
<profile>
<id>linux</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/resources/META-INF/assemble-linux.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
<activation>
<property><name>linux</name></property>
</activation>
</profile>
</profiles>
这样,我们只要执行mvn -Dwindwos assembly:assembly 或者 mvn -Dlinux assembly:assembly 就可以生成指定目标环境的可执行的jar了。
PS:如果你想不同目标环境jar的名字不同,我们可以在相应的assemble.xml文件中更改那个id的值就可以了。