JRT编译实体

发布时间:2024年01月09日

设计器基本完成,就剩打磨了,今天换个口味,完成最后目标,JRT的框架申明的是业务脚本化,而写业务基本离不开实体类,实体类是经常改动的,所以实体的可维护性也很重要,需要给发布程序直接放实体代码,支持命令编译实体。

Windows下效果
在这里插入图片描述
Linux上效果
在这里插入图片描述

实现代码

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 编译JRT架构下的实体jar包,编译的实体工程文件和代码放在Web的CompileModel下面,驱动java -cp D:\JRTPlan\WebLoader\WebSrc\webapps\JRTWeb\CompileModel BuildModel JRT.Model来编译,
 * JRT.Model为实体的文件名称,将借助此工具实现JRT的业务脚本化目标部分的实体代码脚本化部分,在Web下的CompileModel放实体代码,需要改实体时候修改代码后运行jrt命令选8编译实体即可,
 * 实体的业务脚本化不采用自动编译的模式,和普通业务脚本的差别就是让人命令执行
 */
public class BuildModel {
    /**
     * 实体名称
     */
    private static String ModeDirName = "JRT.Model";

    /**
     * 实体编译入口
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
            //检查参数
            if (args == null || args.length == 0) {
                System.out.println("请传入实体文件夹名字");
                return;
            } else {
                ModeDirName = args[0];
            }
            System.out.println("开始编译实体...");
            //创建编译对象
            BuildModel bl = new BuildModel();
            //开始编译
            bl.BuildJava();
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
    }

    /**
     * 编译java代码
     *
     * @throws Exception
     */
    public void BuildJava() throws Exception {
        //得到.class所在的路径CompileModel
        String srcpath = this.getClass().getResource("").getPath();
        String curPath = new File(srcpath).toString();
        //上一级是Web的路径
        String webPath = new File(curPath).getParent();
        //编译成功了就生成这样的文件表示成功
        String successFilePath = Paths.get(curPath, "buildsuccess.jrt").toString();
        File successFile = new File(successFilePath);
        //删删除成功标志
        if (successFile.exists()) {
            successFile.delete();
        }
        //编译执行
        int retcode = BuildJavaDo(webPath, curPath);
        //编译成功
        if (retcode == 0) {
            successFile.createNewFile();
        }
        System.out.println("编译结束返回:" + retcode);
    }


