Eclipse 下的 Java 工程迁移至 Maven

需要一个小小的算法,在 GitHub 上找到一个相关的原型工程,拉下来后发现要把它跑起来有点困难。代码距今已经达八年之久,工程文件是 .project,找了一下信息后基本可以确定,如果你有 Eclipse+JDT,应该就是可以直接打开的,然而我没有。我只有一个百纳环境来处理这些非日常工程,那就是 VSCode,可是它里面集成的插件只认 maven 构建所需的 pom.xml

于是开始寻找如何从 .project 迁移到 pom.xml。找到的方案大多令人啼笑皆非,说 Eclipse 下有个插件可以做到这件事,可问题是我如果有个 Eclipse 那就不需要做这件事了。最后决定查阅这两种工程之间的具体差别,手工完成 pom.xml

神奇的是,maven 的工程好像也还需要 .project 文件的存在,只是要补充一些内容进去。原始文件内容如下:

添入 maven 所需内容后如下:

第一步结束。接下来要手工打造 pom.xml 了,先构造一个框架,如下:

其中,从 groupIdurl 根据工程自身的信息填写就好了。接下来要在 properties 下增加两个节点,dependenciesbuild。在实际的操作中,前者里的明细条目可能是需要把后者基本完善到能够执行构建过程后才能一一补充完整的。最终的 pom.xml 内容如下:

build 节点下的 plugins 下的三个 plugin,一个是编译器,一个是打包器,一个是依赖包处理器。最重要的是,我一开始漏掉了 sourceDirectory,导致打出来的 jar 文件里没有任何代码。你一次次地尝试编译,根据出错信息就可以把 dependencies 节点下的各个 dependency 列举完了。我的实际经历还要更悲催一些,因为代码太老,有些依赖的包名都发生了变化,不过最终还是搞定了。

打包并不止一种方式,上面的方式是把依赖包复制到主包所在路径下,还有一种把所有依赖都打进最终单一包体内的方法。以下所附文章内容中说的很详细。


Maven 生成可以直接运行的 jar 包的多种方式

Maven 可以使用 mvn package 指令对项目进行打包,如果使用 java -jar xxx.jar 执行运行 jar 文件,会出现“no main manifest attribute, in xxx.jar”(没有设置 Main-Class)、ClassNotFoundException(找不到依赖包)等错误。

要想 jar 包能直接通过 java -jar xxx.jar 运行,需要满足:

1、在 jar 包中的 META-INF/MANIFEST.MF 中指定 Main-Class,这样才能确定程序的入口在哪里;

2、要能加载到依赖包。

使用 Maven 有以下几种方法可以生成能直接运行的 jar 包,可以根据需要选择一种合适的方法。

方法一:使用 maven-jar-plugin 和 maven-dependency-plugin 插件打包

pom.xml 中配置:

maven-jar-plugin 用于生成 META-INF/MANIFEST.MF 文件的部分内容,<mainClass>com.xxg.Main</mainClass> 指定 MANIFEST.MF 中的 Main-Class<addClasspath>true</addClasspath> 会在 MANIFEST.MF 加上 Class-Path 项并配置依赖包,<classpathPrefix>lib/</classpathPrefix> 指定依赖包所在目录。

例如下面是一个通过 maven-jar-plugin 插件生成的 MANIFEST.MF文件片段:

只是生成 MANIFEST.MF 文件还不够,maven-dependency-plugin 插件用于将依赖包拷贝到 <outputDirectory>${project.build.directory}/lib</outputDirectory> 指定的位置,即 lib 目录下。

配置完成后,通过 mvn package 指令打包,会在 target 目录下生成 jar 包,并将依赖包拷贝到 target/lib 目录下,目录结构如下:

指定了 Main-Class,有了依赖包,那么就可以直接通过 java -jar xxx.jar 运行 jar 包了。

这种方式生成 jar 包有个缺点,就是生成的 jar 包太多不便于管理,下面两种方式只生成一个 jar 文件,包含项目本身的代码、资源以及所有的依赖包。

方法二:使用 maven-assembly-plugin 插件打包

pom.xml 中配置:

打包方式:

打包后会在 target 目录下生成一个 xxx-jar-with-dependencies.jar 文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过 java -jar 来运行。

此外还可以直接通过 mvn package 来打包,无需 assembly:single,不过需要加上一些配置:

其中 <phase>package</phase><goal>single</goal> 即表示在执行 package 打包时,执行 assembly:single,所以可以直接使用 mvn package 打包。

不过,如果项目中用到 Spring Framework,用这种方式打出来的包运行时会出错,使用下面的方法三可以处理。

方法三:使用 maven-shade-plugin 插件打包

pom.xml 中配置:

配置完成后,执行 mvn package 即可打包。在 target 目录下会生成两个 jar 包,注意不是 original-xxx.jar 文件,而是另外一个。和 maven-assembly-plugin 一样,生成的 jar 文件包含了所有依赖,所以可以直接运行。

如果项目中用到了 Spring Framework,将依赖打到一个 jar 包中,运行时会出现读取 XML schema 文件出错。原因是 Spring Framework 的多个 jar 包中包含相同的文件 spring.handlersspring.schemas,如果生成一个 jar 包会互相覆盖。为了避免互相影响,可以使用 AppendingTransformer 来对文件内容追加合并:


另外还有一篇文章详述 pom.xml 中的各个节点的含义,实在太长,就不全文引入了:https://www.cnblogs.com/hafiz/p/5360195.html

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注