1. package com.eip.common.util;
    2. import cn.hutool.core.util.ReflectUtil;
    3. import com.beust.jcommander.internal.Lists;
    4. import com.eip.common.annotation.FieldName;
    5. import com.google.common.collect.Maps;
    6. import com.google.gson.Gson;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.apache.commons.lang.StringUtils;
    9. import org.springframework.jdbc.core.JdbcTemplate;
    10. import javax.persistence.Column;
    11. import java.lang.reflect.Field;
    12. import java.lang.reflect.InvocationTargetException;
    13. import java.lang.reflect.Method;
    14. import java.math.BigDecimal;
    15. import java.text.DecimalFormat;
    16. import java.text.SimpleDateFormat;
    17. import java.util.Arrays;
    18. import java.util.HashMap;
    19. import java.util.List;
    20. import java.util.Map;
    21. import java.util.Objects;
    22. /**
    23. * 反射工具类
    24. *
    25. */
    26. @Slf4j
    27. public class ReflectionUtils extends ReflectUtil {
    28. /**
    29. * 获取Object对象,所有成员变量属性值
    30. */
    31. public static HashMap<String, Object> getObjAttr(Object obj) {
    32. return getObjAttr(null, obj);
    33. }
    34. /**
    35. * 获取Object对象,所有成员变量属性值
    36. */
    37. public static HashMap<String, Object> getObjAttr(String prefix, Object obj) {
    38. if (obj == null) return Maps.newHashMap();
    39. Field[] fields = obj.getClass().getDeclaredFields();
    40. HashMap<String, Object> map = Maps.newHashMap();
    41. int count = 0;
    42. for (Field field : fields) {
    43. // 对于每个属性,获取属性名
    44. String varName = field.getName();
    45. try {
    46. boolean access = field.isAccessible();
    47. if (!access) {
    48. field.setAccessible(true);
    49. }
    50. //反射获取所有成员变量值
    51. Object o = field.get(obj);
    52. if (PublicUtil.isNotEmpty(o)) count++;
    53. if (StringUtils.isNotBlank(prefix)) map.put(prefix + "_" + varName, o);
    54. if (StringUtils.isBlank(prefix)) map.put(varName, o);
    55. if (!access) {
    56. field.setAccessible(false);
    57. }
    58. } catch (Exception ex) {
    59. ex.printStackTrace();
    60. }
    61. }
    62. return count > 0 ? map : null;
    63. }
    64. /**
    65. * 判断该对象是否
    66. * @param obj 返回ture表示所有属性为null返回false表示不是所有属性都是null
    67. * @return
    68. */
    69. public static boolean isAllFieldNull(Object obj) {
    70. boolean flag = true;
    71. try {
    72. Class stuCla = (Class) obj.getClass();//得到类对象
    73. Field[] fs = stuCla.getDeclaredFields();//得到属性集合
    74. for (Field f : fs) {//遍历属性
    75. f.setAccessible(true);//设置属性是可以访问的(私有的也可以)
    76. Object val = f.get(obj);
    77. if (val != null) {//只要有1个属性不为空,那么就不是所有的属性值都为空
    78. flag = false;
    79. break;
    80. }
    81. }
    82. } catch (IllegalAccessException e) {
    83. e.printStackTrace();
    84. }
    85. return flag;
    86. }
    87. /**
    88. * 比较两个类型一样的对象中的值变更返回字符串
    89. *
    90. * @param pre 变化前的对象
    91. * @param last 变化后的对象
    92. * @param fileIds 需要比对的字段 all为全部
    93. * @param orgNum 查询需要机构号时传入
    94. * @return
    95. * @apiNote 配合@FieldName注解一起使用
    96. */
    97. public static String compareObjectDifferentAttributes(Object pre, Object last, String fileIds, Integer orgNum) {
    98. if (StringUtils.isBlank(fileIds)) fileIds = "all";
    99. List<String> fileIdList = Arrays.asList(fileIds.split(","));
    100. StringBuilder result = new StringBuilder();
    101. Class<?> preClass = pre.getClass();
    102. Class<?> lastClass = last.getClass();
    103. if (!preClass.equals(lastClass)) throw new RuntimeException("两个对象类型不一致");
    104. Field[] declaredFields = preClass.getDeclaredFields();
    105. for (Field field : declaredFields) {
    106. //获取方法名
    107. String fieldName = field.getName();
    108. if (!"all".equalsIgnoreCase(fileIds) && !fileIdList.contains(fieldName)) continue;
    109. try {
    110. //没有注解跳过比较
    111. if (!field.isAnnotationPresent(FieldName.class)) continue;
    112. FieldName fieldAnno = field.getAnnotation(FieldName.class);
    113. boolean access = field.isAccessible();
    114. String type = field.getType().getName();
    115. if (!access) field.setAccessible(true);
    116. Object preValue = field.get(pre);
    117. Object lastValue = field.get(last);
    118. if ("".equals(preValue)) preValue = null;
    119. if ("".equals(lastValue)) lastValue = null;
    120. //BigDecimal 类型的数据要去掉小数点后尾部的0不一致造成数据比对差异
    121. if ("java.math.BigDecimal".equals(type) && preValue != null && lastValue != null) {
    122. BigDecimal valOldBig = new BigDecimal(String.valueOf(preValue));
    123. BigDecimal valNewBig = new BigDecimal(String.valueOf(lastValue));
    124. //由于无法获取精度值,只能对所有带小数点的数据进行处理
    125. if (String.valueOf(valOldBig).contains(".") || String.valueOf(valNewBig).contains(".")) {
    126. DecimalFormat formatter1 = new DecimalFormat("0.00");
    127. preValue = formatter1.format(valOldBig);
    128. lastValue = formatter1.format(valNewBig);
    129. }
    130. }
    131. //DATE 类型的数据要格式化
    132. if ("java.util.Date".equals(type)) {
    133. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    134. if (preValue != null) preValue = sdf.format(preValue);
    135. if (lastValue != null) lastValue = sdf.format(lastValue);
    136. }
    137. //如果前后两个值都是空,那么无需比较
    138. if (Objects.isNull(preValue) && Objects.isNull(lastValue)) {
    139. continue;
    140. } else if (Objects.isNull(preValue) && Objects.nonNull(lastValue)) { //前值为空,后值不为空
    141. if (fieldAnno.isForeignKey()) {
    142. lastValue = getForeignKeyName(fieldAnno.sql(), lastValue, fieldAnno.isOrgNum(), orgNum,fieldAnno.isStringParam());
    143. }else if(fieldAnno.isSysKey()){
    144. lastValue = getSysKeyValue(fieldAnno.sysKey() ,lastValue);
    145. }
    146. result.append("'").append(fieldAnno.name()).append("'").append("由'空'变为").append("'").append(lastValue).append("'").append("\r\n");
    147. } else if (Objects.nonNull(preValue) && Objects.isNull(lastValue)) {//前值不为空,后值为空
    148. if (fieldAnno.isForeignKey()) {
    149. preValue = getForeignKeyName(fieldAnno.sql(), preValue, fieldAnno.isOrgNum(), orgNum,fieldAnno.isStringParam());
    150. }else if(fieldAnno.isSysKey()){
    151. preValue = getSysKeyValue(fieldAnno.sysKey() ,preValue);
    152. }
    153. result.append("'").append(fieldAnno.name()).append("'").append("由").append("'").append(preValue).append("'").append("变为'空'").append("\r\n");
    154. } else if (Objects.nonNull(preValue) && Objects.nonNull(lastValue)) { //两个都不为空
    155. if (preValue.equals(lastValue)) continue;
    156. //是否外键
    157. if (fieldAnno.isForeignKey()) {
    158. preValue = getForeignKeyName(fieldAnno.sql(), preValue, fieldAnno.isOrgNum(), orgNum,fieldAnno.isStringParam());
    159. lastValue = getForeignKeyName(fieldAnno.sql(), lastValue, fieldAnno.isOrgNum(), orgNum,fieldAnno.isStringParam());
    160. }else if(fieldAnno.isSysKey()){
    161. preValue = getSysKeyValue(fieldAnno.sysKey() ,preValue);
    162. lastValue = getSysKeyValue(fieldAnno.sysKey() ,lastValue);
    163. }
    164. result.append("'").append(fieldAnno.name()).append("'").append("由").append("'")
    165. .append(preValue).append("'").append("变为").append("'").append(lastValue).append("'").append("\r\n");
    166. }
    167. if (!access) field.setAccessible(false);
    168. } catch (IllegalAccessException e) {
    169. e.printStackTrace();
    170. }
    171. }
    172. return result.toString();
    173. }
    174. /**
    175. * 查询系统定义的值
    176. * @param sysKey
    177. * @param value
    178. * @return
    179. */
    180. @SuppressWarnings("unchecked")
    181. public static String getSysKeyValue(String sysKey ,Object value) {
    182. if(StringUtils.isBlank(sysKey))return value.toString();
    183. try {
    184. Map<String, String> map = Maps.newHashMap();
    185. map = new Gson().fromJson(sysKey, map.getClass());
    186. return map.get(value.toString())==null?value.toString():map.get(value.toString());
    187. } catch (Exception e) {
    188. return value.toString();
    189. }
    190. }
    191. /**
    192. * 查询外键所对应的名称
    193. *
    194. * @param sql
    195. * @param value
    196. * @param isOrgNum
    197. * @return
    198. */
    199. public static String getForeignKeyName(String sql, Object value, boolean isOrgNum, Integer orgNum,boolean isStringParam) {
    200. // Preconditions.checkArgument(StringUtils.isNotBlank(sql), "sql不能为空!");
    201. if (StringUtils.isBlank(sql)) return "";
    202. try {
    203. JdbcTemplate bean = ApplicationContextHolder.getBean(JdbcTemplate.class);
    204. Object[] args ;
    205. if(isStringParam){
    206. args = new Object[]{value.toString()};
    207. }else{
    208. args = new Object[]{Integer.valueOf(value.toString())};
    209. }
    210. if (isOrgNum) {
    211. sql += " and f_org_num = ?";
    212. if(isStringParam){
    213. args = new Object[]{value.toString(), orgNum};
    214. }else{
    215. args = new Object[]{Integer.valueOf(value.toString()), orgNum};
    216. }
    217. }
    218. return bean.queryForObject(sql, args, String.class);
    219. } catch (Exception e) {
    220. return "空";
    221. }
    222. }
    223. /**
    224. * 解析方法注解
    225. *
    226. * @param clazz
    227. */
    228. public static String getAnnotationAttribute(Class<?> clazz, String attributeField) {
    229. for (Field field : clazz.getDeclaredFields()) {
    230. if (field.getName().equalsIgnoreCase(attributeField) && field.isAnnotationPresent(Column.class)) {
    231. Column column = field.getAnnotation(Column.class);
    232. // System.out.println(column.name());
    233. return column.name();
    234. }
    235. }
    236. return null;
    237. }
    238. /**
    239. * 获取字段属性
    240. *
    241. * @param clazz
    242. * @param attributeField
    243. * @return
    244. */
    245. public static String getFieldType(Class<?> clazz, String attributeField) {
    246. for (Field field : clazz.getDeclaredFields()) {
    247. if (field.getName().equalsIgnoreCase(attributeField)) {
    248. return field.getType().toString();
    249. }
    250. }
    251. return null;
    252. }
    253. /**
    254. * 获取字段名称
    255. * @param clazz
    256. * @param ignoreFields
    257. * @return
    258. */
    259. public static String[] getFieldName(Class<?> clazz, String ignoreFields) {
    260. if(ignoreFields==null)ignoreFields="";
    261. List<String> list = Lists.newArrayList();
    262. for (Field field : clazz.getDeclaredFields()) {
    263. if (!ignoreFields.contains(field.getName())) {
    264. list.add(field.getName());
    265. }
    266. }
    267. return list.stream().toArray(String[]::new);
    268. }
    269. /**
    270. * 通过反射实现get方法
    271. * @param o 要操作类的对象
    272. * @param args 属性名
    273. * @param <T>
    274. * @return
    275. * @throws NoSuchFieldException
    276. */
    277. public static <T> T getMethod(T o,String args) throws NoSuchFieldException {
    278. Class cls = o.getClass();
    279. //判断该属性是否存在
    280. Field field = cls.getDeclaredField(args);
    281. if(field == null){
    282. field = cls.getField(args);
    283. }
    284. if(field == null){
    285. return (T)"";
    286. }
    287. String fieldName = "get"+args.substring(0,1).toUpperCase()+(args.length()>1?args.substring(1):"");
    288. Method method;
    289. try {
    290. method = cls.getMethod(fieldName);
    291. //Boolean返回 true是 false否
    292. if(getFieldType(cls,args).equals("class java.lang.Boolean")){
    293. Boolean invoke = (Boolean)method.invoke(o);
    294. return invoke.equals(true) ?(T)"是" :(T)"否";
    295. }
    296. //Date返回 yyyy-MM-dd
    297. else if (getFieldType(cls,args).equals("class java.util.Date")){
    298. if(method.invoke(o)!=null){
    299. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    300. String date = sdf.format(method.invoke(o));
    301. return (T)date;
    302. }
    303. }
    304. return (T)method.invoke(o);
    305. } catch (NoSuchMethodException e) {
    306. log.error(e.getMessage());
    307. } catch (IllegalAccessException e) {
    308. log.error(e.getMessage());
    309. } catch (InvocationTargetException e) {
    310. log.error(e.getMessage());
    311. }
    312. return (T)"";
    313. }
    314. }