    /**
     * 编译java执行
     *
     * @param webPath 网站路径
     * @param curPath 编译程序class所在路径
     * @return 返回0编译成功
     * @throws Exception
     */
    private int BuildJavaDo(String webPath, String curPath) throws Exception {
        File fiBase = new File(webPath);
        String parentPath = fiBase.getParent();
        //到webapps一级
        File fiParent = new File(parentPath);
        //到WebSrc一级
        File fiParent1 = new File(fiParent.getParent());
        //jar包存放路径
        String libPath = Paths.get(fiParent1.toString(), "lib").toString() + File.separator;
        System.out.println("jar包路径:" + libPath);
        String cmd = "javac -encoding UTF-8 -classpath ";
        //实体代码文件夹
        String modelPath = Paths.get(curPath, ModeDirName).toString();
        //实体代码工程文件
        String imlFile = Paths.get(modelPath, ModeDirName + ".iml").toString();
        //判断配置是否存在
        File iml = new File(imlFile);
        if (!iml.exists()) {
            System.out.println(imlFile + "文件不存在,请确认!");
            return -1;
        }
        //解析xml
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(iml);
        //获得根节点
        Element rootElement = document.getDocumentElement();
        //获得根节点下的所有子节点
        NodeList students = rootElement.getElementsByTagName("component");
        String classPath = "";
        String sp = ";";
        if (IsOSLinux()) {
            sp = ":";
        }
        //解析配置,得到依赖jar包
        for (int i = 0; i < students.getLength(); i++) {
            //由于节点多种类型,而一般我们需要处理的是元素节点
            Node childNode = students.item(i);
            //元素节点就是非空的子节点,也就是还有孩子的子节点
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) childNode;
                NodeList children = childElement.getChildNodes();
                for (int k = 0; k < children.getLength(); k++) {
                    Node child = children.item(k);
                    if (child.getNodeType() == Node.ELEMENT_NODE) {
                        childElement = (Element) child;
                        //不是对象配置元素就忽略
                        if (childElement.getNodeName() != "orderEntry") {
                            continue;
                        }
                        //解析得到包名
                        String name = childElement.getAttribute("name");
                        String type = childElement.getAttribute("type");
                        if (!type.equals("library")) {
                            continue;
                        }
                        String oneJarPath = Paths.get(libPath, name + ".jar").toString();
                        if (classPath == "") {
                            classPath = oneJarPath;
                        } else {
                            classPath += sp + oneJarPath;
                        }
                    }
                }
            }
        }
        //遍历目录下所有java文件,组装成路径串,英文,分割路径
        File modeldir = new File(modelPath);
        System.out.println("查找:" + modeldir + "下的.java文件");
        //遍历文件
        List<String> files = SeeFile(modeldir, ".java");
        int execode = -1;
        Runtime exe = Runtime.getRuntime();
        //循环遍历路径编译文件
        if (files.size() > 0) {
            System.out.println("找到:" + files.size() + "个.java文件");
            String pathstr = "";
            int count = 0;
            for (int i = 0; i < files.size(); i++) {
                String path = files.get(i);
                //空路径退出
                if (path.isEmpty()) {
                    continue;
                }
                if (pathstr.isEmpty()) {
                    pathstr = path;
                } else {
                    pathstr = pathstr + " " + path;
                }
                count++;
                //一次编译100个文件,太多文件导致串太长,编译报错
                if (((count) % 100 == 0) || ((i + 1) == files.size())) {
                    System.out.println("执行编译:" + i + 1);
                    String execcmd = cmd + classPath + " " + pathstr;
                    //执行编译命令
                    execode = Exec(exe, execcmd, webPath);
                    pathstr = "";
                    if (execode != 0) {
                        break;
                    }
                }
            }
            System.out.println("编译结束!");
        } else {
            execode = 0;
            System.out.println("找到:" + files.size() + "个.java文件");
            System.out.println("没有需要编译的.java文件");
        }
        //编译成功,打包编译的class文件为jar包
        if (execode == 0) {
            System.out.println("编译成功!");
            String modelpath = Paths.get(curPath, ModeDirName).toString();
            String jarFileStr = ModeDirName + ".jar";
            //临时目录
            Path tmppath = Paths.get(curPath, "ModelTmp");
            if (!tmppath.toFile().exists()) {
                Files.createDirectory(tmppath);
            }
            String[] modelArr = ModeDirName.split("\\.");
            Path tmpmodel = Paths.get(tmppath.toString(), modelArr[0], modelArr[1]);
            //没有的路径就创建
            if (!tmpmodel.toFile().exists()) {
                Files.createDirectories(tmpmodel);
            }
            //拷贝class文件到临时目录
            Files.walk(Paths.get(modelpath)).filter(Files::isRegularFile).forEach((Path var) -> {
                try {
                    File file = var.toFile();
                    String fileabpath = file.getAbsolutePath().replace(modelpath, tmpmodel.toString());
                    //不是.class的退出
                    if (!fileabpath.endsWith(".class")) {
                        return;
                    }
                    Path par = Paths.get(fileabpath).getParent();
                    //没路径的创建
                    if (!par.toFile().exists()) {
                        Files.createDirectories(par);
                    }
                    //把class文件复制到新的目录,方便打包
                    Files.copy(var, Paths.get(fileabpath), StandardCopyOption.REPLACE_EXISTING);
                } catch (Exception ex) {
                    ex.printStackTrace(System.out);
                }
            });
            System.out.println("打包:" + tmppath + "到:" + jarFileStr);
            cmd = "jar cf " + jarFileStr + " -C " + tmppath + " .";
            execode = Exec(exe, cmd, curPath);
            if (execode == 0) {
                System.out.println("打包完成!");
                //打包完成清除class文件,减少网站目录的文件数
                Files.walk(tmppath).filter(Files::isRegularFile).map(Path::toFile).forEach(File::deleteOnExit);
            }
        }
        return execode;
    }

    /**
     * 执行cmd命令
     *
     * @param exe
     * @param cmd
     * @param workdir
     * @return
     * @throws Exception
     */
    private int Exec(Runtime exe, String cmd, String workdir) throws Exception {
        if (workdir == null || workdir.isEmpty()) {
            workdir = ".";
        }
        System.out.println("执行:" + cmd);
        Process ps = exe.exec(cmd, null, Paths.get(workdir).toFile());
        // 获取命令行程序的输出结果
        StringBuilder retsb = new StringBuilder();
        //windows默认gb18030编码读取错误信息
        String charset = "gb18030";
        if (IsOSLinux()) {
            //linux用fut-8编码
            charset = "utf-8";
        }
        BufferedReader reader = new BufferedReader(new InputStreamReader(ps.getErrorStream(), charset));
        String line;
        while ((line = reader.readLine()) != null) {
            retsb.append(line);
        }
        int execode = ps.waitFor();
        ps.destroy();
        if (execode == 0) {
            System.out.println("执行成功!");
        } else {
            System.out.println("执行失败!");
            System.out.println(retsb);
        }
        return execode;
    }

    /**
     * 判断OS
     *
     * @return 得到是否是Linux
     */
    public static boolean IsOSLinux() {
        Properties prop = System.getProperties();
        String os = prop.getProperty("os.name");
        if (os != null && os.toLowerCase().indexOf("linux") > -1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 扫描文件
     *
     * @param dir
     * @param fileext
     * @return
     * @throws Exception
     */
    public static List<String> SeeFile(File dir, String fileext) throws Exception {
        ArrayList<String> list = new ArrayList<>();
        if (!dir.exists()) return list;
        if (dir.isFile()) {
            list.add(dir.getPath());
            return list;
        }
        Files.walk(dir.toPath()).filter(Files::isRegularFile).map(Path::toFile).forEach((File f) -> {
            String file = f.getPath();
            if (fileext != null && !fileext.isEmpty() && !file.toLowerCase().endsWith(fileext.toLowerCase())) {
                return;
            }
            if (fileext.equals(".java")) {
                String clspath = file.replace(".java", ".class");
                File clsfile = new File(clspath);
                if (clsfile.exists()) {
                    //java文件与之相应的class文件修改时间对比,class文件修改时间新就不编译
                    long clsmodtime = clsfile.lastModified();
                    long javamodtime = new File(file).lastModified();
                    if (clsmodtime > javamodtime) {
                        return;
                    }
                }
            }
            list.add(f.getPath());
        });
        return list;
    }
}

用cpp实现jrt命令
在这里插入图片描述

sh代码
在这里插入图片描述

投放目录
在这里插入图片描述

在这里插入图片描述

Linux下发布https,编译实体测试
在这里插入图片描述

这样除了打印设计器需要完善,各种难点全部解决,已经达到发布水平

文章来源:https://blog.csdn.net/zhanglianzhu_91/article/details/135486202
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。