从零构建可视化jar包部署平台JarManage

打印 上一主题 下一主题

主题 872|帖子 872|积分 2616

项目背景

在java项目部署过程中,由于内外部各种因素,可能会遇到一些感觉操作不便捷的场景,例如

  • jar包未随系统自动启动需要每次手动重启
  • 系统vpn堡垒机多重防御更新繁琐
  • 系统无图形化界面命令行操作复杂
  • 等等......
在工作中之前也总结了windows的Jar包部署工具linux下的jar包自动化部署脚本,这次就想着否能将二者统一结合,本着简单/高效/功能专一的原则,做出一
个可视化jar包部署平台,JarManage应运而生
功能介绍

项目地址:https://gitee.com/code2roc/jar-manage
支持在线创建项目,上传Jar包,自动备份,配置启动参数,注册系统服务,查看启动日志等功能,具有以下优点

  • 基于servlet开发,依赖简洁,部署包10MB左右
  • 结合嵌入式tomcat一键部署,无外部容器依赖
  • 使用h2db存储数据,无外部数据库依赖
  • 适配windows/linux平台,满足多种环境
  • 具体项目经平台部署后自动注册系统服务,无需担心服务器重启
系统架构图如下
系统截图展示


技术分析

平台识别

首先通过系统os识别是windows平台还是linux平台
  1. String os = System.getProperty("os.name").toLowerCase();
  2. if (os.startsWith("win")) {
  3.    platform = DepolyPlatform.Windows;
  4. }
复制代码
通过system-release文件识别部分基于CentOS开发的Linux系统
  1. String command = "cat /etc/system-release";
  2. String result = CMDUtil.executeLinuxCommand(command);
  3. if (result.startsWith("Red Hat")) {
  4.    platform = DepolyPlatform.LinuxRedHat;
  5. } else if (result.startsWith("CentOS")) {
  6.    platform = DepolyPlatform.LinuxCentOS;
  7. } else if (result.startsWith("openEuler")) {
  8.    platform = DepolyPlatform.LinuxOpenEuler;
  9. }
复制代码
通过issue文件识别部分基于Ubuntu/Debian开发的Linux系统
  1. command = "cat /etc/issue";
  2. result = CMDUtil.executeLinuxCommand(command);
  3. if (!StringUtil.isEmpty(result)) {
  4.   if (result.startsWith("Ubuntu")) {
  5.      platform = DepolyPlatform.LinuxUbuntu;
  6. } else if (result.startsWith("Debian")) {
  7.       platform = DepolyPlatform.LinuxDebian;
  8.    }
  9. }
复制代码
windows注册服务

通过sc query命令判断服务状态
  1.     public String getStatus(String serviceName) {
  2.         String status = DepolyStatus.UnInstall;
  3.         try {
  4.             String command = "sc query " + serviceName;
  5.             String commandResultFilePath = CMDUtil.executeWindowCommandStoreFile(command);
  6.             BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(commandResultFilePath)));
  7.             String line = reader.readLine();
  8.             while (line != null) {
  9.                 if (line.trim().startsWith("STATE")) {
  10.                     if (line.trim().substring(line.trim().indexOf(":") + 1, line.trim().indexOf(":") + 4).trim().equals("1"))
  11.                         status = DepolyStatus.Stopped;
  12.                     else if (line.trim().substring(line.trim().indexOf(":") + 1, line.trim().indexOf(":") + 4).trim().equals("2"))
  13.                         status = DepolyStatus.Startting;
  14.                     else if (line.trim().substring(line.trim().indexOf(":") + 1, line.trim().indexOf(":") + 4).trim().equals("3"))
  15.                         status = DepolyStatus.Stopping;
  16.                     else if (line.trim().substring(line.trim().indexOf(":") + 1, line.trim().indexOf(":") + 4).trim().equals("4"))
  17.                         status = DepolyStatus.Running;
  18.                 }
  19.                 line = reader.readLine();
  20.             }
  21.         } catch (IOException e) {
  22.             LogUtil.error(e);
  23.         }
  24.         return status;
  25.     }
复制代码
通过winsw这个开源项目配置exe和xml文件将jar包注册为windows服务,项目地址:https://github.com/winsw/winsw/
linux注册服务

通过systemctl status命令判断服务状态
  1.     public String getStatus(String serviceName) {
  2.         String status = DepolyStatus.UnInstall;
  3.         try {
  4.             String command = "systemctl status " + serviceName;
  5.             String commandResultFilePath = CMDUtil.executeLinuxCommandWithStore(command);
  6.             BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(commandResultFilePath)));
  7.             String line = reader.readLine();
  8.             while (line != null) {
  9.                 if (line.trim().startsWith("Active")) {
  10.                     if (line.trim().indexOf("inactive (dead)") > 0)
  11.                         status = DepolyStatus.Stopped;
  12.                     else if (line.trim().indexOf("active (running)") > 0)
  13.                         status = DepolyStatus.Running;
  14.                     else if (line.trim().indexOf("failed") > 0)
  15.                         status = DepolyStatus.Stopped;
  16.                 }
  17.                 line = reader.readLine();
  18.             }
  19.         } catch (IOException e) {
  20.             LogUtil.error(e);
  21.         }
  22.         return status;
  23.     }
复制代码
通过拷贝service文件到systemd/system目录下注册linux服务
yml配置文件识别


  • maven配置
  1.         <dependency>
  2.             <groupId>org.yaml</groupId>
  3.             <artifactId>snakeyaml</artifactId>
  4.             <version>1.26</version>
  5.         </dependency>
复制代码

  • 配置文件
  1. jarmanage:
  2.   port: 8555
  3.   username: admin
  4.   password: abcd@1234
  5.   backupcount: 5
