反射机制Reflection 简单的理解就是对class类的运用,在项目当中,适用于很多独特的场景,比如我们项目中的需求,1 我这边有两条数据,我主要知道两条数据哪些字段做了变更;2 我们跟别的webServer做联调,适配推送过去的字段等等。
public class Conversion { //将model中与entity中类型和名称相同的属性值赋值给对应的entity的属性,并返回entity public static <T1, T2> T2 TypeConversion(T1 model, T2 entity) { List<Map<String, Object>> modelList = getFiledInfo(model); List<Map<String, Object>> entityList = getFiledInfo(entity); for (Map e : entityList) { for (Map m : modelList) { /** * 判断类型和属性名是否都相同 */ if (e.get("type").toString().equals(m.get("type").toString()) && e.get("name") .toString() .equals(m.get("name").toString())) { try { Field f = entity.getClass().getDeclaredField(e.get("name").toString()); f.setAccessible(true); f.set(entity, m.get("value")); } catch (Exception ex) {//查看其父类属性 try { Field f = entity.getClass().getSuperclass().getDeclaredField(e.get("name").toString()); f.setAccessible(true); f.set(entity, m.get("value")); } catch (Exception e1) { logger.error(ex.getMessage(), "conversion类型转换错误 " + ex); } } } } } return entity; } /** * 根据属性名获取属性值 */ private static Object getFieldValueByName(String fieldName, Object o) { try { String firstLetter = fieldName.substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + fieldName.substring(1); Method method = o.getClass().getMethod(getter, new Class[]{}); Object value = method.invoke(o, new Object[]{}); return value; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } /** * 获取属性名数组 */ private static String[] getFiledName(Object o) { Field[] fields = o.getClass().getDeclaredFields(); String[] fieldNames = new String[fields.length]; for (int i = 0; i < fields.length; i++) { fieldNames[i] = fields[i].getName(); } return fieldNames; } /** * 获取属性类型(type),属性名(name),属性值(value)的map组成的list */ private static List<Map<String, Object>> getFiledInfo(Object o) { List<Map<String, Object>> list = new ArrayList<>(); List<Field> fields = new ArrayList<>(); fields.addAll(Arrays.asList(o.getClass().getDeclaredFields())); /** * 如果存在父类,获取父类的属性值,类型,名称并添加到一起 */ Class sc = o.getClass().getSuperclass(); if (sc != null) { fields.addAll(Arrays.asList(sc.getDeclaredFields())); } for (Field field : fields) { Map<String, Object> infoMap = new HashMap<>(); infoMap.put("type", field.getType().toString()); infoMap.put("name", field.getName()); infoMap.put("value", getFieldValueByName(field.getName(), o)); list.add(infoMap); } return list; } }
// 这边比较数据的值 public List<Map<String, Object>> getCompareData(HecYbMedCodeSyncEntity entityHis, HecYbMedCodeSyncEntity entityNow) { List<Map<String, Object>> lists = new ArrayList<>(); List<Map<String, Object>> modelList = Conversion.getFiledInfo(entityHis); List<Map<String, Object>> entityList = Conversion.getFiledInfo(entityNow); modelList.forEach(mapHis -> { entityList.forEach(mapNow -> { Map<String, Object> map = new HashMap<>(); //这边需要把获取得到的字段名 跟 医保中心的字段名做个匹配,把我们这边的字段名转成他们那边的字段名 if ( mapHis.get("name").toString().equals(mapNow.get("name").toString())) {//判断名字相同 if (!(mapHis.get("value").toString().equals(mapNow.get("value").toString())) ) {//判断值不相同 且 反射实体不为空 map.put("bgzdbm", fieldMappedEnum.getSourceFieldName()); //变更字段编码 map.put("bgzdmc", fieldMappedEnum.getDesc()); //变更字段名称 map.put("bgqz00", mapHis.get("value").toString()); //变更前值 map.put("bghz00", mapNow.get("value").toString()); //变更后值 map.put("bgsj00", DateUtil.limitDay(entityNow.getSyncTime())); //变更时间 lists.add(map); } } }); });
我的设计思路是,设计一个枚举,把我数据库的字段A,和webServer接口上的字段对应上B,这样给B赋值的时候就可以通过枚举获取得到A,并且通过A就可以获取到A的值,这样就绕过了人工的给B赋值的繁琐操作。
调用如下:
FieldMappedEnum fieldMappedEnum = FieldMappedEnum.findSourceFieldByTarget(mapHis.get("name").toString()); map.put("bgzdbm", fieldMappedEnum.getSourceFieldName()); //变更字段编码 map.put("bgzdmc", fieldMappedEnum.getDesc()); //变更字段名称 ....
©著作权归作者所有:来自51CTO博客作者it林工的原创作品,如需转载,请注明出处,否则将追究法律责任