欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring项目导出可运行的JAR 博客分类: SpringMaven Spring3maven可运行jar导出异常 

程序员文章站 2024-03-01 15:43:04
...

一、在使用MAVEN的打包插件。

 

1.背景

    maven现在已经是业界规范了,所以大部分的项目都是采用maven构建。在使用Spring 3的时候,工程中一般不止用到相关的一个spring的JAR。往往用到:spring-context、spring-beans、spring-aop等等一些,同时也会用轻量级的ORM工具mybatis之类的。这就存在Spring的配置文件和mybatis的配置文件。

     在JAVA可运行的ApplicationContext中一般需要使用如下的方式加载Spring3配置文件:

 

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:context/applicationContext.xml");

 

2.问题     

  而基于Spring3的工程在导出runnable JAR的时候如果使用eclipse自带的插件,会出现在指定个路径中找不到applicationContext.xml 或者 applicationContext.xml无法解析的问题。

 

3.原因

  1)找不到applicationContext.xml是由于,maven项目使用eclipse自带的插件导出可执行JAR的时候的目录结构如下图片。项目中的配置文件都被放入到了resources目录下,而从META-INF中可以看到项目的Classpath是该jar的目录,也就是图中所示目录。造成该结果的原因是使用了eclipse自带的插件导出,该工具没有将配置文件直接放入jar所在的目录。

Spring项目导出可运行的JAR
            
    
    博客分类: SpringMaven Spring3maven可运行jar导出异常 

   2)无法解析applicationContext.xml是由于找不到对应的spring.schemas。虽然META-INF中有个spring.schemas,但是打开会发现里头少对beans等标签的使用描述。造成该结果是由于Spring3以后对各个功能模块进行了分包,而诸如spring-context、spring-beans、spring-aop这些模块中都可以找到一个spring.schemas,使用eclipse自带的插件导出时候只是简单的拷贝一个spring.schemas过来,具体是哪一个就需要完全由插件决定,结果不是我们需要的所有的spring.schemas的合并结果。

 

4.解决

  使用MAVEN的插件maven-shade-plugin。配置如下:

 

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>1.7</version>
 
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <finalName>my-spring-app</finalName>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <shadedClassifierName>jar-with-dependencies</shadedClassifierName>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>net.mgorski.path.to.my.main.Clazz</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>
          <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
            <resource>META-INF/spring.tooling</resource>
          </transformer>
        </transformers>
 
      </configuration>
    </execution>
  </executions>
</plugin>

   调用 mvn package 会导出可执行 my-spring-app.jar。该jar包中包含了所有的依赖jar和配置. 然后使用 java -jar my-spring-app.jar 运行即可。从该插件的源码中可以看到该插件对spring-context、spring-beans、spring-aop包中的spring.schemas进行了合并。

 

 

二、手工更改。

   使用了eclipse自带的插件导出Runnable JAR的时候会有如下三种选择:
1.Extract required libraries into generated JAR。                                        ----JAR中是依赖包的class文件。

2.Package required libraries into generated JAR。                                     ----JAR中是依赖的jar包。

3.Copy required libraries into a sub-folder next to the generated JAR。     ---依赖放到了JAR的外部,以jar的形式。

 

    使用第一种方式会造成上述问题。而使用第二中方式就不会出现无法解析applicationContext.xml,这是由于运行后会扫描每个依赖下的spring.schemas。这里Spring还是被放到resources目录下,这里手动调整下JAR,将resources目录下的文件拷贝到JAR的目录下即可,之所以可以这么操作是因为JAR本身只是一个文件结合,在这点上类似于zip和rar。

 

三、总结。

    在使用maven的时候使用插件肯定最好,如果不清楚原理的话,手动操作下。

 

 

参考

1.http://mgorski.net/2013/dev/executable-jar-with-spring-based-application-inside-usin-maven

2.http://maven.apache.org/plugins/maven-shade-plugin/index.html