如何比较同一个项目中不同版本的区别

在项目研发的过程中,我们往往会同时写多个版本的情况,而如果我们在低版本bug的同时新版本可能也存在这个bug,那么,一般解决方案有两个,要么是将最新的代码实时与新版本同步,要么是在新版本要上线的时候对新老版本的bug进行对比。理论上讲,第一种方案相对来说,出错的概率要小一些。所以下面我来介绍一下对于第二种方案的思路。

主体思路

首先,我们要知道,比较两个项目的异同一般是指的对两个版本的异同点进行比较,两个完全不同的项目是没有必要比较异同的。那么比较这个系统的两个不同版本主要关心的点有哪些呢?

1、新版本相对于旧版本少的文件:这很有可能是旧版本为了满足一定的需求而创建的,而这个需求在新版本中也有。
2、相同代码文件中代码的不同之处。

新版本相较于旧版本多出来的文件我们是不需要考虑的。

针对上面两个关注点,可以采取以下两种方案

GIT比较法

git 追踪到文件,就可以很好的满足到上面提到的两种情况。
假设我们的两个版本为1.0和2.0,首先,创建一个1.0项目的副本目录(包含git文件夹),同时也创建一个2.0项目的副本目录(包含git文件夹),然后将1.0副本代码替换为2.0副本代码,然后利用可视化提交界面,一个个的进行区别查看,然后根据现有的逻辑进行补充。
逻辑如图所示:
在这里插入图片描述

当我们使用Git进行异同点检查的时候,可能遇到的指令有 git revert(撤销历史提交),因为对于1.0的git来说,1,.0中新增的文件,对于2.0的代码进行检查显示的就是该文件被删除了,所以我们需要对删除的文件的删除行为进行撤销。

查看思路:

1、unknown的东西就不管,因为这是最新版多的东西
2、miss的东西可能是缺少的,也可能是修改的,所以这里不能盲目git revert。
3、modifined是变化的,如果是变少了:本质上就是1.0修复时加上去的,所以要考虑加到2.0中

注意事项:

1、确保两个版本的代码都是最新的(1.0和2.0)
2、一定不要点确认提交,毕竟我们只是使用git的比较机制
3、看准比较的究竟那边是本地当前的和以前的,这里我推荐使用可视化工具
4、修改的过程中可能会有改错的情况,所以在改完之后要启动所有项目试一下。

Java静态代码分析法

该方法目前只做到了能比较两个java项目的相似度,目前对自动化变更代码尚有技术的不可预知性。

分析Java代码

首先,定义出一个Java代码的项目结构对应的简单对象。

给出Java项目结构所需简单对象

pom

