反射構建類

項目不同系統相互調用時,有些是直接根據接口組報文,或者先根據對方的接口組實體類,在轉換成報文。如果需要通過後者先組實體類的方式,接口調用過多時或者對方接口嵌套比較深,那麼在組實體類時會導入很多類,程序界面比較臃腫。那麼就可以通過反射來組裝請求類。


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節點即可
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章