Maven 项目打包需要注意到的那点事儿

1. 关于 Maven 打 war 包

《使用 Eclipse 的 Maven 2 插件开发一个 JEE 项目》详细介绍了如何在 Eclipse 使用 Maven 新建一个 JEE 项目并对其进行断点跟踪调试,但是没有介绍如何对 JEE 项目打 war 包。其实很简单,你只需要把 pom.xml 中的 jar 换成 war 就可以使用 mvn package 命令对其打 war 包了,而不需要添加任何 maven 插件。只要你遵循了 maven 规范(比如照着《使用 Eclipse 的 Maven 2 插件开发一个 JEE 项目》所述做了),那你打成的 war 包就肯定包含了第三方依赖包:

maven打的war包里边的第三方依赖包

把这个 war 包丢进 tomcat 的 webapps 目录,重启 tomcat 即可完成了该项目的部署。你唯一需要注意的是,在重启 tomcat 之前把你的 war 重命名为 项目访问路径.war。比如作者打成的 war 包是为 swifton-1.0.0.war,对该项目定义的访问路径是 /swifton,那么我在重启 tomcat 之前需要将其重命名为 swifton.war。

2. 可执行程序打 jar 包

关于可执行程序(需要指定一个 main 类)打 jar 包就没这么方便了,我们需要考虑以下几个问题:

  • 配置文件需要打进 jar 包;
  • 需要指定 main 入口类;
  • 所依赖的第三方库也要打进 jar 包;

只有同时满足以上三点,我们才可以直接使用 java -jar swiftonrsa-1.0.0.jar 命令成功执行该程序。
为了让讨论不那么抽象,我们在 Eclipse 下新建一个 maven 项目 swiftonrsa:


新建maven项目swiftonrsa

其中,com.defonds.RsaEncryptor 是入口 main 类,其源码如下:

package com.defonds;  
 
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
import com.defonds.service.LinkPayAntharService;  
  
public class RsaEncryptor {  
  
    public static void main(String[] args) {  
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
        LinkPayAntharService linkPayAntharService = (LinkPayAntharService) context.getBean("linkPayAntharService");  
        linkPayAntharService.dealWithYearData();  
    }  
}  

2.1 配置文件打包不需要额外关注

只要你项目所依赖的配置文件都按照 maven 规范放对位置(src/main/resources),那么打好的 jar 包就会把它们一起打包:


配置文件打包不需要额外关注

但是这样打好的 jar 包既没有指定 main 入口类,也没有将依赖包打进来,我们运行它:


swiftonrsa-1.0.0.jar中没有清单属性

提示"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 入口类。

2.2 maven-assembly-plugin 插件

于是我们引入了 maven-assembly-plugin 插件,pom.xml 中加入如下代码:

  
      
          
            maven-assembly-plugin  
              
                false  
                  
                    jar-with-dependencies  
                  
                  
                      
                        com.defonds.RsaEncryptor  
                      
                  
              
              
                  
                    make-assembly  
                    package  
                      
                        assembly  
                      
                  
              
          
      
  

执行 mvn assembly:assembly,成功构建 swiftonrsa-1.0.0.jar,查看其打包目录,各种配置文件以及第三方依赖包也都有:


assembly打包后的目录结构

然后查看 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
怀着兴奋的心情执行之:


assembly打包后的执行情况

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 本地映射。

2.3 maven-shade-plugin 插件

有破必有立。http://jira.codehaus.org/browse/MASSEMBLY-360 跟帖中有网友推荐了 maven-shade-plugin 插件。于是我们使用 maven-shade-plugin 将 maven-assembly-plugin 替代:

  
      
          
            org.apache.maven.plugins  
            maven-shade-plugin  
            1.4  
              
                  
                    package  
                      
                        shade  
                      
                      
                          
                              
                                com.defonds.RsaEncryptor  
                              
                              
                                META-INF/spring.handlers  
                              
                              
                                META-INF/spring.schemas  
                              
                          
                      
                  
              
          
      
  