public class Pom {
    public String schemaLocation; // http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
    public String modelVersion; // 4.0.0
    public String groupId; // org.ccs.nss
    public String artifactId; // nss-boot-parent
    public String version; // 1.0
    public String packaging; // pom
    public PomParent parent; // {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, version=2.3.3.RELEASE, relativePath=}
    public PomRepositories repositories; // {repository=[{id=central, name=aliyun Repository, url=https://maven.aliyun.com/repository/central, snapshots={enabled=false}}, {id=jeecg, name=jeecg Repository, url=http://maven.jeecg.org/nexus/content/repositories/jeecg, snapshots={enabled=false}}]}
    public PomPluginrepositories pluginRepositories; // {pluginRepository=[{id=central, url=https://maven.aliyun.com/repository/central}, {id=jeecg, url=http://maven.jeecg.org/nexus/content/repositories/jeecg}]}
    public PomModules modules; // {module=[base-common, module-system]}
    public PomProperties properties; // {log4j2.version=2.17.1, maven-jar-plugin.version=3.1.1, nss.common.version=1.0, java.version=1.8, project.reporting.outputEncoding=UTF-8, project.build.sourceEncoding=UTF-8, mybatis-plus.version=3.1.2, druid.version=1.1.17, jwt.version=0.9.1, commons.version=2.6, aliyun-java-sdk-core.version=3.2.3, aliyun-java-sdk-dysmsapi.version=1.0.0}
    public PomDependencies dependencies; // {dependency=[{groupId=org.springframework.boot, artifactId=spring-boot-starter-web}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-mail}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-test, scope=test}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-aop}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-actuator}, {groupId=org.apache.cxf, artifactId=cxf-spring-boot-starter-jaxws, version=3.2.4}, {groupId=commons-io, artifactId=commons-io, version=${commons.version}}, {groupId=commons-lang, artifactId=commons-lang, version=${commons.version}}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-freemarker}, {groupId=org.projectlombok, artifactId=lombok}, {groupId=com.baomidou, artifactId=mybatis-plus-boot-starter, version=${mybatis-plus.version}}, {groupId=com.alibaba, artifactId=druid-spring-boot-starter, version=${druid.version}}, {groupId=com.baomidou, artifactId=dynamic-datasource-spring-boot-starter, version=2.5.4}, {groupId=com.alibaba, artifactId=fastjson, version=1.2.73}, {groupId=mysql, artifactId=mysql-connector-java, version=5.1.47, scope=runtime}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-quartz}, {groupId=com.auth0, artifactId=java-jwt, version=3.7.0}, {groupId=org.apache.shiro, artifactId=shiro-spring-boot-starter, version=1.6.0}, {groupId=io.springfox, artifactId=springfox-swagger2, version=2.9.2}, {groupId=io.springfox, artifactId=springfox-swagger-ui, version=2.9.2}, {groupId=com.github.xiaoymin, artifactId=swagger-bootstrap-ui, version=1.9.3}, {groupId=io.springfox, artifactId=springfox-bean-validators, version=2.9.2}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-data-redis}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-data-ldap}, {groupId=org.apache.commons, artifactId=commons-pool2}, {groupId=com.github.tobato, artifactId=fastdfs-client, version=1.26.7}, {groupId=org.jeecgframework.boot, artifactId=codegenerate, version=1.0.5}, {groupId=org.jeecgframework, artifactId=autopoi-web, version=1.1.1, exclusions={exclusion={groupId=commons-codec, artifactId=commons-codec}}}, {groupId=cn.hutool, artifactId=hutool-all, version=4.5.11}, {groupId=com.thoughtworks.xstream, artifactId=xstream, version=1.3.1}, {groupId=com.aliyun, artifactId=aliyun-java-sdk-dysmsapi, version=${aliyun-java-sdk-dysmsapi.version}}, {groupId=com.aliyun, artifactId=aliyun-java-sdk-core, version=${aliyun-java-sdk-core.version}}, {groupId=com.github.penggle, artifactId=kaptcha, version=2.3.2}, {groupId=com.itextpdf, artifactId=itextpdf, version=5.5.13}, {groupId=org.bouncycastle, artifactId=bcprov-jdk15on, version=1.49}, {groupId=com.itextpdf, artifactId=itext-asian, version=5.2.0}, {groupId=commons-net, artifactId=commons-net, version=3.6}, {groupId=com.jcraft, artifactId=jsch, version=0.1.55}]}
    public PomDependencymanagement dependencyManagement; // {dependencies={dependency={groupId=org.ccs.nss, artifactId=base-common, version=${nss.common.version}}}}
    public PomBuild build; // {plugins={plugin=[{groupId=org.apache.maven.plugins, artifactId=maven-compiler-plugin, configuration={source=1.8, target=1.8, encoding=UTF-8}}, {groupId=org.apache.maven.plugins, artifactId=maven-surefire-plugin, configuration={skipTests=true}}, {groupId=org.apache.maven.plugins, artifactId=maven-resources-plugin, configuration={nonFilteredFileExtensions={nonFilteredFileExtension=[woff, woff2, eot, ttf, svg, xlsx, xls]}}}]}, resources={resource=[{directory=src/main/resources, filtering=true}, {directory=src/main/java, includes={include=[**/*.xml, **/*.json, **/*.ftl]}}]}}
}
public class PomParent {
    public String groupId; // org.springframework.boot
    public String artifactId; // spring-boot-starter-parent
    public String version; // 2.3.3.RELEASE
    public String relativePath; // 
}
public class PomRepositories {
    public List<PomRepositoriesRepository> repository; // [{id=central, name=aliyun Repository, url=https://maven.aliyun.com/repository/central, snapshots={enabled=false}}, {id=jeecg, name=jeecg Repository, url=http://maven.jeecg.org/nexus/content/repositories/jeecg, snapshots={enabled=false}}]
}
public class PomPluginrepositories {
    public List<PomPluginrepositoriesPluginrepository> pluginRepository; // [{id=central, url=https://maven.aliyun.com/repository/central}, {id=jeecg, url=http://maven.jeecg.org/nexus/content/repositories/jeecg}]
}
public class PomModules {
	public List<String> module; // [base-common, module-system]
}
public class PomProperties {
    public String log4j2Version; // 2.17.1
    public String mavenJarPluginVersion; // 3.1.1
    public String nssCommonVersion; // 1.0
    public String javaVersion; // 1.8
    public String projectReportingOutputEncoding; // UTF-8
    public String projectBuildSourceEncoding; // UTF-8
    public String mybatisPlusVersion; // 3.1.2
    public String druidVersion; // 1.1.17
    public String jwtVersion; // 0.9.1
    public String commonsVersion; // 2.6
    public String aliyunJavaSdkCoreVersion; // 3.2.3
    public String aliyunJavaSdkDysmsapiVersion; // 1.0.0
}
public class PomDependencies {
    public List<PomDependenciesDependency> dependency; // [{groupId=org.springframework.boot, artifactId=spring-boot-starter-web}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-mail}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-test, scope=test}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-aop}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-actuator}, {groupId=org.apache.cxf, artifactId=cxf-spring-boot-starter-jaxws, version=3.2.4}, {groupId=commons-io, artifactId=commons-io, version=${commons.version}}, {groupId=commons-lang, artifactId=commons-lang, version=${commons.version}}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-freemarker}, {groupId=org.projectlombok, artifactId=lombok}, {groupId=com.baomidou, artifactId=mybatis-plus-boot-starter, version=${mybatis-plus.version}}, {groupId=com.alibaba, artifactId=druid-spring-boot-starter, version=${druid.version}}, {groupId=com.baomidou, artifactId=dynamic-datasource-spring-boot-starter, version=2.5.4}, {groupId=com.alibaba, artifactId=fastjson, version=1.2.73}, {groupId=mysql, artifactId=mysql-connector-java, version=5.1.47, scope=runtime}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-quartz}, {groupId=com.auth0, artifactId=java-jwt, version=3.7.0}, {groupId=org.apache.shiro, artifactId=shiro-spring-boot-starter, version=1.6.0}, {groupId=io.springfox, artifactId=springfox-swagger2, version=2.9.2}, {groupId=io.springfox, artifactId=springfox-swagger-ui, version=2.9.2}, {groupId=com.github.xiaoymin, artifactId=swagger-bootstrap-ui, version=1.9.3}, {groupId=io.springfox, artifactId=springfox-bean-validators, version=2.9.2}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-data-redis}, {groupId=org.springframework.boot, artifactId=spring-boot-starter-data-ldap}, {groupId=org.apache.commons, artifactId=commons-pool2}, {groupId=com.github.tobato, artifactId=fastdfs-client, version=1.26.7}, {groupId=org.jeecgframework.boot, artifactId=codegenerate, version=1.0.5}, {groupId=org.jeecgframework, artifactId=autopoi-web, version=1.1.1, exclusions={exclusion={groupId=commons-codec, artifactId=commons-codec}}}, {groupId=cn.hutool, artifactId=hutool-all, version=4.5.11}, {groupId=com.thoughtworks.xstream, artifactId=xstream, version=1.3.1}, {groupId=com.aliyun, artifactId=aliyun-java-sdk-dysmsapi, version=${aliyun-java-sdk-dysmsapi.version}}, {groupId=com.aliyun, artifactId=aliyun-java-sdk-core, version=${aliyun-java-sdk-core.version}}, {groupId=com.github.penggle, artifactId=kaptcha, version=2.3.2}, {groupId=com.itextpdf, artifactId=itextpdf, version=5.5.13}, {groupId=org.bouncycastle, artifactId=bcprov-jdk15on, version=1.49}, {groupId=com.itextpdf, artifactId=itext-asian, version=5.2.0}, {groupId=commons-net, artifactId=commons-net, version=3.6}, {groupId=com.jcraft, artifactId=jsch, version=0.1.55}]
}
public class PomDependencymanagement {
    public PomDependencymanagementDependencies dependencies; // {dependency={groupId=org.ccs.nss, artifactId=base-common, version=${nss.common.version}}}
}
public class PomBuild {
    public PomBuildPlugins plugins; // {plugin=[{groupId=org.apache.maven.plugins, artifactId=maven-compiler-plugin, configuration={source=1.8, target=1.8, encoding=UTF-8}}, {groupId=org.apache.maven.plugins, artifactId=maven-surefire-plugin, configuration={skipTests=true}}, {groupId=org.apache.maven.plugins, artifactId=maven-resources-plugin, configuration={nonFilteredFileExtensions={nonFilteredFileExtension=[woff, woff2, eot, ttf, svg, xlsx, xls]}}}]}
    public PomBuildResources resources; // {resource=[{directory=src/main/resources, filtering=true}, {directory=src/main/java, includes={include=[**/*.xml, **/*.json, **/*.ftl]}}]}
}
... ...

javacontroller

public class JavaController {
    private String absolutePath;
    private String name;
    private List<String> methodZhuShi;
    private List<String> allZhuShi;
    private List<JavaHttpApi> apis;

    public JavaController() {
        this.methodZhuShi = new ArrayList<>();
        this.allZhuShi = new ArrayList<>();
        this.apis = new ArrayList<>();
    }

    public List<JavaHttpApi> getApis() {
        return apis;
    }

    public void setApis(List<JavaHttpApi> apis) {
        this.apis = apis;
    }

    public List<String> getAllZhuShi() {
        return allZhuShi;
    }

    public void setAllZhuShi(List<String> allZhuShi) {
        this.allZhuShi = allZhuShi;
    }

    public List<String> getMethodZhuShi() {
        return methodZhuShi;
    }

    public void setMethodZhuShi(List<String> methodZhuShi) {
        this.methodZhuShi = methodZhuShi;
    }

    public String getAbsolutePath() {
        return absolutePath;
    }

