为了快速的落地一个项目,工期压缩极短,领导说可以用老项目的部分业务代码。
就这一句话,连环坑踩起来。
Emo……
简单介绍一下老项目:
老项目是2015年开发的,主业务是一个解析CNML文件,经过一系列业务处理(其中涉及到一些计算逻辑)后入库的任务调度项目,并且支持搜索。
这个项目是基于一个TCM(任务调度平台)开发的。
其最终作为一个jar(一个任务插件)运行在任务调度平台。
可能是2015年,当年写这个项目的老哥还不习惯用maven构建吧,直接添加的lib库目录,增加了MANIFEST.MF文件。
结构如下:
这里简单说明一下MANIFEST.MF文件的用法:
Java打包文件(jar文件)中一般会包含清单文件(META-INF/MANIFEST.MF),该文件能够包含主类以及加载类路径等信息。
该文件有着严格的格式要求,甚至一个空格都会引发错误。 java MANIFEST.MF格式特别须要注意如下几点:
- 文件中的内容以键值对的形式出现,键值对之间采用"冒号+空格"进行分隔(注意:冒号后的空格必须有,不然格式有错误)
- 文件每行最多72个字符,能够分多行写。调用多个jar时,能够把调用的jar的路径写到一行,每一个用空格隔开。当调用的jar比较多时,写在一行就比较多,并且看起来也不方便,因此更多时候是一行写一个jar,可是要注意,每行开头要至少一个空格。
- 文件的最后必需要空两行,而且这两行都必须顶格。
使用这个MANIFEST.MF生成的jar,就能够使用java -jar xxx.jar直接调用执行了.
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: pjq
Build-Jdk: 1.8.0_251
Class-Path: avro-1.7.7.jar axis-1.4.jar cnml-basic-java-api-1.4d_sun.jar
Main-Class: com.hhy.Main
好吧,因为原来的项目涉及到任务调度,所以统一需要放到任务调度平台运行,但是现在的项目场景下是不需要在任务调度平台统一运行(完全没必要),而且原来用的任务调度平台并不是开源调度平台,是跟其他公司商业合作的,这就有点尴尬,一个字,没文档,啥也没有!
通过来来回回的和跟老项目的项目负责人拉扯,终于找到了一些文档,全是任务调度平台的文档,老项目的文档是一个也没有。
好吧,自己看代码,花了点时间看了下代码,发现里面接入了调度平台的SPI,通过调度平台来调度。
PS:(强颜欢笑的认为)零零散散的get到一些设计方法,思考了一下这样设计的背后需求,接着梳理这个项目的业务流程…… over
终于,代码中的业务流程理清了,权衡利弊后,决定不再用该调度平台(偏重),兴致勃勃的大刀阔斧的进行重构工作。
重构结构如下:
没想到,没想到,真的没想到:
1.使用的一些离线计算,需要依托调度平台(解决办法,干掉这一部分)使用了com.sun.image.codec.jpeg包
2.使用maven重构,直接用schedule进行调度,但是解析CNML等,还有一些业务逻辑处理,依赖了一些jar包,非公有jar,考虑到这些都是其他人写的私jar,便没有install进maven库,resource下新建了个libs,将这些jar仍了进去。(好家伙,可以直接运行,但是编译不通过)
3.部分外部调用的接口所具有的功能需要重写,没法用(头大)。
现在,一步一步来,第一个问题,已经被我砍掉了,既然让人纠结,若不重要,就把它从业务层面砍掉,这是我的一贯操作。
麻烦事来了,就在第二个问题上。
先说结果:这个问题是两个主要原因造成,一个是在原来的业务代码中使用了com.sun.image.codec.jpeg包,另一个问题是在原来引入的私jar中使用了其他jar的包,就是包没拷全,好家伙。
第一个原因的解决办法,stack overflow上找到了答案,在pom中加入sun的一些jar的引入。 第二个原因的解决办法,总不能把那些包都拉过来吧(30多个jar),不行,一个一个试吧(出一个错引入一个),通过报错提示的全类名(会报java.lang.ClassNotFoundException: xxx.xxx.xxxxException 类没有发现异常),去比较老项目lib库中的jar,从而引入,所幸没有多少,只缺失了两个jar。
最终,终于将所有问题都处理掉了,花了整整大半天时间,老项目重构就真是坑,处理过的老项目重构,就没有一个利索的。
后面就是一个业务补充和填充了,好家伙,真怕以后review code的时候,说这些代码是我写的,毕竟是我重构的,时间太紧没办法,只能复用老项目业务代码了。
这里列出自己解决问题的一个指导性思路: 遇到问题不能陷入自己固化的认知,一定要怀疑任何东西,从整体来考虑,再去排除边缘因素,再去抽丝剥茧定位本质,借助stack overflow。
这里贴出maven构建的项目引入第三方jar库,新建lib添加为lib库,和解决com.sun.image.codec.jpeg包引入后编译出错的方法:
如上图,完成1、2步骤后,需要在pom.xml中做配置。 配置如下:
<dependencies>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>xxx-lib</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${project.basedir}/src/main/resources/libs/xxx-lib-2.1-jdk15.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
<compilerArguments><verbose/><bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
其中,dependency中scope需要设置为system,需要添加systemPath,systemPath中使用${project.basedir}作为项目根路径,这个变量不需要再额外添加property去配置。
rt.jar等的引入是为了解决com.sun.image.codec.jpeg包引入后编译出错。
至此,一大半问题已经处理,年后来再干了,明天回家!