主要思路:
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"]}