    public void setAbsolutePath(String absolutePath) {
        this.absolutePath = absolutePath;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

javahttpApi

public class JavaHttpApi {
    private String belongController;
    private String method;
    private String url;
    private String paramStr;
    private String name;
    private Map<String,Object> paramJsons;

    public Map<String, Object> getParamJsons() {
        return paramJsons;
    }

    public void setParamJsons(Map<String, Object> paramJsons) {
        this.paramJsons = paramJsons;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBelongController() {
        return belongController;
    }

    public void setBelongController(String belongController) {
        this.belongController = belongController;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getParamStr() {
        return paramStr;
    }

    public void setParamStr(String paramStr) {
        this.paramStr = paramStr;
    }
}

javaClass

public class JavaClass {
    private String absolutePath;
    private String name;
    private List<String> allZhuShi = new ArrayList<>();
    private Set<String> allAnaotion = new HashSet<>();
    private Map<String,Object> fields = new HashMap<>();

    public Map<String, Object> getFields() {
        return fields;
    }

    public void setFields(Map<String, Object> fields) {
        this.fields = fields;
    }

    public Set<String> getAllAnaotion() {
        return allAnaotion;
    }

    public void setAllAnaotion(Set<String> allAnaotion) {
        this.allAnaotion = allAnaotion;
    }

    public String getAbsolutePath() {
        return absolutePath;
    }

    public void setAbsolutePath(String absolutePath) {
        this.absolutePath = absolutePath;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getAllZhuShi() {
        return allZhuShi;
    }

    public void setAllZhuShi(List<String> allZhuShi) {
        this.allZhuShi = allZhuShi;
    }
}
将pom文件反序列化为对象
public static List<Pom> getPomContent(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> pomPaths = FolderUtils.getAbsolutePathOfDirNameByCondition(dir, "pom.xml");
        List<Pom> poms = new ArrayList<>();
        for (String pomPath : pomPaths) {
            String content = FileUtils.getFileContent(pomPath, false);
            ObjectMapper xmlMapper = new XmlMapper();
            try {
                Pom pom = PomExchange.exchangePom(xmlMapper.readValue(content, Map.class));
                poms.add(pom);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return poms;
    }

下面是exchange方法

import cn.chaojilaji.auto.zlang.codereview.javahandler.pomHandler.data.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PomExchange {
    public static Pom exchangePom(Map<String, Object> tmp) {
        Pom tmpDto = new Pom();
        tmpDto.schemaLocation = (String) tmp.getOrDefault("schemaLocation", "");
        tmpDto.modelVersion = (String) tmp.getOrDefault("modelVersion", "");
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        tmpDto.version = (String) tmp.getOrDefault("version", "");
        tmpDto.packaging = (String) tmp.getOrDefault("packaging", "");
        tmpDto.parent = exchangePomParent((Map<String, Object>) tmp.getOrDefault("parent", new HashMap<>()));
        tmpDto.repositories = exchangePomRepositories((Map<String, Object>) tmp.getOrDefault("repositories", new HashMap<>()));
        tmpDto.pluginRepositories = exchangePomPluginrepositories((Map<String, Object>) tmp.getOrDefault("pluginRepositories", new HashMap<>()));
        tmpDto.modules = exchangePomModules((Map<String, Object>) tmp.getOrDefault("modules", new HashMap<>()));
        tmpDto.properties = exchangePomProperties((Map<String, Object>) tmp.getOrDefault("properties", new HashMap<>()));
        tmpDto.dependencies = exchangePomDependencies((Map<String, Object>) tmp.getOrDefault("dependencies", new HashMap<>()));
        tmpDto.dependencyManagement = exchangePomDependencyManagement((Map<String, Object>) tmp.getOrDefault("dependencyManagement", new HashMap<>()));
        tmpDto.build = exchangePomBuild((Map<String, Object>) tmp.getOrDefault("build", new HashMap<>()));
        return tmpDto;
    }

    public static PomParent exchangePomParent(Map<String, Object> tmp) {
        PomParent tmpDto = new PomParent();
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        tmpDto.version = (String) tmp.getOrDefault("version", "");
        tmpDto.relativePath = (String) tmp.getOrDefault("relativePath", "");
        return tmpDto;
    }

    public static PomRepositories exchangePomRepositories(Map<String, Object> tmp) {
        PomRepositories tmpDto = new PomRepositories();
        try {
            tmpDto.repository = new ArrayList<>();
            List<Map<String, Object>> tmpRepository = (List<Map<String, Object>>) tmp.getOrDefault("repository", new ArrayList<>());
            for (Map<String, Object> a : tmpRepository) {
                tmpDto.repository.add(exchangePomRepositoriesRepository(a));
            }
        } catch (Exception e) {
        }

        return tmpDto;
    }

    public static PomRepositoriesRepository exchangePomRepositoriesRepository(Map<String, Object> tmp) {
        PomRepositoriesRepository tmpDto = new PomRepositoriesRepository();
        tmpDto.snapshots = exchangePomRepositoriesRepositorySnapshots((Map<String, Object>) tmp.getOrDefault("snapshots", new HashMap<>()));
        tmpDto.name = (String) tmp.getOrDefault("name", "");
        tmpDto.id = (String) tmp.getOrDefault("id", "");
        tmpDto.url = (String) tmp.getOrDefault("url", "");
        return tmpDto;
    }

    public static PomRepositoriesRepositorySnapshots exchangePomRepositoriesRepositorySnapshots(Map<String, Object> tmp) {
        PomRepositoriesRepositorySnapshots tmpDto = new PomRepositoriesRepositorySnapshots();
        tmpDto.enabled = (String) tmp.getOrDefault("enabled", "");
        return tmpDto;
    }

    public static PomPluginrepositories exchangePomPluginrepositories(Map<String, Object> tmp) {
        PomPluginrepositories tmpDto = new PomPluginrepositories();
        try {
            tmpDto.pluginRepository = new ArrayList<>();
            List<Map<String, Object>> tmpPluginRepository = (List<Map<String, Object>>) tmp.getOrDefault("pluginRepository", new ArrayList<>());
            for (Map<String, Object> a : tmpPluginRepository) {
                tmpDto.pluginRepository.add(exchangePomPluginrepositoriesPluginrepository(a));
            }
        } catch (Exception e) {
        }

        return tmpDto;
    }

    public static PomPluginrepositoriesPluginrepository exchangePomPluginrepositoriesPluginrepository(Map<String, Object> tmp) {
        PomPluginrepositoriesPluginrepository tmpDto = new PomPluginrepositoriesPluginrepository();
        tmpDto.id = (String) tmp.getOrDefault("id", "");
        tmpDto.url = (String) tmp.getOrDefault("url", "");
        return tmpDto;
    }

    public static PomModules exchangePomModules(Map<String, Object> tmp) {
        PomModules tmpDto = new PomModules();
        tmpDto.module = (List<String>) tmp.getOrDefault("module", new ArrayList<>());
        return tmpDto;
    }

    public static PomProperties exchangePomProperties(Map<String, Object> tmp) {
        PomProperties tmpDto = new PomProperties();
        tmpDto.log4j2Version = (String) tmp.getOrDefault("log4j2.version", "");
        tmpDto.mavenJarPluginVersion = (String) tmp.getOrDefault("maven-jar-plugin.version", "");
        tmpDto.nssCommonVersion = (String) tmp.getOrDefault("nss.common.version", "");
        tmpDto.javaVersion= (String) tmp.getOrDefault("java.version", "");
        tmpDto.projectReportingOutputEncoding = (String) tmp.getOrDefault("project.reporting.outputEncoding", "");
        tmpDto.projectBuildSourceEncoding = (String) tmp.getOrDefault("project.build.sourceEncoding", "");
        tmpDto.mybatisPlusVersion = (String) tmp.getOrDefault("mybatis-plus.version", "");
        tmpDto.druidVersion = (String) tmp.getOrDefault("druid.version", "");
        tmpDto.jwtVersion = (String) tmp.getOrDefault("jwt.version", "");
        tmpDto.commonsVersion = (String) tmp.getOrDefault("commons.version", "");
        tmpDto.aliyunJavaSdkCoreVersion = (String) tmp.getOrDefault("aliyun-java-sdk-core.version", "");
        tmpDto.aliyunJavaSdkDysmsapiVersion = (String) tmp.getOrDefault("aliyun-java-sdk-dysmsapi.version", "");
        return tmpDto;
    }

    public static PomDependencies exchangePomDependencies(Map<String, Object> tmp) {
        PomDependencies tmpDto = new PomDependencies();
        try {
            tmpDto.dependency = new ArrayList<>();
            List<Map<String, Object>> tmpDependency = (List<Map<String, Object>>) tmp.getOrDefault("dependency", new ArrayList<>());
            for (Map<String, Object> a : tmpDependency) {
                tmpDto.dependency.add(exchangePomDependenciesDependency(a));
            }
        } catch (Exception e) {
        }

        return tmpDto;
    }

    public static PomDependenciesDependency exchangePomDependenciesDependency(Map<String, Object> tmp) {
        PomDependenciesDependency tmpDto = new PomDependenciesDependency();
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.scope = (String) tmp.getOrDefault("scope", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        tmpDto.exclusions = exchangePomDependenciesDependencyExclusions((Map<String, Object>) tmp.getOrDefault("exclusions", new HashMap<>()));
        tmpDto.version = (String) tmp.getOrDefault("version", "");
        return tmpDto;
    }

    public static PomDependenciesDependencyExclusions exchangePomDependenciesDependencyExclusions(Map<String, Object> tmp) {
        PomDependenciesDependencyExclusions tmpDto = new PomDependenciesDependencyExclusions();
        tmpDto.exclusion = exchangePomDependenciesDependencyExclusionsExclusion((Map<String, Object>) tmp.getOrDefault("exclusion", new HashMap<>()));
        return tmpDto;
    }

    public static PomDependenciesDependencyExclusionsExclusion exchangePomDependenciesDependencyExclusionsExclusion(Map<String, Object> tmp) {
        PomDependenciesDependencyExclusionsExclusion tmpDto = new PomDependenciesDependencyExclusionsExclusion();
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        return tmpDto;
    }

    public static PomDependencymanagement exchangePomDependencyManagement(Map<String, Object> tmp) {
        PomDependencymanagement tmpDto = new PomDependencymanagement();
        tmpDto.dependencies = exchangePomDependencymanagementDependencies((Map<String, Object>) tmp.getOrDefault("dependencies", new HashMap<>()));
        return tmpDto;
    }

    public static PomDependencymanagementDependencies exchangePomDependencymanagementDependencies(Map<String, Object> tmp) {
        PomDependencymanagementDependencies tmpDto = new PomDependencymanagementDependencies();
        try {
            tmpDto.dependency = exchangePomDependencymanagementDependenciesDependency((Map<String, Object>) tmp.getOrDefault("dependency", new HashMap<>()));
        }catch (Exception e){
            e.printStackTrace();
        }
        return tmpDto;
    }

    public static PomDependencymanagementDependenciesDependency exchangePomDependencymanagementDependenciesDependency(Map<String, Object> tmp) {
        PomDependencymanagementDependenciesDependency tmpDto = new PomDependencymanagementDependenciesDependency();
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        tmpDto.version = (String) tmp.getOrDefault("version", "");
        return tmpDto;
    }

    public static PomBuild exchangePomBuild(Map<String, Object> tmp) {
        PomBuild tmpDto = new PomBuild();
        tmpDto.plugins = exchangePomBuildPlugins((Map<String, Object>) tmp.getOrDefault("plugins", new HashMap<>()));
        tmpDto.resources = exchangePomBuildResources((Map<String, Object>) tmp.getOrDefault("resources", new HashMap<>()));
        return tmpDto;
    }

    public static PomBuildPlugins exchangePomBuildPlugins(Map<String, Object> tmp) {
        PomBuildPlugins tmpDto = new PomBuildPlugins();
        try {
            tmpDto.plugin = new ArrayList<>();
            List<Map<String, Object>> tmpPlugin = (List<Map<String, Object>>) tmp.getOrDefault("plugin", new ArrayList<>());
            for (Map<String, Object> a : tmpPlugin) {
                tmpDto.plugin.add(exchangePomBuildPluginsPlugin(a));
            }
        } catch (Exception e) {
        }

        return tmpDto;
    }

    public static PomBuildPluginsPlugin exchangePomBuildPluginsPlugin(Map<String, Object> tmp) {
        PomBuildPluginsPlugin tmpDto = new PomBuildPluginsPlugin();
        tmpDto.configuration = exchangePomBuildPluginsPluginConfiguration((Map<String, Object>) tmp.getOrDefault("configuration", new HashMap<>()));
        tmpDto.groupId = (String) tmp.getOrDefault("groupId", "");
        tmpDto.artifactId = (String) tmp.getOrDefault("artifactId", "");
        return tmpDto;
    }

    public static PomBuildPluginsPluginConfiguration exchangePomBuildPluginsPluginConfiguration(Map<String, Object> tmp) {
        PomBuildPluginsPluginConfiguration tmpDto = new PomBuildPluginsPluginConfiguration();
        tmpDto.source = (String) tmp.getOrDefault("source", "");
        tmpDto.target = (String) tmp.getOrDefault("target", "");
        tmpDto.encoding = (String) tmp.getOrDefault("encoding", "");
        return tmpDto;
    }

    public static PomBuildResources exchangePomBuildResources(Map<String, Object> tmp) {
        PomBuildResources tmpDto = new PomBuildResources();
        try {
            tmpDto.resource = new ArrayList<>();
            List<Map<String, Object>> tmpResource = (List<Map<String, Object>>) tmp.getOrDefault("resource", new ArrayList<>());
            for (Map<String, Object> a : tmpResource) {
                tmpDto.resource.add(exchangePomBuildResourcesResource(a));
            }
        } catch (Exception e) {
        }

        return tmpDto;
    }

    public static PomBuildResourcesResource exchangePomBuildResourcesResource(Map<String, Object> tmp) {
        PomBuildResourcesResource tmpDto = new PomBuildResourcesResource();
        tmpDto.includes = exchangePomBuildResourcesResourceIncludes((Map<String, Object>) tmp.getOrDefault("includes", new HashMap<>()));
        tmpDto.directory = (String) tmp.getOrDefault("directory", "");
        tmpDto.filtering = (String) tmp.getOrDefault("filtering", "");
        return tmpDto;
    }

    public static PomBuildResourcesResourceIncludes exchangePomBuildResourcesResourceIncludes(Map<String, Object> tmp) {
        PomBuildResourcesResourceIncludes tmpDto = new PomBuildResourcesResourceIncludes();
        tmpDto.include = (List<String>) tmp.getOrDefault("include", new ArrayList<>());
        return tmpDto;
    }
}

解析所有的Controller
public static List<JavaController> getAllController(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> controllerPaths = FolderUtils.getAbsolutePathOfDirContentByCondition(dir, "@Controller");
        controllerPaths.addAll(FolderUtils.getAbsolutePathOfDirContentByCondition(dir, "@RestController"));
        Collections.sort(controllerPaths);
        List<JavaController> ans = new ArrayList<>();
        Pattern pattern = Pattern.compile(PatternEnum.CLASS_TITLE.getRegexp());
        Pattern zhuShiPattern = Pattern.compile(PatternEnum.CONTROLLER_FUNC_ZHUSHI.getRegexp());
        Set<String> controllerSet = new HashSet<>();
        for (String path : controllerPaths) {
            String content = FileUtils.getFileContent(path, false);
            // TODO: 2022/5/18 寻找controller的类标头
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                String xx = matcher.group("name").trim();
                if (controllerSet.contains(xx)) {
                    continue;
                }
                controllerSet.add(xx);
                JavaController controller = new JavaController();
                controller.setAbsolutePath(path);
                controller.setName(xx);
                // TODO: 2022/5/18 寻找各个方法
                StringBuilder tmpContent = new StringBuilder();
                tmpContent.append(content);
                List<String> x = getAllResultByRegexp(tmpContent.toString(), zhuShiPattern);
                controller.getMethodZhuShi().addAll(x);
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_YANZHENG.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_2.getRegexp())));
                ans.add(controller);
            }
        }
        return ans;
    }
获取所有的类
public static List<JavaClass> getAllClass(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> classPaths = FolderUtils.getAbsolutePathOfDirNameByCondition(dir, ".java");
        Pattern pattern = Pattern.compile(PatternEnum.CLASS_TITLE.getRegexp());
        Set<String> controllerSet = new HashSet<>();
        List<JavaClass> ans = new ArrayList<>();
        for (String path : classPaths) {
            String content = FileUtils.getFileContent(path, false);
            // TODO: 2022/5/18 寻找controller的类标头
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                String xx = matcher.group("name").trim();
                if (controllerSet.contains(xx)) {
                    continue;
                }
                controllerSet.add(xx);
                JavaClass controller = new JavaClass();
                controller.setAbsolutePath(path);
                controller.setName(xx);
                // TODO: 2022/5/18 寻找各个方法
                StringBuilder tmpContent = new StringBuilder();
                tmpContent.append(content);
                controller.getAllAnaotion().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ANA.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_YANZHENG.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_2.getRegexp())));
                ans.add(controller);
            }
        }
        return ans;
    }
