對 J2EE 項目打 war 包。其實很簡單,你只須要把 pom.xml 中的 <packaging>jar</packaging> 換成 <packaging>war</packaging> 就可使用 mvn package 命令對其打 war 包了,而不須要添加任何 maven 插件。只要你遵循了 maven 規範,那你打成的 war 包就確定包含了第三方依賴包:
把這個 war 包丟進 tomcat 的 webapps 目錄,重啓 tomcat 便可完成了該項目的部署。你惟一須要注意的是,在重啓 tomcat 以前把你的 war 重命名爲 項目訪問路徑.war。好比做者打成的 war 包是爲 swifton-1.0.0.war,對該項目定義的訪問路徑是 /swifton,那麼我在重啓 tomcat 以前須要將其重命名爲 swifton.war。
html
關於可執行程序(須要指定一個 main 類)打 jar 包就沒這麼方便了,咱們須要考慮如下幾個問題:
java
配置文件須要打進 jar 包;web
須要指定 main 入口類;spring
所依賴的第三方庫也要打進 jar 包;apache
只有同時知足以上三點,咱們才能夠直接使用 java -jar swiftonrsa-1.0.0.jar 命令成功執行該程序。
爲了讓討論不那麼抽象,咱們在 Eclipse 下新建一個 maven 項目 swiftonrsa:
其中,com.defonds.RsaEncryptor 是入口 main 類,其源碼以下:
swift
package com.defonds; tomcat
import org.springframework.context.ApplicationContext; app
import org.springframework.context.support.ClassPathXmlApplicationContext; webapp
import com.defonds.service.LinkPayAntharService; maven
public class RsaEncryptor {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
LinkPayAntharService linkPayAntharService = (LinkPayAntharService) context.getBean("linkPayAntharService");
linkPayAntharService.dealWithYearData();
}
}
只要你項目所依賴的配置文件都按照 maven 規範放對位置(src/main/resources),那麼打好的 jar 包就會把它們一塊兒打包:
可是這樣打好的 jar 包既沒有指定 main 入口類,也沒有將依賴包打進來,咱們運行它:
提示"swiftonrsa-1.0.0.jar中沒有主清單屬性",咱們查看打好 jar 包下 META-INF 目錄中的 MANIFEST.MF,其內容以下:
Manifest-Version: 1.0
Built-By: Defonds
Build-Jdk: 1.7.0_67
Created-By: Apache Maven 3.2.3
Archiver-Version: Plexus Archiver
確實沒有指出 main 入口類。
因而咱們引入了 maven-assembly-plugin 插件,pom.xml 中加入以下代碼:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.defonds.RsaEncryptor</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
執行 mvn assembly:assembly,成功構建 swiftonrsa-1.0.0.jar,查看其打包目錄,各類配置文件以及第三方依賴包也都有:
而後查看 META-INF 目錄中的 MANIFEST.MF,內容以下:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Defonds
Build-Jdk: 1.7.0_67
Main-Class: com.defonds.RsaEncryptor
懷着興奮的心情執行之:
maven-assembly-plugin 插件沒有給咱們帶來驚喜。錯誤信息以下:
Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]
原來這是 assembly 插件的一個 bug:http://jira.codehaus.org/browse/MASSEMBLY-360,它在對第三方打包時,對於 META-INF 下的 spring.handlers,spring.schemas 等多個同名文件進行了覆蓋,遺漏掉了一些版本的 xsd 本地映射。
有破必有立。http://jira.codehaus.org/browse/MASSEMBLY-360 跟帖中有網友推薦了 maven-shade-plugin 插件。因而咱們使用 maven-shade-plugin 將 maven-assembly-plugin 替代:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.defonds.RsaEncryptor</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
對於多個第三方包 META-INF 下的同名的 spring.handlers 文件它採起的態度是追加而不是覆蓋。執行 maven clean package,成功構建 swiftonrsa-1.0.0.jar,查看其打包目錄,各類配置文件以及第三方依賴包也都有,以及 META-INF 目錄中的 MANIFEST.MF 的內容,基本如 maven-assembly-plugin 打包後的樣子,執行之:
錯誤信息以下:
java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
這是因爲一些包重複引用,打包後的 META-INF 目錄多出了一些 *.SF 等文件所致。
有破必有立。博客 http://zhentao-li.blogspot.com/2012/06/maven-shade-plugin-invalid-signature.html 給出瞭解決方案,pom.xml 添加:
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
因而咱們對 maven-shade-plugin 的配置變成這樣:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.defonds.RsaEncryptor</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
再次執行 maven clean package,再次執行成功構建後的 swiftonrsa-1.0.0.jar:
最後兩行是具體業務實現類 com.defonds.service.LinkPayAntharServiceImpl 成功執行打印出的 log 日誌。
轉載:http://blog.csdn.net/defonds/article/details/43233131