class 增量发包改造为 jar 包方式发布
haoteby 2025-01-15 13:31 3 浏览
大纲
- class 增量发包介绍
- 项目目录结构介绍
- jar 包方式发布落地方案
class 增量发包介绍
当前项目的迭代修复都是通过 class 增量包来发版本的
将改动的代码 class 增量打包,如下图
class 发包方式优点
- class 增量发布,增量包体积较小
- 出现问题时,可以本地打log编译后,临时替换对应 class,便于调试
- 可以方便的看出本地迭代包文件变动情况 (用户不太关心)
但是也存在一些问题,开发人员维护困难,主要体现在以下几个点
- 每次编译后需要开发人员根据变动记录,手动收集本次迭代变动 class,容易出现错漏
- 本地打包后,一个 class可能会生成 n 个 class 文件 (FileToolsUI$1.class,FileToolsUI$2.class); ( 在 idea 中是看不出来的,必须在目录下才能看到) 导致增量包经常出问题...
- 经常要维护一个稳定版本的全量基线包
- 由于是 class 增量升级,误打包或重构删除的类,客户那边依旧会冗余,不利于重构; (而当前项目代码臃肿,项目亟需重构 很多java文件代码量的比较大 3k,5k,7k代码; )
于是大家商量一下想改变升级包提供方式,通过提供全量可 jar 包升级
项目目录结构介绍
项目工程结构如下
KingDomFileToolCombine
java 源代码
resources 资源目录1
source 资源目录 2
doc 文档
lib 外部依赖 jar 包存放目录
由于早期项目没有使用构建工具,当初导入项目也是花了些时间;
具体可以查看 idea 导入并配置非标准maven工程
jar 包方式发布落地方案
改造后要求满足以下需求
- 当前项目 jar包形式发布
- 外部依赖单独存放在 lib目录下 (减少升级包体积)
- 配置文件单独存放在jar包的同级目录的bin目录下 (方便用户调整配置)
使用 maven 打 jar'包方案实现步骤如下
- 添加 pom.xml 使用 maven 管理依赖
- 使用 maven <systemPath>管理本地 jar 包
- 选择maven构建插件,打 jar 包
- 刷新 maven 依赖; (最好是手动删除 project structure中的依赖,然后刷新maven)
- mvn clean package 打 jar 包
- cd 到目录下 java -jar xxx.jar 启动应用
pom,xml 配置如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.szkingdom.filetool</groupId>
<artifactId>KingDomFileToolCombine</artifactId>
<version>V3.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>7</maven.compiler.source>
<maven.compiler.target>7</maven.compiler.target>
<!-- Java版本 -->
<java.version>1.7</java.version>
<!-- 通过${hutool.version}来使用 -->
<spring.version>3.2.2.RELEASE</spring.version>
</properties>
<dependencies>
<!-- 使用 maven <systemPath>管理本地 jar 包
项目依赖的外部jar 是放在/lib目录下 (有的jar存在多版本)
- 1 <scope>system</scope>
- 2 <systemPath>${project.basedir}/lib/dom4j-1.6.1.jar</systemPath>
- 3 实在不知道 groupId 的用了自定义值替换; 比如local
- 4 在maven-dependency-plugin 打包到 lib 目录时,会改变jar名称为 (artifactId-version.jar)
- 5 配置完成后重新刷新 maven 依赖 (idea 中建议先手动移除
project structure>modules>dependencies 中的依赖,刷新后maven会自动配置)
-->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
<!--system,类似provided,需要显式提供依赖的jar以后,Maven就不会在Repository中查找它-->
<scope>system</scope>
<systemPath>${project.basedir}/lib/dom4j-1.6.1.jar</systemPath>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<!--
在maven-dependency-plugin 打包到 lib 目录时,会改变 jar 名称为 (artifactId-version.jar; )
将原 jar包数字拆分到 <version>;可以实现重新打包后名称不变 如: bcprov-jdk15-133.jar
-->
<version>133</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/bcprov-jdk15-133.jar</systemPath>
</dependency>
<dependency>
<!--实在不知道 groupId 的用了自定义值替换; 比如local-->
<groupId>local</groupId>
<artifactId>chinapnr</artifactId>
<!--实在不知道 version 的用了自定义值替换; 比如localversion;
在maven-dependency-plugin 打包到 lib 目录时,
会改变 jar 名称为 (artifactId-version.jar;如: chinapnr-localversion.jar )
需要配合 maven-jar-plugin <Class-Path>标签一起使用,
配置的 class-path jar名称为 chinapnr-localversion.jar
-->
<version>localversion</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/chinapnr.jar</systemPath>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/spring-beans-3.2.2.RELEASE.jar</systemPath>
</dependency>
</dependencies>
<build>
<!--构建后 jar 文件名称-->
<finalName>kingDomFileToolCombine</finalName>
<!--java 源代码所在目录 默认 src/main/java-->
<sourceDirectory>java</sourceDirectory>
<!--配置文件所在目录 默认 src/main/resources-->
<scriptSourceDirectory>source</scriptSourceDirectory>
<!--<!–构建目录 默认target–>-->
<directory>bin</directory>
<!--编译后class存放目录 默认target/classes-->
<outputDirectory>bin</outputDirectory>
<!--资源文件夹,可配置多个-->
<resources>
<resource>
<directory>resources</directory>
</resource>
<resource>
<directory>source</directory>
</resource>
</resources>
<!--插件打包-->
<plugins>
<!--在打包阶段将依赖的jar包导出到lib目录下-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<outputDirectory>out/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<!-- 生成MANIFEST.MF的设置 -->
<manifest>
<useUniqueVersions>false</useUniqueVersions>
<!-- jar启动入口类 -->
<mainClass>com.szkingdom.FileTools.UI.FileToolsSurface</mainClass>
<!-- 为依赖包添加路径, 这些路径会写在MANIFEST文件的Class-Path下 -->
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<!--将依赖.jar 写进MANIFEST.MF文件中的Class-Path-->
<Class-Path>lib/bcprov-jdk15-133.jar lib/cipher-localversion.jar</Class-Path>
</manifestEntries>
</archive>
<!-- 指定打包后 jar包的位置,设置为根目录下 /out -->
<outputDirectory>out</outputDirectory>
<excludes>
<exclude>*.jar</exclude> <!--排除打包后的 jar文件本身-->
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
打包启动 jar 后报错记录解决
mvn clean package 打包 后 cd 到 jar 所在目录 java -jar 启动程序
#### Error assembling JAR: A zip file cannot include itself
- 装配JAR错误:zip文件不能包含自身
```asp
<excludes>
<exclude>*.jar</exclude> <!--排除打包后的 jar文件本身-->
</excludes>
```
#### java -jar 运行程序报错, java.lang.NoClassDefFoundError
- java.lang.NoClassDefFoundError 找不到外部依赖的 jar
- 解决:
- 1 打包时插件配置 <Class-Path>
- 2 需要将 lib 目录放到 jar同级别目录
#### java -jar 运行程序报错, java.lang.Error: Properties init: Could not determine current working directory.
- 原因: 找不到当前所在目录; 每次重新 mvn clear package 时 ,旧的命令行窗口所在目录已经被清除了
- 解决: 重新 cd 到 jar 目录 运行 java -jar
代码改造,之前读取 classpath 下的配置,改造为从 jar 包外文件中读取
//编写配置文件加载工具类
public class ConfigFileUtil {
/**
* 文件分割路径 ,mac windows 适配
*/
public final static String PATH_SPLIT = File.separator;
private static String CONFIG_FILE_PATH;
static {
//System.out.println(" 相对于当前用户目录的相对路径 user.dir :" + System.getProperty("user.dir"));
//获取当前 jar 包路径 .....jar
String jarFilePath = FileUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();
System.out.println(" jar文件所在路径为 :" + jarFilePath);
try {
jarFilePath=URLDecoder.decode(jarFilePath, "utf-8");// 转化为utf-8编码,支持中文
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
File file = new File(jarFilePath);
CONFIG_FILE_PATH = file.getParent();
System.out.println(" 配置文件所在路径为 :" + CONFIG_FILE_PATH);
}
public static String getFileAbsolutePath(String underBinPath) {
String filePath = "";
if (underBinPath.startsWith("bin")) {
filePath = FileUtil.CONFIG_FILE_PATH + FileUtil.PATH_SPLIT + underBinPath;
} else {
filePath = FileUtil.CONFIG_FILE_PATH + FileUtil.PATH_SPLIT + "bin" + FileUtil.PATH_SPLIT + underBinPath;
}
System.out.println(" 配置文件所在绝对路径为 :" + filePath);
return filePath;
}
/**
* @param underBinPath 存放在 /src/main/resources/bin 下的相对路径
* @return
*/
public static FileInputStream getConfigFileInputStream(String underBinPath) {
FileInputStream is = null;
try {
String fileAbsolutePath = getFileAbsolutePath(underBinPath);
is = new FileInputStream(fileAbsolutePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return is;
}
public static FileOutputStream getConfigFileOutPutStream(String underBinPath) {
FileOutputStream os = null;
try {
String fileAbsolutePath = getFileAbsolutePath(underBinPath);
os = new FileOutputStream(fileAbsolutePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return os;
}
项目问题每天不重样,遇到问题解决问题, 调整升级方式为后续代码重构做铺垫
- 上一篇:Fluent网格前处理常见问题
- 下一篇:汽车常见中英文专业术语
相关推荐
- 「乌龟」龟壳对比了几款伤害统计插件,最好用的是它?
-
乌龟服伤害统计插件虽然我们熟悉的Details和Recount,在乌龟服暂时没有很好的迁移,...
- 「听风」WOW网易有爱整合插件功能拆解(上)
-
魔兽小伙伴使用的怀旧服插件一般为大脚、网易有爱、ElvUI等,昨天将大脚整合包插件梳理之后发现插件清晰好多,虽然有些界面还是找不到设置方法,需要花些时间逐个看一下。网易有爱考虑到有一大部小伙伴使用网易...
- 教你使用iOS8插件iVeency 让电脑控制你的iPhone
-
【搞科技教程】iOS8越狱后安装什么插件好?对于一些高玩越狱族来说,他们一直在期待着远程监控插件Veency的更新,在昨日,Cydia之父终于放出了Veency的更新。此次更新支持iOS8完美越狱。来...
- 宝塔面板安全软件/插件有哪些?(宝塔面板5.9 安装命令)
-
许多新手站长在选择服务器管理面板的时候都会考虑包含哪些安全插件。对于安装宝塔Linux面板作为服务器管理软件的用户。建议使用宝塔自带的安全软件。一、免费使用...
- Chrome和火狐插件让数以百万计用户隐私数据泄露
-
7月21日消息,流行浏览器诸如广告拦截等扩展功能,已经遭利用而让数以百万计使用Chrome和火狐(Firefox)的消费者个人数据泄露。遭遇泄露的这些个人数据,不仅涉及他们的浏览历史,而且还包括他们存...
- 如何使用Elasticsearch插件改进性能
-
撰写:PierrePoitevin,高级软件工程师|DanielGeng,软件工程师|萧湖李,工程经理(第一部分)问题TinderEng团队最近一直在致力于将机器学习(ML)算法集成到Tind...
- RL必备插件:ERT--游戏内的战斗分析插件
-
ExorsusRaidTools插件介绍ExorsusRaidTools(以下简称ERT)是来自EUHowlingFjord服务器的Exorsus(NGA俗称3K3)公会开发的一款功能非...
- 魔兽世界7.0军团再临 多功能姓名版插件推荐
-
关键词>>魔兽世界,插件,姓名版,血条,wow魔兽世界7.0军团再临多功能姓名版插件推荐看着新版姓名版不习惯?来看看这款Kui_Nameplates姓名版插件吧!还带技能监视功能哟!K...
- DTU配电自动化站所终端通讯接口有哪些 主控单元可配置多少插件?
-
世东电气HS-6302/DTU配电自动化站所终端通讯接口:...
- 魔兽世界:毒蛇神殿踏潮者很难?5张图教你学会如何通关
-
作为一个最会画画的魔兽世界辣鸡小编,我今天又来分享技术贴了。我们继续用图文并茂...
- Aliexpress速卖通销量监控和一键复制运费模板Chrome插件v0.1
-
发现一个很强大的速卖通插件,支持所有速卖通产品的5天销量监控和一键复制运费模板功能,地址:https://github.com/YouthCodeChen/Aliexpress-Plugin...
- 魔兽世界boss技能提示?魔兽世界DBM插件?
-
魔兽世界boss技能提示可以通过使用DBM插件来实现,DBM是一款老牌首领报警插件。DBM的主要主要功能包括:包含所有团队级首领的警报模块;一些模块具有强大的功能,比如洛欧塞布的治疗者监视器,该功能允...
- 老学长分享10个最强chrome浏览器插件!瞬间开发效率棒棒哒
-
今天老学长给大家推荐几款超强大的谷歌插件!用过都说好!1、Tampermonkey(油猴插件)Tampermonkey(油猴脚本)是一款免费的浏览器扩展和最为流行的用户脚本管理器,它适用于Chro...
- 电脑浏览器无法安装控件问题的解决办法
-
前几天碰到一个监控设备在浏览器浏览时无法找到控件的问题,调整了好几次才改好,所以今天就来分享一下这个问题的解决办法。电脑在日常生活和办公中有可能需要下载安装一些特殊的控件,比如监控软件和各个银行的登录...
- waves11:盘点waves的Meters表类插件
-
俗话说:混音就是"听,不要去看"。作为一门关于声音的艺术,混音的全部内容都关于听的。尽管如此,我们依然能够在混音场所中见到各种仪表,而它们的存在有其然的原因。仪表可以用在混音的很多阶段...