比对两个项目

在完成对Java项目进行反序列化之后,我们对两个不同的项目进行比较

public static Double rejectProjects(JavaProject source, JavaProject target, String ignores) {
        System.out.println("-----生成分析结果--------");
//        Double zhuShi = rejectAllZhuShi(source, target);
//        Double classNum = rejectAllClass(source, target);
//        Double utils = rejectAllUtils(source, target);
        Map<String, JavaClass> sourceName2Class = new HashMap<>();
        List<JavaClass> sourceClasses = source.getClasses();
        for (JavaClass javaClass : sourceClasses) {
            sourceName2Class.put(javaClass.getName(), javaClass);
        }
        Double total = 0.0;
        int cnt = 0;
        for (JavaClass javaClass : target.getClasses()) {
            if (sourceName2Class.containsKey(javaClass.getName())) {
                cnt++;
                System.out.println("开始分析 " + javaClass.getName());
                String sourceClassBody = FileUtils.getFileContent(sourceName2Class.get(javaClass.getName()).getAbsolutePath(), false);
                for (String zhuShi1 : sourceName2Class.get(javaClass.getName()).getAllZhuShi()) {
                    sourceClassBody = sourceClassBody.replace(zhuShi1, "");
                }
                String targetClassBody = FileUtils.getFileContent(javaClass.getAbsolutePath(), false);
                for (String zhuShi2 : javaClass.getAllZhuShi()) {
                    targetClassBody = targetClassBody.replace(zhuShi2, "");
                }
                total += classSimilarity(sourceClassBody, targetClassBody, new HashSet<>(Arrays.asList(ignores.split(","))));
            }
        }

        return total / cnt;
    }

