掃描Class文件,獲取所有可調用方法及方法的入參等信息

主要思路:
1.從gitlab上下載contract源碼,使用org.eclipse.jgit
2.mvn編譯並把生成的jar和依賴的jar拷貝到指定目錄下,使用org.apache.maven.shared maven-invoker
3.掃描源碼列出所有以I開頭,以.java結尾的文件絕對路徑getCanonicalPath()
4.根據第三步的文件絕對路徑,切割轉換出className,package+文件名
5.Class獲取Method,解析每個method,java基本類型需要轉換爲class類的名稱

MethodEntity.java

public class MethodEntity {
    // 接口類名,例如:IZZHaHaService
    private String interfaceClassName;
    // 接口類名,包含package信息,例如:com.bj58.zhuanzhuan.IZZHaHaService
    private String interfaceClassFullName;
    private String methodName;
    // 入參類型的完整名稱,按照入參順序排列,例如:java.util.List<com.bj58.zhuanzhuan.entity.ViViEntity>
    private List<String> paramterTypeCanonicalNames;
    // 入參類型名稱,按照入參順序排列,例如:List
    private List<String> paramterTypeNames;

    /**
     * 根據函數名和入參的類型及名稱,判斷當前實例是否是要找的
     * 
     * @param methodName
     *            不爲空
     * @param paramNames
     *            參數類型列表
     * @param interfaceName
     *            接口類名,傳null不做比對
     * @return True or False
     */
    public Boolean isSeached(String methodName, List<String> paramNames, String interfaceName) {
        if (interfaceName != null) {
            if (!interfaceName.equals(this.interfaceClassName)) {
                return Boolean.FALSE;
            }
        }

        if (methodName == null) {
            return Boolean.FALSE;
        }
        if (paramNames == null && getParamterTypeNames() == null) {
            return Boolean.TRUE;
        }

        if ((paramNames == null && getParamterTypeNames() != null)
                || paramNames != null && getParamterTypeNames() == null
                || paramNames.size() != getParamterTypeNames().size()) {
            return Boolean.FALSE;
        }

        if (methodName.equals(getMethodName())) {
            return paramNames.equals(getParamterTypeNames());
        } else {
            return Boolean.FALSE;
        }
    }
    public String getInterfaceClassFullName() {
        return interfaceClassFullName;
    }

    public void setInterfaceClassFullName(String interfaceClassFullName) {
        this.interfaceClassFullName = interfaceClassFullName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public List<String> getParamterTypeCanonicalNames() {
        return paramterTypeCanonicalNames;
    }

    public void setParamterTypeCanonicalNames(List<String> paramterTypeCanonicalNames) {
        this.paramterTypeCanonicalNames = paramterTypeCanonicalNames;
    }

    public List<String> getParamterTypeNames() {
        return paramterTypeNames;
    }

    public void setParamterTypeNames(List<String> paramterTypeNames) {
        this.paramterTypeNames = paramterTypeNames;
    }

    public String getInterfaceClassName() {
        return interfaceClassName;
    }

    public void setInterfaceClassName(String interfaceClassName) {
        this.interfaceClassName = interfaceClassName;
    }

}

掃包,獲取所有的可調用方法

// java基本數據類型和對應的類
private static Map<String, String> basicDataTypeReference = new HashMap<String, String>() {
        private static final long serialVersionUID = 4477784757087366211L;
        {
            // 九種基本類型
            // java.lang.Boolean
            // java.lang.Character
            // java.lang.Byte
            // java.lang.Short
            // java.lang.Integer
            // java.lang.Long
            // java.lang.Float
            // java.lang.Double
            // java.lang.Void
            put("boolean", "java.lang.Boolean");
            put("char", "java.lang.Character");
            put("byte", "java.lang.Byte");
            put("short", "java.lang.Short");
            put("int", "java.lang.Integer");
            put("long", "java.lang.Long");
            put("float", "java.lang.Float");
            put("double", "java.lang.Double");
        }
    };

/**
* 掃碼contract目錄下的所有接口文件
* 
* @param serviceName
*            服務名,例如zzpost
* @throws Exception
*/
public void scanContractFiles(String serviceName) throws Exception {
    // 拿到所有以.java結尾的文件
    Collection<File> sourceFiles = FileUtils.listFiles(file, new WildcardFileFilter("I*.java"),TrueFileFilter.INSTANCE);
    for (File f : sourceFiles) {
        String canonicalPath = f.getCanonicalPath();
        String fileName = f.getName();
                // D:\aaa\com\bj58\zhuanzhuan\IHaHaService.java
                // 以com開始不要最後的.java com.bj58.zhuanzhuan.IHaHaService
        String clazzPath = canonicalPath.substring(canonicalPath.indexOf("com"), canonicalPath.length() - 5)
                        .replace("\\", ".").replace("/", ".");

        Class<?> clazz = Class.forName(clazzPath, true, loader);
        for (Method m : clazz.getMethods()) {
            MethodEntity entity = new MethodEntity();
            List<String> paramTypeCanonicalNames = new ArrayList<>();
            List<String> paramTypeNames = new ArrayList<>();

            // 5 爲".java"的長度
            entity.setInterfaceClassName(fileName.substring(0, fileName.length() - 5));
            entity.setInterfaceClassFullName(clazzPath);
            entity.setMethodName(m.getName());

            for (Parameter p : m.getParameters()) {
                String paramSimpleName = p.getType().getSimpleName();
                // List,抹掉具體類型
                paramTypeNames.add(basicDataType2ClassType(paramSimpleName, true));

                String paramClassName = p.getParameterizedType().getTypeName();
                // java.util.List<java.lang.Long>,參數類型的完整名稱
                paramTypeCanonicalNames.add(basicDataType2ClassType(paramClassName, false));
            }

            entity.setParamterTypeCanonicalNames(paramTypeCanonicalNames);
            entity.setParamterTypeNames(paramTypeNames);
            methodEntities.add(entity);

            String json = JSON.toJSONString(entity);
            System.out.println(json);
        }
    }
}
 /**
     * 基本數據類型替換爲基本類型對應的class類
     * 
     * @param type
     *            需要轉換的類型
     * @param isSimpleName
     *            是否爲類名簡寫
     * @return String
     */
private String basicDataType2ClassType(String type, Boolean isSimpleName) {
    String res = "";
    if (basicDataTypeReference.containsKey(type)) {
        res = basicDataTypeReference.get(type);
        if (isSimpleName) {
            res = res.substring(res.lastIndexOf(".") + 1);
        }
        return res;
     } else {
        return type;
     }
}

console輸出如下:


{"interfaceClassFullName":"com.bj58.zhuanzhuan.IAaaaService","interfaceClassName":"IAaaaService","methodName":"getInfo","paramterTypeCanonicalNames":["java.lang.String","java.util.List<java.lang.Long>"],"paramterTypeNames":["String","List"]}
{"interfaceClassFullName":"com.bj58.zhuanzhuan.IBiuBiuService","interfaceClassName":"IBiuBiuService","methodName":"getUser","paramterTypeCanonicalNames":["java.lang.String","java.lang.String","java.lang.String","java.lang.Integer","java.lang.Integer"],"paramterTypeNames":["String","String","String","Integer","Integer"]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章