复制代码

  • 工具类
  1.     public static String getConfigValue(String configName){
  2.         String configValue = "";
  3.         try{
  4.             Yaml yaml = new Yaml();
  5.             InputStream resourceAsStream = new FileInputStream(new File("resources"+File.separator+"application.yml"));
  6.             Map obj = yaml.load(resourceAsStream);
  7.             Map<String,Object> param = (Map) obj.get("jarmanage");
  8.             configValue = ConvertUtil.convert2String(param.get(configName));
  9.         }catch (Exception e){
  10.             LogUtil.error(e);
  11.         }
  12.         return configValue;
  13.     }
复制代码
h2database使用


  • maven引用
  1.         <dependency>
  2.             <groupId>com.h2database</groupId>
  3.             <artifactId>h2</artifactId>
  4.             <version>2.1.214</version>
  5.         </dependency>
复制代码

  • 工具类
  1.     public static Connection getConnection() throws Exception {
  2.         File file = new File("database");
  3.         Connection conn = DriverManager.getConnection("jdbc:h2:file:" + file.getAbsolutePath() + File.separator + "manage", "root", "abcd@1234");
  4.         return conn;
  5.     }
  6.    
  7.     public static void executeSQL(String sql) {
  8.         try {
  9.             Connection conn = getConnection();
  10.             Statement stmt = conn.createStatement();
  11.             stmt.execute(sql);
  12.             stmt.close();
  13.             conn.close();
  14.         } catch (Exception e) {
  15.             LogUtil.error(e);
  16.         }
  17.     }
复制代码
servelt内置tomcat打包


  • maven引用
  1.         <dependency>
  2.             <groupId>org.apache.tomcat.embed</groupId>
  3.             <artifactId>tomcat-embed-core</artifactId>
  4.             <version>9.0.35</version>
  5.         </dependency>
  6.         <dependency>
  7.             <groupId>org.apache.tomcat.embed</groupId>
  8.             <artifactId>tomcat-embed-el</artifactId>
  9.             <version>9.0.35</version>
  10.         </dependency>
  11.         <dependency>
  12.             <groupId>org.apache.tomcat.embed</groupId>
  13.             <artifactId>tomcat-embed-jasper</artifactId>
  14.             <version>9.0.35</version>
  15.         </dependency>
复制代码

  • 手动启动
  1.             //启动tomcat服务
  2.             // 1.创建一个内嵌的Tomcat
  3.             Tomcat tomcat = new Tomcat();
  4.             // 2.设置Tomcat端口
  5.             tomcat.setPort(8555);
  6.             // 3.设置工作目录,tomcat需要使用这个目录进行写一些东西
  7.             final String baseDir = "workspace" + File.separator;
  8.             tomcat.setBaseDir(baseDir);
  9.             tomcat.getHost().setAutoDeploy(false);
  10.             // 4. 设置webapp资源路径
  11.             String webappDirLocation = "webapp" + File.separator;
  12.             StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
  13.             // 5. 设置上下文路每径
  14.             String contextPath = "";
  15.             ctx.setPath(contextPath);
  16.             ctx.addLifecycleListener(new Tomcat.FixContextListener());
  17.             ctx.setName("jar-manage");
  18.             tomcat.getHost().addChild(ctx);
  19.             //6.启动
  20.             tomcat.getConnector();
  21.             tomcat.start();
  22.             tomcat.getServer().await();
复制代码

  • 打包包含引用类库,自定义配置xml,指定运行class
  1.         <plugins>
  2.             <plugin>
  3.                
  4.                 <artifactId>maven-assembly-plugin</artifactId>
  5.                 <configuration>
  6.                     <descriptors>
  7.                         
  8.                         <descriptor>package.xml</descriptor>
  9.                     </descriptors>
  10.                     <archive>
  11.                         <manifest>
  12.                            
  13.                             <mainClass>com.code2roc.jarmanage.Application</mainClass>
  14.                         </manifest>
  15.                     </archive>
  16.                 </configuration>
  17.                 <executions>
  18.                     <execution>
  19.                         <id>make-assembly</id>
  20.                         <phase>package</phase>
  21.                         <goals>
  22.                             <goal>single</goal>
  23.                         </goals>
  24.                     </execution>
  25.                 </executions>
  26.             </plugin>
  27.             <plugin>
  28.                 <groupId>org.apache.maven.plugins</groupId>
  29.                 <artifactId>maven-compiler-plugin</artifactId>
  30.                 <configuration>
  31.                     <source>8</source>
  32.                     <target>8</target>
  33.                 </configuration>
  34.             </plugin>
  35.         </plugins>
复制代码
  1. <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1"
  2.           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.           xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 https://maven.apache.org/xsd/assembly-2.1.1.xsd">
  4.    
  5.     <id>depoly</id>
  6.     <formats>
  7.         <format>jar</format>
  8.     </formats>
  9.     <includeBaseDirectory>false</includeBaseDirectory>
  10.     <dependencySets>
  11.         <dependencySet>
  12.             <outputDirectory>/</outputDirectory>
  13.             <useProjectArtifact>true</useProjectArtifact>
  14.             <unpack>true</unpack>
  15.             <scope>runtime</scope>
  16.         </dependencySet>
  17.     </dependencySets>
  18.     <fileSets>
  19.         <fileSet>
  20.             <directory>src/main/webapp/</directory>
  21.             <outputDirectory>/webapp</outputDirectory>
  22.             <includes>
  23.                 <include>**/**</include>
  24.             </includes>
  25.         </fileSet>
  26.         <fileSet>
  27.             <directory>src/main/resources/</directory>
  28.             <outputDirectory>/resources</outputDirectory>
  29.             <includes>
  30.                 <include>**/**</include>
  31.             </includes>
  32.         </fileSet>
  33.     </fileSets>
  34. </assembly>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表