public static Map<String, Integer> splitStr(String classBody, Set<String> ignores) {
        String[] a = classBody.replaceAll(",|\\.| |\n|;|\\{|}|\\(|\\)|\\[|]|\"|==|=|<|>|:|/|\\\\|\\?|!", "----").toLowerCase().split("----");
        Map<String, Integer> ans = new HashMap<>();
        for (String aa : a) {
            if (ignores.contains(aa)) continue;
//            aa = aa.replaceAll("[\\\\u4e00-\\\\u9fa5]+","");
            if (StringUtils.hasText(aa)) {
                if (!ans.containsKey(aa)) {
                    ans.put(aa, 0);
                }
                ans.put(aa, ans.get(aa) + 1);
            }
        }
        return ans;
    }

    public static Double classSimilarity(String classA, String classB, Set<String> ignores) {
        if (classA.equals(classB)) {
            System.out.println("两边代码一模一样");
            return 1.0;
        }
        Map<String, Integer> a = splitStr(classA, ignores);
        Map<String, Integer> b = splitStr(classB, ignores);
        Set<String> xxx = new HashSet<>(a.keySet());
        xxx.addAll(b.keySet());
        if (a.size() == b.size()) {
            System.out.print("两边代码关键词数量相同,");
        } else {
            System.out.print("两边代码关键词数量不同,分别为 原始:" + a.size() + ",新的:" + b.size() + " ");
        }
        int cnt = 0;
        Set<String> numberNt = new HashSet<>();
        Set<String> strNt = new HashSet<>();
        for (String xxxx : xxx) {
            if (a.containsKey(xxxx) && b.containsKey(xxxx)) {
                if (a.get(xxxx).equals(b.get(xxxx))) {
                    cnt++;
                } else {
                    numberNt.add(xxxx);
                }
            } else {
                if (a.containsKey(xxxx) && !b.containsKey(xxxx)) {
                    strNt.add("减少了 " + xxxx);
                } else {
                    strNt.add("增加了 " + xxxx);
                }
            }
        }
        System.out.println("其中关键字数量相同的有 " + cnt + "个,占总个数的" + (2 * cnt * 1.0) / (a.size() + b.size()));
        System.out.println("数量不同的为 " + Json.toJson(numberNt));
        System.out.println("关键词不同的为 " + Json.toJson(strNt));
        System.out.println();
        return (2 * cnt * 1.0) / (a.size() + b.size());
    }