对于多个第三方包 META-INF 下的同名的 spring.handlers 文件它采取的态度是追加而不是覆盖。执行 maven clean package,成功构建 swiftonrsa-1.0.0.jar,查看其打包目录,各种配置文件以及第三方依赖包也都有,以及 META-INF 目录中的 MANIFEST.MF 的内容,基本如 maven-assembly-plugin 打包后的样子,执行之:


shade插件打包后执行情况

错误信息如下:
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 添加:

  
    
      
      *:*  
        
        META-INF/*.SF  
        META-INF/*.DSA  
        META-INF/*.RSA  
        
      
    
  

于是我们对 maven-shade-plugin 的配置变成这样:

  
      
          
            org.apache.maven.plugins  
            maven-shade-plugin  
            1.4  
              
                  
                    package  
                      
                        shade  
                      
                      
                          
                              
                                *:*  
                                  
                                    META-INF/*.SF  
                                    META-INF/*.DSA  
                                    META-INF/*.RSA  
                                  
                              
                          
                          
                              
                                com.defonds.RsaEncryptor  
                              
                              
                                META-INF/spring.handlers  
                              
                              
                                META-INF/spring.schemas  
                              
                          
                      
                  
              
          
      
  

再次执行 maven clean package,再次执行成功构建后的 swiftonrsa-1.0.0.jar:


再次执行shade插件打包后的swiftonrsa

最后两行是具体业务实现类 com.defonds.service.LinkPayAntharServiceImpl 成功执行打印出的 log 日志。

2.4 示例项目

本文示例项目 swiftonrsa 已上传至 CSDN 资源,有兴趣的朋友可以下载下来参考实验,下载地址:http://download.csdn.net/detail/defonds/8404739。
本文示例项目最终 pom.xml 如下:

  
    4.0.0  
  
    settle  
    swiftonrsa  
    1.0.0  
    jar  
  
    swiftonrsa  
    http://maven.apache.org  
  
      
        UTF-8  
      
  
      
          
              
                org.apache.maven.plugins  
                maven-shade-plugin  
                1.4  
                  
                      
                        package  
                          
                            shade  
                          
                          
                              
                                  
                                    *:*  
                                      
                                        META-INF/*.SF  
                                        META-INF/*.DSA  
                                        META-INF/*.RSA  
                                      
                                  
                              
                              
                                  
                                    com.defonds.RsaEncryptor  
                                  
                                  
                                    META-INF/spring.handlers  
                                  
                                  
                                    META-INF/spring.schemas  
                                  
                              
                          
                      
                  
              
          
      
  
  
      
  
          
          
            log4j  
            log4j  
            1.2.17  
          
  
          
            commons-logging  
            commons-logging  
            1.2  
          
  
          
            org.slf4j  
            slf4j-api  
            1.7.10  
          
  
          
            org.slf4j  
            slf4j-log4j12  
            1.7.10  
          
  
          
          
            org.springframework  
            spring-core  
            3.2.3.RELEASE  
          
  
          
            org.springframework  
            spring-orm  
            3.2.3.RELEASE  
          
  
          
            org.springframework  
            spring-context  
            3.2.3.RELEASE  
          
  
          
          
            org.apache.ibatis  
            ibatis-sqlmap  
            2.3.4.726  
          
  
          
          
            mysql  
            mysql-connector-java  
            5.1.19  
          
  
          
          
            commons-dbcp  
            commons-dbcp  
            1.4  
          
  
          
            commons-pool  
            commons-pool  
            1.6  
          
  
          
          
            org.bouncycastle  
            bcprov-jdk15on  
            1.51  
          
  
          
          
            commons-codec  
            commons-codec  
            1.6  
          
  
      
  

你可能感兴趣的:(Maven 项目打包需要注意到的那点事儿)