項目不同系統相互調用時,有些是直接根據接口組報文,或者先根據對方的接口組實體類,在轉換成報文。如果需要通過後者先組實體類的方式,接口調用過多時或者對方接口嵌套比較深,那麼在組實體類時會導入很多類,程序界面比較臃腫。那麼就可以通過反射來組裝請求類。
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ReflectUtil {
private static Logger logger = LoggerFactory.getLogger(ReflectUtil.class);
public static Map<String, String> Map_AllClassPath = new HashMap<String, String>();
public static Map<String, Class> Map_AllClassObj = new HashMap<String, Class>();
/**
*
* @param map 類屬性與值的鍵值對
* @param packPath 包名
* @param objType 要獲取的反射對象類名
* @return
* @throws Exception
*/
public Object getESBReqObj(Map<String, Object> map, String packPath, String objType) throws Exception {
Class<?> clazz = Class.forName(packPath);
// 獲取內部類
Class<?>[] innerClazz = clazz.getDeclaredClasses();
// 用於反射各級子類使用,存放請求類中所以子類類名
List<String> sonClsName = new ArrayList<String>();
for (Class<?> cls : innerClazz) {
String clsName = cls.getName();
// 獲取子類名稱
int rmkindex = clsName.indexOf("$") + 1;
String clsName1 = clsName.substring(rmkindex);
sonClsName.add(clsName.substring(rmkindex));
Map_AllClassPath.put(clsName1, clsName);
Map_AllClassObj.put(clsName1, cls);
}
// 判斷入參類名
if (Map_AllClassPath.containsKey(objType)) {
Object obj = refToObject(map, Map_AllClassPath.get(objType));
return obj;
} else {
logger.error("在待反射類中不存在" + objType + "此類");
}
return objType;
}
/**
*
* @param map 屬性值
* @param className 內部類類名
* @return
* @throws Exception
*/
private Object refToObject(Map<String, Object> map, String className) throws Exception {
Class<?> c = Class.forName(className);
Object obj = c.newInstance();
Field[] files = c.getDeclaredFields();
// 存放上級類對象
Map<String, Object> Map_TransMap = new HashMap<String, Object>();
// 獲取set方法賦值
for (Field field : files) {
// 獲取變量名稱
String fpath = field.toString();
String fname = fpath.substring(fpath.lastIndexOf(".") + 1);
// 獲取變量類型
Class<?> ftype = field.getType();
// 屬性類型名稱,除去前綴"class"
String ftypenm = ftype.toString().substring(6);
// 與接口對應的字段名稱,除去前綴local
String ffname = fname.substring(5);
// 處理list對象
if ("class java.util.ArrayList".equals(ftype.toString())) {
Type listType = c.getDeclaredField(fname).getGenericType();
String listTypeNm = listType.toString();
// 獲取list泛型類型
int startIndex = listTypeNm.indexOf("<") + 1;
int endIndex = listTypeNm.indexOf(">");
String listInnerTy = listTypeNm.substring(startIndex, endIndex);
if (Map_AllClassPath.containsValue(listInnerTy)) {
// 存放轉換後的結果對象
List<Object> innerObjList = new ArrayList<Object>();
for (Map<String, Object> innerMap : (List<Map>) map.get(ffname)) {
Object innerSonObj = refToObject(innerMap, listInnerTy);
innerObjList.add(innerSonObj);
}
// 移除以轉換的類
Map_AllClassPath.remove(files);
Map_TransMap.put(fname, innerObjList);
}
} else if (Map_AllClassPath.containsKey(ftypenm)) {
Map<String, Object> tempMap = new HashMap<String, Object>();
if (map.containsKey(ffname)) {
tempMap = (Map<String, Object>) map.get(ffname);
} else {
tempMap = map;
}
Object sonObj = refToObject(tempMap, ftypenm);
Map_TransMap.put(fname, sonObj);
Map_AllClassPath.remove(files);
} else if (map.containsKey(ffname)) {
Method method = c.getMethod(
"set" + ffname.substring(0, 1).toUpperCase() + ffname.substring(1, ffname.length()), ftype);
logger.info("類屬性類型:" + ffname + "---" + ftype + "---" + (map.get(ffname)).getClass());
if (field.getType().isAssignableFrom(String.class)) {
logger.info(ffname + "String類型屬性");
if (map.get(ffname).getClass().isAssignableFrom(Integer.class)
|| map.get(ffname).getClass().isAssignableFrom(Long.class)
|| map.get(ffname).getClass().isAssignableFrom(Float.class)) {
method.invoke(obj, map.get(ffname).toString());
} else {
method.invoke(obj, map.get(ffname));
logger.info(ffname + "反射成功");
}
} else if (field.getType().isAssignableFrom(Double.class)
|| field.getType().isAssignableFrom(double.class)) {
logger.info(ffname + "Double類型屬性");
if (map.get(ffname).getClass().isAssignableFrom(Integer.class)
|| map.get(ffname).getClass().isAssignableFrom(Long.class)
|| map.get(ffname).getClass().isAssignableFrom(String.class)
|| map.get(ffname).getClass().isAssignableFrom(Float.class)) {
method.invoke(obj, (Double) Double.parseDouble(map.get(ffname).toString()));
logger.info(ffname + "反射成功");
}
} else {
Object object = (Object) map.get(ffname);
if (object instanceof ArrayList) {
ArrayList list = (ArrayList) object;
if (list.size() > 0) {
method.invoke(obj, map.get(ffname));
}
} else {
method.invoke(obj, map.get(ffname));
}
}
}
if (!Map_TransMap.isEmpty()) {
logger.info("開始組裝上層對象");
for (Map.Entry<String, Object> emap : Map_TransMap.entrySet()) {
String ename = emap.getKey().substring(5);
Class etype = emap.getValue().getClass();
Method method = c.getMethod(
"set" + ename.substring(0, 1).toUpperCase() + ename.substring(1, ename.length()), etype);
method.invoke(obj, Map_TransMap.get(emap.getKey()));
logger.info("上層對象組裝成功");
}
}
}
return obj;
}
}
關於入參map的要求,按照接口層級組裝map節點即可