老旧Java Web应用实现增量自动化部署的一个方案


声明:本文转载自https://my.oschina.net/u/2288883/blog/1797722,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

    如果你也有一个老旧的Java Web应用,因为各种原因,代码库中的代码是不完整的,所以每次上线只能增量部署,或者研发规范里就要求增量部署,在这种情况下如何实现自动化的编译和部署呢?下面给出一个可行的方案:

    1、部署前,将需要部署的代码合并到deliver分支

    2、比较deliver分支和master分支的差异,得到差异列表之后,用于后续的编译

    3、编译差异文件时,需要将应用所依赖的jar,已经部署的class文件等加入到CLASSPATH

    4、如果各测试环境也使用这一套自动部署的方案,可能还需要考虑剥离环境相关的配置到配置文件中,并根据环境分目录存放,具体可以参考maven的profile机制

    核心代码(代码结构请自行优化 :D):

    1、比较两个分支的差异(忽略whitespace带来的差异):

        try (Git git = Git.open(gitRepoFile);                 ByteArrayOutputStream out = new ByteArrayOutputStream();                 DiffFormatter df = new DiffFormatter(out);) {              Repository repository = git.getRepository();             ObjectReader reader = repository.newObjectReader();              String branchName = repository.getBranch();              ObjectId masterId = repository.resolve("remotes/origin/master^{tree}");             ObjectId branchId = repository.resolve(branchName + "^{tree}");              CanonicalTreeParser masterTreeParser = new CanonicalTreeParser();             masterTreeParser.reset(reader, masterId);              CanonicalTreeParser branchTreeParser = new CanonicalTreeParser();             branchTreeParser.reset(reader, branchId);              List<DiffEntry> diffs = git.diff()                     .setNewTree(branchTreeParser)                     .setOldTree(masterTreeParser)                     .call();              Map<String, List<String>> diffFileMap = new HashMap<>();             List<String> changeFileList = new ArrayList<>();             List<String> deleteFileList = new ArrayList<>();              df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);             df.setRepository(git.getRepository());              for (DiffEntry diffEntry : diffs) {                 df.format(diffEntry);                 FileHeader fileHeader = df.toFileHeader(diffEntry);                  @SuppressWarnings("unchecked")                 List<HunkHeader> hunks = (List<HunkHeader>) fileHeader.getHunks();                 int changedSize = 0;                 for (HunkHeader hunkHeader : hunks) {                     EditList editList = hunkHeader.toEditList();                     for (Edit edit : editList) {                         changedSize += edit.getEndA() - edit.getBeginA();                         changedSize += edit.getEndB() - edit.getBeginB();                     }                 }                  if (changedSize > 0) {                     ChangeType changeType = diffEntry.getChangeType();                     if (ChangeType.DELETE.equals(changeType)) {                         String oldFilePath = diffEntry.getOldPath();                         log.info("{}|{}", changeType.name(), oldFilePath);                         deleteFileList.add(oldFilePath);                     } else {                         String newFilePath = diffEntry.getNewPath();                         log.info("{}|{}", changeType.name(), newFilePath);                         changeFileList.add(newFilePath);                     }                 }             }             diffFileMap.put("change", changeFileList);             diffFileMap.put("delete", deleteFileList);              return diffFileMap;         }

    2、编译:

        Iterable<String> options = Arrays.asList(                 "-classpath", classpath,                 "-encoding", encoding,                 "-source", jdkVersion,                 "-target", jdkVersion,                 "-d", targetPath);          JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();         log.info("classpath:{}", classpath);         log.info("targetPath:{}", targetPath);          try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);) {              Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(fileList);              DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();              CompilationTask compilationTask = compiler                     .getTask(null, fileManager, diagnostics, options, null, compilationUnits);              if (!compilationTask.call()) {                 log.error("JavaCompiler Build failed:");                  for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {                     long line = diagnostic.getLineNumber();                     String source = diagnostic.getSource() != null ? diagnostic.getSource().toString() : "";                     String kind = diagnostic.getKind().name();                     String message = diagnostic.getMessage(null);                     log.info("{} on line:{} in {}.", kind, line, source);                     log.info("message:{}", message);                 }                 return false;             }         }

    要实现完整的功能,还需要根据应用的具体情况完善,比如:从运行环境同步删除代码库中删除的文件;从代码库拉取文件时,用fetch,reset的方式;还可以借助Marathon、Mesos、Docker运行应用等。

本文发表于2018年04月19日 22:38
(c)注:本文转载自https://my.oschina.net/u/2288883/blog/1797722,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2382 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

万稳万当,不如一默。任何一句话,你不说出来便是那句话的主人,你说了出来,便是那句话的奴隶。

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1