e2

滴滴侠,fai抖

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1. 关于 Maven 打 war 包

使用 Eclipse 的 Maven 2 插件开发一个 JEE 项目》详细介绍了如何在 Eclipse 使用 Maven 新建一个 JEE 项目并对其进行断点跟踪调试,但是没有介绍如何对 JEE 项目打 war 包。其实很简单,你只需要把 pom.xml 中的 <packaging>jar</packaging> 换成 <packaging>war</packaging> 就可以使用 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 类,其源码如下:
  1.  
    package com.defonds;
  2.  
     
  3.  
    import org.springframework.context.ApplicationContext;
  4.  
    import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
     
  6.  
    import com.defonds.service.LinkPayAntharService;
  7.  
     
  8.  
    public class RsaEncryptor {
  9.  
     
  10.  
    public static void main(String[] args) {
  11.  
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  12.  
    LinkPayAntharService linkPayAntharService = (LinkPayAntharService) context.getBean("linkPayAntharService");
  13.  
    linkPayAntharService.dealWithYearData();
  14.  
    }
  15.  
    }

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 中加入如下代码:
  1.  
    <build>
  2.  
    <plugins>
  3.  
    <plugin>
  4.  
    <artifactId>maven-assembly-plugin</artifactId>
  5.  
    <configuration>
  6.  
    <appendAssemblyId>false</appendAssemblyId>
  7.  
    <descriptorRefs>
  8.  
    <descriptorRef>jar-with-dependencies</descriptorRef>
  9.  
    </descriptorRefs>
  10.  
    <archive>
  11.  
    <manifest>
  12.  
    <mainClass>com.defonds.RsaEncryptor</mainClass>
  13.  
    </manifest>
  14.  
    </archive>
  15.  
    </configuration>
  16.  
    <executions>
  17.  
    <execution>
  18.  
    <id>make-assembly</id>
  19.  
    <phase>package</phase>
  20.  
    <goals>
  21.  
    <goal>assembly</goal>
  22.  
    </goals>
  23.  
    </execution>
  24.  
    </executions>
  25.  
    </plugin>
  26.  
    </plugins>
  27.  
    </build>

执行 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 替代:
  1.  
    <build>
  2.  
    <plugins>
  3.  
    <plugin>
  4.  
    <groupId>org.apache.maven.plugins</groupId>
  5.  
    <artifactId>maven-shade-plugin</artifactId>
  6.  
    <version>1.4</version>
  7.  
    <executions>
  8.  
    <execution>
  9.  
    <phase>package</phase>
  10.  
    <goals>
  11.  
    <goal>shade</goal>
  12.  
    </goals>
  13.  
    <configuration>
  14.  
    <transformers>
  15.  
    <transformer
  16.  
    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  17.  
    <mainClass>com.defonds.RsaEncryptor</mainClass>
  18.  
    </transformer>
  19.  
    <transformer
  20.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  21.  
    <resource>META-INF/spring.handlers</resource>
  22.  
    </transformer>
  23.  
    <transformer
  24.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  25.  
    <resource>META-INF/spring.schemas</resource>
  26.  
    </transformer>
  27.  
    </transformers>
  28.  
    </configuration>
  29.  
    </execution>
  30.  
    </executions>
  31.  
    </plugin>
  32.  
    </plugins>
  33.  
    </build>

