说明:打包maven结构项目的工程,不能像打包javaweb工程一样,直接通过配置新的Java Application入口,然后在通过Export—>Runnable JAR file的方式导出;因为这样做,会按照目录结构直接将resource目录下的资源文件打包进resource目录,而不是项目根目录下面,在程序中通过ClassPathXMLApplication方式访问配置文件时候,会出现找不到资源的情况;
一、背景介绍
本项目是一个通过maven构建的Javaweb工程,项目中使用Spring+mybatis+webmagic框架来做开发,写了几个爬虫,然后用一个方法将几个爬虫集成在一起,通过传出参数,分别调用不同的爬虫,最后需要将爬虫作为定时任务独立运行在Linux服务器上;
因为项目中集成了其他的框架,并且需要将爬取的数据存储到数据库,所以在打包时候,需要将spring、mybatis以及其他项目依赖的jar包都需要打入到同一个可执行的Jar包中;
二、 资源发现、方案寻找
在将项目打包成可执行的jar包时,可能有两种原因:
- 1.将项目打包成为一个工具包,提供给其他工程使用,这种方式不需要将依赖包添加进去;
- 2.最终打包出来的jar包可以成为一个独立运行的Jar包,这种情况就需要将项目及所依赖的所有Jar包打包成一个Jar;
在文章开始已经说明不能通过直接导出的方式来解决,既然是maven工程,那么可以利用maven的插件来实现,以下链接是网上比较靠谱(我都试过,但是都没有成功解决问题,但是提供了思路)的解决方案:
三、最终解决方案
通过以上的资源,我尝试了很多次,但是每次运行都会出错,比如以下错误:
- 错误1:
C:\Users\shexia> java -jar C:\Users\shexia\Desktop\SpiderMan.jar pageProcessor
...
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Unrecognized xbean namespace mapping: http://www.springframework.org/schema/context
at org.apache.xbean.spring.context.v2c.XBeanNamespaceHandler.parseBeanFromExtensionElement(XBeanNamespaceHandler.java:284)
at org.apache.xbean.spring.context.v2c.XBeanNamespaceHandler.parse(XBeanNamespaceHandler.java:156)
at org.apache.xbean.spring.context.v2.XBeanNamespaceHandler.parse(XBeanNamespaceHandler.java:49)
at
...
解决方法:
在使用ClassPathXmlApplicationContext时,导入包为
import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
,应该使用
import org.springframework.context.support.ClassPathXmlApplicationContext;
错误2:
C:\Users\shexia>java -jar C:\Users\shexia\Desktop\SpiderMan.jar StorebtPageProcessor
...
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]
Offending resource: class path resource [spring/spring-service.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.java:316)
...
- 解决方法:
在resource目录下,先建META-INF文件夹,合并所有与spring相关的spring.schemas,spring.handlers,spring.tooling;
最终pom中插件如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<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>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>edu.cqupt.service.impl.ServiceFactory</Main-Class>
<Build-Number>123</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
四、 打包成jar包
在打包时,需要把pom文件中packaging属性值改为jar,这样打出来的包才是jar包。
执行命令mvn clean install ,将会把jar包打入到target目录中,在target目录中,会存在两个jar包:
- original-XXX.jar 这个jar包中,只包括本项目中的class文件;
- xxx.jar 不仅包括本项目中的class文件,还包括项目依赖的class文件;
五、参考
- http://maven.apache.org/plugins/maven-assembly-plugin/examples/single/filtering-some-distribution-files.html#
- http://maven.apache.org/plugins/maven-assembly-plugin/advanced-descriptor-topics.html
- http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html
- http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html
- https://stackoverflow.com/questions/1937767/spring-3-0-unable-to-locate-spring-namespacehandler-for-xml-schema-namespace