为减少软件升级资源的大小,希望对升级资源各个包进行识别,本地已经有的包,就不需要下载。通过比较文件大小方式存在隐患,并不能彻底解决上述问题。所以采用文件hashCode方式来识别。
在feature文件夹内增加各个jar包的hashcode,更新软件时,对比本地和服务器上jar的hashcode,hashcode一致的文件包不下载。
参见https://blog.csdn.net/YeahToYeah/article/details/123772742 如下
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.math.BigInteger; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class FileHashUtil { private static final int A1024 = 1024; public static String md5HashCode(InputStream fis) { try { MessageDigest md = MessageDigest.getInstance("MD5"); // 分次读入,于大型文件而言,占用内存比较少。 byte[] buffer = new byte[A1024]; int length = -1; while ((length = fis.read(buffer, 0, A1024)) != -1) { md.update(buffer, 0, length); } fis.close(); // 转换并返回包含16个元素字节数组,返回数值范围为-128到127 byte[] md5Bytes = md.digest(); BigInteger bigInt = new BigInteger(1, md5Bytes);// 1代表绝对值 return bigInt.toString(16);// 转换为16进制 } catch (Exception e) { e.printStackTrace(); return ""; } } public static String hashFile(File file) throws Exception { String sha256 = null; try (FileInputStream inputStream = new FileInputStream(file)) { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte buffer[] = new byte[A1024]; int length = -1; while ((length = inputStream.read(buffer, 0, A1024)) != -1) { md.update(buffer, 0, length); } byte[] digest = md.digest(); sha256 = byte2hexLower(digest); } catch (Exception e) { e.printStackTrace(); throw new Exception("计算文件hash值错误"); } return sha256; } private static String byte2hexLower(byte[] b) { String hs = ""; String stmp = ""; for (int i = 0; i < b.length; i++) { stmp = Integer.toHexString(b[i] & 0XFF); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs; } public static String encodeSHA(String content) { byte[] inputData = content.getBytes(); try { MessageDigest messageDigest = MessageDigest.getInstance("SHA"); messageDigest.update(inputData); BigInteger sha = new BigInteger(messageDigest.digest()); return sha.toString(32); } catch (Exception e) { e.printStackTrace(); } return null; } private static String getHashCode(File file) { if (!file.exists()) return ""; if (file.isFile()) { String hashCode = ""; try { hashCode = FileHashUtil.md5HashCode(new FileInputStream(file)); } catch (Exception e) { } return hashCode; } else if (file.isDirectory()) { Map<String, String> fileHashMap = new HashMap<String, String>(); File[] listFiles = file.listFiles(); for (int i = 0; i < listFiles.length; i++) { File file2 = listFiles[i]; String hashCode = getHashCode(file2); fileHashMap.put(file2.getAbsolutePath(), hashCode); } List<String> collect = new ArrayList<String>(fileHashMap.keySet()); Collections.sort(collect); StringBuilder sb = new StringBuilder(); for (int i = 0; i < collect.size(); i++) { String obj = collect.get(i); String string = fileHashMap.get(obj); sb.append(string); } return encodeSHA(sb.toString()); } return ""; } /** * 参数需要两个以上,最后一个参数指明存放hashcode的文件 * @param args */ public static void main(String[] args) { write(args); } public static void write(String[] args) { if (args != null && args.length > 1) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length - 1; i++) { File file = new File(args[i]); String hashCode = getHashCode(file); sb.append(file.getName()).append("="); sb.append(hashCode).append("\r\n"); } File file = new File(args[args.length - 1]); String string = sb.toString(); System.out.println("hashcode:"+string); try (FileOutputStream outStream = new FileOutputStream(file)) { outStream.write(string.getBytes()); outStream.close(); } catch (Exception e) { e.printStackTrace(); } } } }
为防止java版本不同对于FileHashUtil.class 的不支持,我们使FileHashUtil在调用之前每次编译,生成.class文件。如下:
<javac destdir="${basedir}/javaclasses" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" source="${javacSource}" target="${javacTarget}">
<classpath refid="compile.classpath" />
<src path="${basedir}/FileHashUtilPath/" /> <!-- 注意这里不能直接编译java文件,只能编译目录-->
</javac>
先将编译的class文件,打成jar包。
<jar jarfile="${basedir}/FileHashUtil.jar" basedir="${basedir}/javaclasses"/>
在ant中调用FilehashUtil.jar写出hash值文件,并移动到指定位置:
<java classname="FileHashUtil" classpath="${basedir}/FileHashUtil.jar" fork="true" failonerror="true" >
<arg value="${build.result.folder}"/>
<arg value="${eclipse.home}/${bundleId}_hash.txt"/>
</java>
<move file="${eclipse.home}/${bundleId}_hash.txt" todir="${eclipse.plugins.home}" overwrite="true" failonerror="false" />
在构建全部的jar后,将全部的hash.txt写入到feature中,在更新时,取得feature.jar中的hash.txt.供在线升级程序做比较用。
ant的使用
http://www.codebaoku.com/ant/ant-length-task.html
http://t.zoukankan.com/fnlingnzb-learner-p-6279189.html
https://www.cnblogs.com/sky-heaven/p/5883634.html
相关推荐
最后找到原因是因为同一个id被启动了两次(第一次是之前使用vue组件时启动的,另外一个是路由时启动的) 附上部分代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- 引入...
"v3-admin:vue3 with ant-design-vue管理员"是一个基于Vue3框架和ant-design-vue UI库构建的后台管理界面。这个项目主要是为了提供一个高效、易用且功能丰富的前端管理界面,开发者可以在此基础上进行二次开发,满足...
例如,`build.xml`可能是一个Ant构建文件,用于编译Java源代码、打包成可执行jar文件以及执行测试。而`build-user.xml`可能是针对特定用户或环境的配置文件,用于定制构建过程。 3. `src`:这是一个源代码目录,...
// 打包路由为 hash 模式 yarn run build:hash 发布到 github-pages yarn run deploy 项目依赖 antd reactui 库 @ant-design/icons antd图标组件包 mobx 状态管理 mobx-react 在 react 中使用 mobx react-router-dom...
9. **Build工具**:项目中的`build.xml`文件可能是Ant构建脚本,用于自动化构建、编译和打包过程。 10. **源代码**:`src`目录可能包含了项目的源代码,用户可以查看和学习Chord协议的具体实现细节。 11. `build`...
在本项目中,我们主要探讨的是一个基于Ant Design、React和Axios的后端管理系统,采用了Hash Router V6作为路由管理方案。这个压缩包“vite04.zip”包含了实现这样一个系统的必要组件和配置。 首先,让我们从React...
4. **Less 变量替换**:通过 Less 加载器(less-loader),可以进行 Less 变量替换,比如 Ant Design 的图标字体文件路径可以通过变量替换功能动态设置。 5. **React 组件热加载**:`react-hot-loader` 配合 `...
这个中间件的作用是在找不到对应静态资源时,将所有请求重定向到应用的入口文件,通常是`index.html`,让Vue Router在客户端处理路由。 以下是一个简单的Node.js服务器配置示例,展示了如何使用`connect-history-...
- 将应用程序打包成可执行的JAR或WAR文件运行。 - **题目解析**: 使用Ant脚本运行不是Spring Boot推荐的运行方式之一,因此正确答案是`D: 使用Ant脚本运行`。 #### 21. 运算符优先级 - **知识点**: Java中运算符有...
3. **build.xml** 文件:Ant 构建脚本,用于编译、打包和测试 emu-csp 模块。 4. **README** 文件:提供了项目的基本信息和构建/运行指南。 通过阅读和分析 emu-csp 源码,我们可以学习到以下关键知识点: 1. **...