对于多个第三方包 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 添加:
  1.  
    <configuration>
  2.  
    <filters>
  3.  
    <filter>
  4.  
    <artifact>*:*</artifact>
  5.  
    <excludes>
  6.  
    <exclude>META-INF/*.SF</exclude>
  7.  
    <exclude>META-INF/*.DSA</exclude>
  8.  
    <exclude>META-INF/*.RSA</exclude>
  9.  
    </excludes>
  10.  
    </filter>
  11.  
    </filters>
  12.  
    </configuration>

于是我们对 maven-shade-plugin 的配置变成这样:
  1.  
    <build>
  2.  
    <plugins>
  3.  
    <plugin>
  4.  
    <groupId>org.apache.maven.plugins</groupId>
  5.  
    <artifactId>maven-shade-plugin</artifactId>
  6.  
    <version>1.4</version>
  7.  
    <executions>
  8.  
    <execution>
  9.  
    <phase>package</phase>
  10.  
    <goals>
  11.  
    <goal>shade</goal>
  12.  
    </goals>
  13.  
    <configuration>
  14.  
    <filters>
  15.  
    <filter>
  16.  
    <artifact>*:*</artifact>
  17.  
    <excludes>
  18.  
    <exclude>META-INF/*.SF</exclude>
  19.  
    <exclude>META-INF/*.DSA</exclude>
  20.  
    <exclude>META-INF/*.RSA</exclude>
  21.  
    </excludes>
  22.  
    </filter>
  23.  
    </filters>
  24.  
    <transformers>
  25.  
    <transformer
  26.  
    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  27.  
    <mainClass>com.defonds.RsaEncryptor</mainClass>
  28.  
    </transformer>
  29.  
    <transformer
  30.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  31.  
    <resource>META-INF/spring.handlers</resource>
  32.  
    </transformer>
  33.  
    <transformer
  34.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  35.  
    <resource>META-INF/spring.schemas</resource>
  36.  
    </transformer>
  37.  
    </transformers>
  38.  
    </configuration>
  39.  
    </execution>
  40.  
    </executions>
  41.  
    </plugin>
  42.  
    </plugins>
  43.  
    </build>

再次执行 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 如下:
  1.  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2.  
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3.  
    <modelVersion>4.0.0</modelVersion>
  4.  
     
  5.  
    <groupId>settle</groupId>
  6.  
    <artifactId>swiftonrsa</artifactId>
  7.  
    <version>1.0.0</version>
  8.  
    <packaging>jar</packaging>
  9.  
     
  10.  
    <name>swiftonrsa</name>
  11.  
    <url>http://maven.apache.org</url>
  12.  
     
  13.  
    <properties>
  14.  
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  15.  
    </properties>
  16.  
     
  17.  
    <build>
  18.  
    <plugins>
  19.  
    <plugin>
  20.  
    <groupId>org.apache.maven.plugins</groupId>
  21.  
    <artifactId>maven-shade-plugin</artifactId>
  22.  
    <version>1.4</version>
  23.  
    <executions>
  24.  
    <execution>
  25.  
    <phase>package</phase>
  26.  
    <goals>
  27.  
    <goal>shade</goal>
  28.  
    </goals>
  29.  
    <configuration>
  30.  
    <filters>
  31.  
    <filter>
  32.  
    <artifact>*:*</artifact>
  33.  
    <excludes>
  34.  
    <exclude>META-INF/*.SF</exclude>
  35.  
    <exclude>META-INF/*.DSA</exclude>
  36.  
    <exclude>META-INF/*.RSA</exclude>
  37.  
    </excludes>
  38.  
    </filter>
  39.  
    </filters>
  40.  
    <transformers>
  41.  
    <transformer
  42.  
    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  43.  
    <mainClass>com.defonds.RsaEncryptor</mainClass>
  44.  
    </transformer>
  45.  
    <transformer
  46.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  47.  
    <resource>META-INF/spring.handlers</resource>
  48.  
    </transformer>
  49.  
    <transformer
  50.  
    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  51.  
    <resource>META-INF/spring.schemas</resource>
  52.  
    </transformer>
  53.  
    </transformers>
  54.  
    </configuration>
  55.  
    </execution>
  56.  
    </executions>
  57.  
    </plugin>
  58.  
    </plugins>
  59.  
    </build>
  60.  
     
  61.  
     
  62.  
    <dependencies>
  63.  
     
  64.  
    <!-- logs -->
  65.  
    <dependency>
  66.  
    <groupId>log4j</groupId>
  67.  
    <artifactId>log4j</artifactId>
  68.  
    <version>1.2.17</version>
  69.  
    </dependency>
  70.  
     
  71.  
    <dependency>
  72.  
    <groupId>commons-logging</groupId>
  73.  
    <artifactId>commons-logging</artifactId>
  74.  
    <version>1.2</version>
  75.  
    </dependency>
  76.  
     
  77.  
    <dependency>
  78.  
    <groupId>org.slf4j</groupId>
  79.  
    <artifactId>slf4j-api</artifactId>
  80.  
    <version>1.7.10</version>
  81.  
    </dependency>
  82.  
     
  83.  
    <dependency>
  84.  
    <groupId>org.slf4j</groupId>
  85.  
    <artifactId>slf4j-log4j12</artifactId>
  86.  
    <version>1.7.10</version>
  87.  
    </dependency>
  88.  
     
  89.  
    <!-- spring -->
  90.  
    <dependency>
  91.  
    <groupId>org.springframework</groupId>
  92.  
    <artifactId>spring-core</artifactId>
  93.  
    <version>3.2.3.RELEASE</version>
  94.  
    </dependency>
  95.  
     
  96.  
    <dependency>
  97.  
    <groupId>org.springframework</groupId>
  98.  
    <artifactId>spring-orm</artifactId>
  99.  
    <version>3.2.3.RELEASE</version>
  100.  
    </dependency>
  101.  
     
  102.  
    <dependency>
  103.  
    <groupId>org.springframework</groupId>
  104.  
    <artifactId>spring-context</artifactId>
  105.  
    <version>3.2.3.RELEASE</version>
  106.  
    </dependency>
  107.  
     
  108.  
    <!-- ibatis -->
  109.  
    <dependency>
  110.  
    <groupId>org.apache.ibatis</groupId>
  111.  
    <artifactId>ibatis-sqlmap</artifactId>
  112.  
    <version>2.3.4.726</version>
  113.  
    </dependency>
  114.  
     
  115.  
    <!-- connector -->
  116.  
    <dependency>
  117.  
    <groupId>mysql</groupId>
  118.  
    <artifactId>mysql-connector-java</artifactId>
  119.  
    <version>5.1.19</version>
  120.  
    </dependency>
  121.  
     
  122.  
    <!-- dbcp -->
  123.  
    <dependency>
  124.  
    <groupId>commons-dbcp</groupId>
  125.  
    <artifactId>commons-dbcp</artifactId>
  126.  
    <version>1.4</version>
  127.  
    </dependency>
  128.  
     
  129.  
    <dependency>
  130.  
    <groupId>commons-pool</groupId>
  131.  
    <artifactId>commons-pool</artifactId>
  132.  
    <version>1.6</version>
  133.  
    </dependency>
  134.  
     
  135.  
    <!-- rsa encrypt -->
  136.  
    <dependency>
  137.  
    <groupId>org.bouncycastle</groupId>
  138.  
    <artifactId>bcprov-jdk15on</artifactId>
  139.  
    <version>1.51</version>
  140.  
    </dependency>
  141.  
     
  142.  
    <!-- commons-codec -->
  143.  
    <dependency>
  144.  
    <groupId>commons-codec</groupId>
  145.  
    <artifactId>commons-codec</artifactId>
  146.  
    <version>1.6</version>
  147.  
    </dependency>
  148.  
     
  149.  
    </dependencies>
  150.  
    </project>


posted on 2018-07-01 15:17  纯黑Se丶  阅读(436)  评论(0编辑  收藏  举报