这个方案我曾经拿来比对开源项目与面试者提供的项目的区别,以查看面试者究竟是何水平。
![image.png](https://img-blog.csdnimg.cn/img_convert/3ac4a148f6671e7d6cb0ccfbfbfbf6d3.png#clientId=ub8ddd883-d89f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=172&id=u4a006309&margin=[object Object]&name=image.png&originHeight=172&originWidth=2424&originalType=binary&ratio=1&rotation=0&showTitle=false&size=45228&status=done&style=none&taskId=ucc9126ec-e797-42dc-aafa-6ef1d20a164&title=&width=2424)
最终会得到相似度
![image.png](https://img-blog.csdnimg.cn/img_convert/c09c35e2d45a8799d61d2f926952927e.png#clientId=ub8ddd883-d89f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=638&id=u57fda94c&margin=[object Object]&name=image.png&originHeight=638&originWidth=1600&originalType=binary&ratio=1&rotation=0&showTitle=false&size=82967&status=done&style=none&taskId=ue30f6a10-56a5-460a-bdff-927ea5c1bc1&title=&width=1600)
现贴上完整代码

import cn.chaojilaji.auto.zlang.codereview.javahandler.JavaClass;
import cn.chaojilaji.auto.zlang.codereview.javahandler.JavaProject;
import cn.chaojilaji.auto.zlang.codereview.javahandler.PatternEnum;
import cn.chaojilaji.auto.zlang.codereview.javahandler.controllerHandler.JavaController;
import cn.chaojilaji.auto.zlang.codereview.javahandler.controllerHandler.JavaHttpApi;
import cn.chaojilaji.auto.zlang.codereview.javahandler.pomHandler.PomExchange;
import cn.chaojilaji.auto.zlang.codereview.javahandler.pomHandler.data.Pom;
import cn.chaojilaji.auto.zlang.file.FileUtils;
import cn.chaojilaji.auto.zlang.file.FolderUtils;
import cn.chaojilaji.auto.zlang.generate.DuiJieUtils;
import cn.chaojilaji.auto.zlang.generate.GenerateDto;
import cn.chaojilaji.auto.zlang.generate.GenerateFile;
import cn.chaojilaji.auto.zlang.json.Json;
import cn.chaojilaji.auto.zlang.string.StringFormatUtils;
import cn.chaojilaji.auto.zlang.yaml.YamlUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class JavaProjectCodeReview {


    /**
     * 该函数为准备阶段函数
     *
     * @param file
     */
    public static void getPomStruct(String file) {
        String xmlStr = FileUtils.getFileContent(file, false);
        ObjectMapper xmlMapper = new XmlMapper();
        Map y = null;
        try {
            y = xmlMapper.readValue(xmlStr, Map.class);
            String json = Json.toJson(y);
            List<GenerateDto> generateDtos = DuiJieUtils.recursionJson(json, "Pom");
            GenerateFile.createExchange(generateDtos, "src/main/java/cn/chaojilaji/auto/zlang/codereview/javahandler/pomHandler", "Pom");
            for (GenerateDto dto : generateDtos) {
                GenerateFile.createDto(dto, "src/main/java/cn/chaojilaji/auto/zlang/codereview/javahandler/pomHandler/data");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static List<Pom> getPomContent(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> pomPaths = FolderUtils.getAbsolutePathOfDirNameByCondition(dir, "pom.xml");
        List<Pom> poms = new ArrayList<>();
        for (String pomPath : pomPaths) {
            String content = FileUtils.getFileContent(pomPath, false);
            ObjectMapper xmlMapper = new XmlMapper();
            try {
                Pom pom = PomExchange.exchangePom(xmlMapper.readValue(content, Map.class));
                poms.add(pom);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return poms;
    }

    public static void getPropertyContent(String folder, String ignores, JavaProject project) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> properties = FolderUtils.getAbsolutePathOfDirNameByCondition(dir, ".yml");
        properties.addAll(FolderUtils.getAbsolutePathOfDirNameByCondition(dir, ".property"));
        for (String path : properties) {
            if (path.endsWith(".yml")) {
                Map<String, Object> xx = YamlUtils.loadFromFile2Map(path);
                if (Objects.isNull(xx)) continue;
                for (Map.Entry<String, Object> xxx : xx.entrySet()) {
                    String xxxx = xxx.getKey().replace("_", "").toLowerCase() + " : "
                            + xxx.getValue().toString().replace("_", "").toLowerCase();
                    if (xxxx.contains("url")
                            || xxxx.contains("password")
                            || xxxx.contains("pwd")
//                            || xxxx.contains("path")
                            || xxxx.contains("username")
                            || xxxx.contains("http")) {
                        project.getSensitiveProperties().add(xxxx);
                    }
                    project.getAllProperties().add(xxxx);
                }
            } else {
                List<String> content = FileUtils.getListKeyWithOneLine(path, false);
                for (String x : content) {
                    String xxxx = x.replaceAll("_", "").toLowerCase();
                    if (xxxx.contains("url")
                            || xxxx.contains("password")
                            || xxxx.contains("pwd")
//                            || xxxx.contains("path")
                            || xxxx.contains("username")
                            || xxxx.contains("http")) {
                        project.getSensitiveProperties().add(xxxx);
                    }
                    project.getAllProperties().add(xxxx);
                }
            }
        }
    }

    public static List<String> getAllResultByRegexp(String content, Pattern pattern) {
        Matcher matcher = pattern.matcher(content);
        List<String> ans = new ArrayList<>();
        while (matcher.find()) {
            String x = matcher.group();
            ans.add(x);
//            System.out.println(x);
//            System.out.println("begin = " + matcher.start() + ", end = " + matcher.end());
        }
        return ans;

    }

    public static List<JavaClass> getAllClass(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> classPaths = FolderUtils.getAbsolutePathOfDirNameByCondition(dir, ".java");
        Pattern pattern = Pattern.compile(PatternEnum.CLASS_TITLE.getRegexp());
        Set<String> controllerSet = new HashSet<>();
        List<JavaClass> ans = new ArrayList<>();
        for (String path : classPaths) {
            String content = FileUtils.getFileContent(path, false);
            // TODO: 2022/5/18 寻找controller的类标头
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                String xx = matcher.group("name").trim();
                if (controllerSet.contains(xx)) {
                    continue;
                }
                controllerSet.add(xx);
                JavaClass controller = new JavaClass();
                controller.setAbsolutePath(path);
                controller.setName(xx);
                // TODO: 2022/5/18 寻找各个方法
                StringBuilder tmpContent = new StringBuilder();
                tmpContent.append(content);
                controller.getAllAnaotion().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ANA.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_YANZHENG.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_2.getRegexp())));
                ans.add(controller);
            }
        }
        return ans;
    }

    public static List<JavaController> getAllController(String folder, String ignores) {
        FolderUtils.Dir dir = FolderUtils.getFolder(folder, ignores);
        List<String> controllerPaths = FolderUtils.getAbsolutePathOfDirContentByCondition(dir, "@Controller");
        controllerPaths.addAll(FolderUtils.getAbsolutePathOfDirContentByCondition(dir, "@RestController"));
        Collections.sort(controllerPaths);
        List<JavaController> ans = new ArrayList<>();
        Pattern pattern = Pattern.compile(PatternEnum.CLASS_TITLE.getRegexp());
        Pattern zhuShiPattern = Pattern.compile(PatternEnum.CONTROLLER_FUNC_ZHUSHI.getRegexp());
        Set<String> controllerSet = new HashSet<>();
        for (String path : controllerPaths) {
            String content = FileUtils.getFileContent(path, false);
            // TODO: 2022/5/18 寻找controller的类标头
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                String xx = matcher.group("name").trim();
                if (controllerSet.contains(xx)) {
                    continue;
                }
                controllerSet.add(xx);
                JavaController controller = new JavaController();
                controller.setAbsolutePath(path);
                controller.setName(xx);
                // TODO: 2022/5/18 寻找各个方法
                StringBuilder tmpContent = new StringBuilder();
                tmpContent.append(content);
                List<String> x = getAllResultByRegexp(tmpContent.toString(), zhuShiPattern);
                controller.getMethodZhuShi().addAll(x);
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_YANZHENG.getRegexp())));
                controller.getAllZhuShi().addAll(getAllResultByRegexp(tmpContent.toString(), Pattern.compile(PatternEnum.ZHUSHI_2.getRegexp())));
                ans.add(controller);
            }
        }
        return ans;
    }

    public static void categoryClass(JavaProject project) {
        List<JavaClass> javaClasses = project.getClasses();
        for (JavaClass javaClass : javaClasses) {
            String x = javaClass.getName().toLowerCase();
            x = x.toLowerCase().trim();
            if (x.endsWith("pojo") || x.endsWith("query") || x.endsWith("bo")
                    || x.endsWith("ao") || x.endsWith("dto") || x.endsWith("vo")
                    || x.endsWith("entity")) {
                if (x.split(" ").length == 1) {
                    project.getPojo().add(javaClass);
                    if (x.endsWith("query")) {
                        project.getQuery().add(javaClass);
                    }
                    if (x.endsWith("vo")) {
                        project.getVo().add(javaClass);
                    }
                    if (x.endsWith("dto")) {
                        project.getDto().add(javaClass);
                    }
                }
            }
            if (x.contains("service") || x.contains("server") || x.contains("task")) {
                project.getServices().add(javaClass);
            }
            if (x.contains("repository") || x.contains("dao") || x.contains("mapper")) {
                project.getRepository().add(javaClass);
            }
            if (x.contains("util")) {
                project.getUtils().add(javaClass);
            }
        }
    }

    public static void getAllZhuShi(JavaProject project) {
        List<JavaClass> classes = project.getClasses();
        for (JavaClass javaClass : classes) {
            if (Objects.nonNull(javaClass.getAllZhuShi())) {
                project.getAllZhuShi().addAll(javaClass.getAllZhuShi());
            }
        }
    }

    public static JavaClass getJavaClassByName(String name, JavaProject javaProject) {
        for (JavaClass javaClass : javaProject.getClasses()) {
            if (javaClass.getName().equalsIgnoreCase(name)) {
                return javaClass;
            }
        }
        return null;
    }

    public static void handleFields(JavaClass javaClass) {
        String path = javaClass.getAbsolutePath();
        String content = FileUtils.getFileContent(path, false);
        Pattern pattern1 = Pattern.compile("((public|private|protect) )(?<type>[<>a-zA-Z0-9]+) (?<name>[a-zA-Z0-9]+);");
        Matcher matcher = pattern1.matcher(content);
        while (matcher.find()) {
            String type = matcher.group("type");
            String name = matcher.group("name");
            if (type.equalsIgnoreCase(javaClass.getName())) {
                continue;
            }
            javaClass.getFields().put(StringFormatUtils.camel(name), type);
        }
    }

    public static Map<String, Object> getApisParams(String params, JavaProject javaProject) {
        Matcher requestBodyMatcher = PatternEnum.PARAMS_REQUEST_BODY.getPattern().matcher(params);
        Matcher queryObjectMatcher = PatternEnum.PARAMS_QUERY.getPattern().matcher(params);
        Matcher pathMatcher = PatternEnum.PARAMS_PATH.getPattern().matcher(params);
        Matcher paramMatcher = PatternEnum.PARAMS_REQUEST_PARAM.getPattern().matcher(params);
        Matcher param2Matcher = PatternEnum.PARAMS_REQUEST_PARAM2.getPattern().matcher(params);
        Matcher fileMatcher = PatternEnum.PARAMS_MULTIPARTFILE.getPattern().matcher(params);
        Map<String, Object> ans = new HashMap<>();
        while (requestBodyMatcher.find()) {
            String className = requestBodyMatcher.group("type");
            if (StringUtils.hasText(className)) {
                JavaClass javaClass = getJavaClassByName(className, javaProject);
                if (Objects.nonNull(javaClass)) {
                    ans.put(javaClass.getName(), javaClass.getFields());
                } else {
                    ans.put(className, "项目中不存在");
                }
            }
        }
        while (queryObjectMatcher.find()) {
            String className = queryObjectMatcher.group("queryObject");
            if (StringUtils.hasText(className)) {
                JavaClass javaClass = getJavaClassByName(className, javaProject);
                if (Objects.nonNull(javaClass)) {
                    ans.put(javaClass.getName(), javaClass.getFields());
                } else {
                    ans.put(className, "项目中不存在");
                }
            }
        }
        while (pathMatcher.find()) {
            String innerName = pathMatcher.group("innerName");
            String type = pathMatcher.group("type");
            if (StringUtils.hasText(innerName))
            ans.put(StringFormatUtils.camel(innerName), type);
        }
        while (paramMatcher.find()) {
            String innerName = paramMatcher.group("innerName");
            String type = paramMatcher.group("type");
            String nullable = paramMatcher.group("nullable");
            String outerName = paramMatcher.group("outerName");
            String value = type;
            String key = outerName;
            if (StringUtils.hasText(nullable)){
                value = value + " or nullable";
            }
            if (StringUtils.hasText(innerName)){
                key = innerName;
            }
            if (StringUtils.hasText(key))
            ans.put(StringFormatUtils.camel(key),value);
        }
        while (param2Matcher.find()) {
            String innerName = param2Matcher.group("innerName");
            String type = param2Matcher.group("type");
            String nullable = param2Matcher.group("nullable");
            String outerName = param2Matcher.group("outerName");
            String value = type;
            String key = outerName;
            if (StringUtils.hasText(nullable)){
                value = value + " or nullable";
            }
            if (StringUtils.hasText(innerName)){
                key = innerName;
            }
            if (StringUtils.hasText(key))
                ans.put(StringFormatUtils.camel(key),value);
        }
        while (fileMatcher.find()){
            String name = fileMatcher.group("name");
            if (StringUtils.hasText(name))
            ans.put(StringFormatUtils.camel(name),"file");
        }
        return ans;
    }

    public static void getControllerHttpMethod(JavaProject project) {
        Pattern pattern = Pattern.compile(PatternEnum.CONTROLLER_2_API.getRegexp());
        List<JavaController> controllers = project.getPublicControllers();
        for (JavaController controller : controllers) {
            String content = FileUtils.getFileContent(controller.getAbsolutePath(), false);
            Matcher matcher = pattern.matcher(content);
            while (matcher.find()) {
                String method = matcher.group("method");
                String path = matcher.group("path");
                String name = matcher.group("name");
                String params = matcher.group("params");
                String responseBodyOrNot = matcher.group("jsonOrNot");
                if (method.toLowerCase().equals("request")) {
                    method = matcher.group(4);
                }
                JavaHttpApi api = new JavaHttpApi();
                api.setBelongController(controller.getName());
                api.setMethod(Objects.isNull(method) ? "controller上的或未定义" : method);
                api.setUrl(path);
                api.setParamStr(params);
                api.setParamJsons(getApisParams(params,project));
                api.setName(name);
                controller.getApis().add(api);
            }
        }
    }


    public static JavaProject reviewJavaProject(String folder, String ignores) {
        JavaProject project = new JavaProject();
        project.setName(folder.replaceAll("/", "").replace("\\", "").toLowerCase());
        project.setPath(folder);
        project.getPoms().addAll(getPomContent(folder, ignores));
        project.getPublicControllers().addAll(getAllController(folder, ignores));
        getPropertyContent(folder, ignores, project);
        project.getClasses().addAll(getAllClass(folder, ignores));
        for (JavaClass javaClass : project.getClasses()) {
            project.getAllAnoations().addAll(javaClass.getAllAnaotion());
            handleFields(javaClass);
        }
        categoryClass(project);
        getAllZhuShi(project);
        getControllerHttpMethod(project);
        System.out.println(project.getPublicControllers().size());
        return project;
    }

    public static Double rejectAllZhuShi(JavaProject source, JavaProject target) {
        System.out.println("-----生成分析结果--------");
        Set<String> x = new HashSet<>(source.getAllZhuShi());
        x.retainAll(target.getAllZhuShi());
        int n = target.getAllZhuShi().size();
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (x.contains(target.getAllZhuShi().get(i))) {
                cnt++;
            }
        }
        Map<String, Object> params = new HashMap<>();
        params.put("old_size", source.getAllZhuShi().size());
        params.put("new_size", target.getAllZhuShi().size());
        params.put("new_in_old_size", cnt);

        System.out.println(StringFormatUtils.formatByName("原始的注释条数为 {old_size}条,新的注释条数为{new_size}条,其中相同的注释有 {new_in_old_size} 条", params));
        return (2 * cnt) / (source.getAllZhuShi().size() + target.getAllZhuShi().size()) * 1.0;
    }

    public static Double rejectAllClass(JavaProject source, JavaProject target) {
        List<JavaClass> javaClasses = source.getClasses();
        Set<String> x = new HashSet<>(javaClasses.stream().map(JavaClass::getName).collect(Collectors.toSet()));
        x.retainAll(target.getClasses().stream().map(JavaClass::getName).collect(Collectors.toSet()));
        Map<String, Object> params = new HashMap<>();
        params.put("old_size", source.getClasses().size());
        params.put("new_size", target.getClasses().size());
        params.put("new_in_old_size", x.size());

        System.out.println(StringFormatUtils.formatByName("原始的类的个数为 {old_size}条,新的类的个数为{new_size}条,其中相同的类的个数有 {new_in_old_size} 条", params));
        return (2 * x.size()) / (source.getAllZhuShi().size() + target.getAllZhuShi().size()) * 1.0;
    }

    public static Double rejectAllUtils(JavaProject source, JavaProject target) {
        List<JavaClass> javaClasses = source.getUtils();
        Set<String> x = new HashSet<>(javaClasses.stream().map(JavaClass::getName).collect(Collectors.toSet()));
        x.retainAll(target.getUtils().stream().map(JavaClass::getName).collect(Collectors.toSet()));
        Map<String, Object> params = new HashMap<>();
        params.put("old_size", source.getUtils().size());
        params.put("new_size", target.getUtils().size());
        params.put("new_in_old_size", x.size());

        System.out.println(StringFormatUtils.formatByName("原始的工具类的个数为 {old_size}条,新的工具类的个数为{new_size}条,其中相同的工具类的个数有 {new_in_old_size} 条", params));
        return (2 * x.size()) / (source.getAllZhuShi().size() + target.getAllZhuShi().size()) * 1.0;
    }

    public static Map<String, Integer> splitStr(String classBody, Set<String> ignores) {
        String[] a = classBody.replaceAll(",|\\.| |\n|;|\\{|}|\\(|\\)|\\[|]|\"|==|=|<|>|:|/|\\\\|\\?|!", "----").toLowerCase().split("----");
        Map<String, Integer> ans = new HashMap<>();
        for (String aa : a) {
            if (ignores.contains(aa)) continue;
//            aa = aa.replaceAll("[\\\\u4e00-\\\\u9fa5]+","");
            if (StringUtils.hasText(aa)) {
                if (!ans.containsKey(aa)) {
                    ans.put(aa, 0);
                }
                ans.put(aa, ans.get(aa) + 1);
            }
        }
        return ans;
    }

    public static Double classSimilarity(String classA, String classB, Set<String> ignores) {
        if (classA.equals(classB)) {
            System.out.println("两边代码一模一样");
            return 1.0;
        }
        Map<String, Integer> a = splitStr(classA, ignores);
        Map<String, Integer> b = splitStr(classB, ignores);
        Set<String> xxx = new HashSet<>(a.keySet());
        xxx.addAll(b.keySet());
        if (a.size() == b.size()) {
            System.out.print("两边代码关键词数量相同,");
        } else {
            System.out.print("两边代码关键词数量不同,分别为 原始:" + a.size() + ",新的:" + b.size() + " ");
        }
        int cnt = 0;
        Set<String> numberNt = new HashSet<>();
        Set<String> strNt = new HashSet<>();
        for (String xxxx : xxx) {
            if (a.containsKey(xxxx) && b.containsKey(xxxx)) {
                if (a.get(xxxx).equals(b.get(xxxx))) {
                    cnt++;
                } else {
                    numberNt.add(xxxx);
                }
            } else {
                if (a.containsKey(xxxx) && !b.containsKey(xxxx)) {
                    strNt.add("减少了 " + xxxx);
                } else {
                    strNt.add("增加了 " + xxxx);
                }
            }
        }
        System.out.println("其中关键字数量相同的有 " + cnt + "个,占总个数的" + (2 * cnt * 1.0) / (a.size() + b.size()));
        System.out.println("数量不同的为 " + Json.toJson(numberNt));
        System.out.println("关键词不同的为 " + Json.toJson(strNt));
        System.out.println();
        return (2 * cnt * 1.0) / (a.size() + b.size());
    }


    public static Double rejectProjects(JavaProject source, JavaProject target, String ignores) {
        System.out.println("-----生成分析结果--------");
//        Double zhuShi = rejectAllZhuShi(source, target);
//        Double classNum = rejectAllClass(source, target);
//        Double utils = rejectAllUtils(source, target);
        Map<String, JavaClass> sourceName2Class = new HashMap<>();
        List<JavaClass> sourceClasses = source.getClasses();
        for (JavaClass javaClass : sourceClasses) {
            sourceName2Class.put(javaClass.getName(), javaClass);
        }
        Double total = 0.0;
        int cnt = 0;
        for (JavaClass javaClass : target.getClasses()) {
            if (sourceName2Class.containsKey(javaClass.getName())) {
                cnt++;
                System.out.println("开始分析 " + javaClass.getName());
                String sourceClassBody = FileUtils.getFileContent(sourceName2Class.get(javaClass.getName()).getAbsolutePath(), false);
                for (String zhuShi1 : sourceName2Class.get(javaClass.getName()).getAllZhuShi()) {
                    sourceClassBody = sourceClassBody.replace(zhuShi1, "");
                }
                String targetClassBody = FileUtils.getFileContent(javaClass.getAbsolutePath(), false);
                for (String zhuShi2 : javaClass.getAllZhuShi()) {
                    targetClassBody = targetClassBody.replace(zhuShi2, "");
                }
                total += classSimilarity(sourceClassBody, targetClassBody, new HashSet<>(Arrays.asList(ignores.split(","))));
            }
        }

        return total / cnt;
    }

    public static void main(String[] args) {
        String ignores2 = "goose,reggie,glj,itheima,*,**";
        JavaProject source = reviewJavaProject("D:\\个人\\面试的\\1 瑞吉外卖项目\\1 瑞吉外卖项目\\代码\\day06\\reggie_take_out\\reggie_take_out", "target,.mvn,.idea,.git");
        JavaProject source1 = reviewJavaProject("D:\\个人\\面试的\\5 瑞吉外卖项目优化篇\\5 瑞吉外卖项目优化篇\\代码\\day03\\reggie_take_out\\reggie_take_out", "target,.mvn,.idea,.git");
        Double y = rejectProjects(source, source1, ignores2);
        System.out.println(y);
    }



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海燕技术栈

你的鼓励我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值